PICTools Programmer's Reference
OP_JPIPCLIENT, OP_JPIPSERVER

OP_JPIPCLIENT, OP_JPIPSERVER: JPEG2000 Interactive Protocol

JPIP is a network protocol to be used for interactive and progressive delivery of JPEG2000 images or regions of images from a server to a client. Typically, a client sends requests via HTTP to a server, the server processes the requests and delivers JPEG2000 data to the client, which the client then outputs for further processing by a JPEG20000 decoder and viewer. The client can then make subsequent requests for more detail and/or for other areas of the image.

JPIP distinguishes between two types of requests: stateless requests and requests that belong to a session.  Stateless requests are entirely self-contained. As part of a stateless request, the client sends to the server a snapshot of its cache state so that the server need not resend data the client already has. When operating within a session, the server keeps open a channel to the client and is able to maintain a copy of the client's cache state itself thereby making it unnecessary for the client to upload its cache state with each request. A session connection also allows for the client to send a new request before the current response has been completely received, stop the transmission of the current response, and instead start sending data to satisfy this new request.

Accusoft offers two opcodes, OP_JPIPCLIENT and OP_JPIPSERVER, upon which applications can build JPIP-compliant clients and servers (see request fields here). The opcodes provide and process the JPIP strings that get passed between client and server in a network connection and extract and ingest the JPIP image data passed from server to client. This implementation facilitates HTTP interaction by providing formatted HTTP request and response strings, but does not depend on HTTP protocol to perform the JPIP operations. Therefore, the opcodes also allow the application to create and parse the JPIP strings itself and pass the relevant field values to and from the opcode via fields in the PIC_PARM structure. The opcodes support both stateless and stateful (requests that belong to a session) requests.

Note that, if you are familiar with other PICTools opcodes, these two opcodes operate similarly in most respects.  However they operate slightly differently from most other PICTools opcodes in one important respect: that REQ_EXEC will ordinarily be called multiple times before REQ_TERM is called.

The client application calling the OP_JPIPCLIENT opcode will still call REQ_INIT once for each image for initialization.  However the "operation" phase of using OP_JPIPCLIENT will ordinarily require calling REQ_EXEC multiple times instead of only calling REQ_EXEC once as with most other opcodes.  The client application will call REQ_EXEC each time it needs to construct a request to send to the server.  The client will also call REQ_EXEC each time it receives a response from the server.  The client will also call REQ_EXEC each time it needs to generate another JPEG 2000 output image from the totality of the responses received from the server to that point.  After the client application is finished with the image, it will ordinarily call REQ_TERM once.

In stateless mode, for each request, the server application will ordinarily make this sequence of calls into OP_JPIPSERVER: REQ_INIT, REQ_EXEC to parse and process the client's request, REQ_EXEC to generate the response for the client, then REQ_TERM.  Generally, for the best file input performance, the server application should set the Get queue size to 2048 bytes and support seeking. Alternatively, if the Get queue contains the entire image, then OP_JPIPSERVER will not need any additional input operations.

For stateful mode, the server application will call REQ_INIT one time only, will ordinarily call REQ_EXEC twice for each request - once for parsing and processing each client request and once for generating each response for the client - and then will call REQ_TERM one time only after it has finished with all requests. OP_JPIPSERVER reads in the entire image during REQ_INIT and does not require any further input operations in any of the subsequent REQ_EXEC calls.

OP_JPIPSERVER sets the JPIPServerStatusCode when returning from the call to REQ_EXEC to parse and process the client's request. If OP_JPIPSERVER returns with JPIPServerStatusCode set to JPIP_SSCode_OK (all requested items are okay) or JPIP_SSCode_NotImplemented (one or more requested items is not implemented in the opcode but the remainder of the request is okay), the request was enqueued and the server application calls REQ_EXEC to generate the response. If, instead, OP_JPIPSERVER sets JPIPServerStatusCode to JPIP_SSCode_BadRequest or JPIP_SSCode_ServiceUnavailable, the request was not enqueued and the server application can respond immediately to the client so indicating this.  The server application does not make a subsequent call to REQ_EXEC to generate a response because there will be no data to deliver in response to this request.

To support possibly asynchronous communication between server and client and to support handling new incoming requests at the server before a current response is completed, OP_JPIPSERVER allows multiple and interleaved calls to REQ_EXEC for request input and response output. The server application just needs to be sure to call REQ_EXEC to retrieve a response for each request that has been successfully enqueued. If the server application makes an extraneous call to REQ_EXEC to output a response that does not exist (e.g., the request had not been enqueued), OP_JPIPSERVER returns with EORReasonCode set to JPIP_EOR_None and no new data in the Put queue.

ParmVerMinor must be at least 2 for the OP_JPIPSERVER and OP_JPIPCLIENT opcodes.  As with the OP_J2KE and OP_J2KP JPEG 2000 opcodes, if ParmVerMinor is 3 or greater, then errors or warnings returned from the underlying JPIP technology library optionally return additional descriptive text in PIC2List if there is enough space or if the application reacts to RES_EXTEND_PIC2LIST responses.  In that case, ERR_PIC2LIST_HAS_DESCRIPTION is returned in Status and the information about the error appears in P2PktErrorText packets with Type P2P_ErrorText.  See include\pic2file.h and the PIC2List section of Accessing Comments and Other Auxiliary Data in the PICTools and AIMTools Programmer's Guide for more information about PIC2List packets.

As with other PICTools opcodes, OP_JPIPCLIENT and OP_JPIPSERVER may return non-fatal warning status codes in the Status field in PIC_PARM.  A fatal error is signaled when RES_ERR is returned from Pegasus and then Status has an error code providing additional information about the fatal error.  In all other circumstances where Status has a value different from ERR_NONE, the opcode is reporting a non-fatal warning or error status and the value in Status provides additional information according to the names defined in the PICTools include file errors.h.

OP_JPIPSERVER will attempt to provide properly formatted JPIP responses even when the input data had been improperly encoded, or ends prematurely, or is corrupted. The server application needs to check the return code from Pegasus and the Status to determine the severity of any input image problems. If OP_JPIPSERVER returns a warning status when it otherwise indicates it was able to enqueue the request and then generate a response, the response data is JPIP compliant and will form a valid JPEG2000 image in the client but it may differ from the original input image. For example, an improperly formatted header will be caught and corrected by OP_JPIPSERVER so that the client will see only the correct header. For the case of a truncated input image, if there is sufficient meaningful data, OP_JPIPSERVER will generate the best possible response using that data and return a warning status, such as ERR_UNEXPECTED_EOF. The JPIP response itself will not indicate that there may be something wrong with the image; it is the responsibility of the server application to convey this to the client in the communication between server and client.

OP_JPIPSERVER and OP_JPIPCLIENT Usage Overview

The typical high-level sequence of events for using the opcodes and communicating between client and server proceeds as follows (this example uses HTTP protocol, but other communications protocols could be used):

  1. A user at the client wishes to view a JPEG2000 image available on a remote server.
  2. The client app calls REQ_INIT to initialize the opcode.
  3. The client app sets Action = JPIP_Action_Create_Request and calls REQ_EXEC to create a JPIPRequestString.
  4. The client app establishes an HTTP connection to the server app using the GET or POST method. The URL in the HTTP request identifies the name of the JPEG2000 image to be delivered and the JPIPRequestString created by the client opcode is included in the query string part of the HTTP request.
  5. The server app receives the HTTP request and recognizes it to be requesting JPIP services.
  6. The server app calls REQ_INIT to initialize the opcode.  The requested JPEG2000 image is input to the Get queue. The query string is extracted from the HTTP request and input to the opcode via the JPIPRequestString pointer field to be used by the opcode for initialization processing only.
  7. The server opcode determines whether the request is stateless or stateful and indicates which to the server app.
  8. The server app sets Action = JPIP_Action_Input_Request and calls REQ_EXEC to input the request to the opcode for detailed processing.
  9. The server app sets Action = JPIP_Action_Output_Response and calls REQ_EXEC to get from the opcode the JPIP headers and JPIP body that it needs to send back to the client to satisfy its request.  The JPIP headers are returned in the JPIPResponseString and the JPIP body is output via the Put queue.
  10. The server constructs the HTTP response using the JPIPResponseString to formulate the HTTP header. The Put queue contents are sent as HTTP body and chunked according to HTTP rules.
  11. If the request was stateless and after all data has been delivered, the server app calls REQ_TERM and waits for the next request to arrive. When it does, the server app repeats the sequence of server opcode calls starting with REQ_INIT. If the request was stateful, the server app just waits for the next request. When it arrives, the server app repeats the sequence of server opcode calls starting from REQ_EXEC with Action = JPIP_Action_Input_Request.
  12. The client opcode receives the HTTP response.
  13. The client opcode sets Action = JPIP_Action_Input_Response and calls REQ_EXEC to input the server's response for processing. The complete HTTP header is input as the JPIPResponseString and the HTTP body data is input via the Get queue.
  14. After all JPIP data has been input to the client opcode and REQ_EXEC returns, the client opcode sets Action = JPIP_Action_Output_Bitstream and calls REQ_EXEC to output the delivered JPEG2000 image bits via the Put queue.
  15. The client app directs the bitstream into a JPEG2000 decoder and then displays the reconstructed image for the user.
  16. If the user wishes to view further details of the image or another region of the image or another image, then another request must be made and sent to server. The client app repeats the sequence of client opcode calls starting from REQ_EXEC with Action = JPIP_Action_Create_Request.

A client makes a JPIP view window request by setting these parameters:

A suggested way to set the JPIP view window parameters is as follows:

  1. Set ViewWindowFrameWidth and ViewWindowFrameHeight to the width and height of the user's display window; these parameters define the requested frame size.  The server will try to find the best fit to these dimensions and then will deliver those bits of the requested JPEG2000 image that would reconstruct the image scaled to a size that it found to be the best match to the requested frame size and at the best quality for that size. The actual dimensions are a function of how the image was encoded and may or may not exactly match the requested ViewWindowFrameWidth and ViewWindowFrameHeight. The client instructs the server how to find the best match to the requested frame size by setting the ViewWindowFrameRoundDirection; it can be set to round-up, round-down, or closest. Set to round-up if the client can accept larger dimensions than requested. This may mean that more compressed data must be transmitted.  Set to round-down if the client prefers the server reduce the dimensions if necessary. This may mean that less compressed data must be transmitted, but it may result in lower perceived quality if the image will be viewed at a size larger than the rounded-down frame size.  Set to closest to instruct the server to find the closest match according to overall size.  The individual matching dimensions may then be larger or smaller than the request.
  2. Within the requested frame, choose a region of interest and set ViewWindowRegionWidth and ViewWindowRegionHeight to the dimensions of that region of interest and set ViewWindowRegionOffsetX and ViewWindowRegionOffsetY to the horizontal and vertical offsets, respectively, of the upper left corner of the region of interest from the upper left corner of the frame. The sum of ViewWindowRegionOffsetX plus ViewWindowRegionWidth should be less than or equal to ViewWindowFrameWidth; the sum of ViewWindowRegionOffsetY plus ViewWindowRegionHeight should be less than or equal to ViewWindowFrameHeight.  ViewWindowRegionWidth, ViewWindowRegionHeight, ViewWindowRegionOffsetX, and ViewWindowRegionOffsetY can all be omitted if the region of interest is the entire frame, in which case the server delivers the entire image scaled to the frame size the server found.
  3. Set ViewWindowMinComponent and ViewWindowMaxComponent to the minimum and maximum component indices desired or omit these fields to request all components in the image. Use these fields only if the application doesn't require all components of the JPEG2000 image.
  4. Set ViewWindowLayers to request a reduced number of quality layers or omit this field to have all available layers delivered. Use this field to speed up delivery at the expense of reduced quality.
  5. The server will find the best match to the requested frame size.  The server will return these best matching frame width and frame height values to the client if the match is different from the client's request. The server will then scale the requested region size and offsets so that they identify the same region of the image within the matching frame size as they did within the requested frame size. The server returns to the client the scaled region size and offsets if those values now differ from the client's request.
  6. The JPEG2000 bits returned by the server describe an image that may have total dimensions larger than the returned frame width and frame height. For best quality viewing, decode those bits to the thumbnail whose size matches the returned frame width and frame height and display in a window of that size. If the region of interest is smaller than the full image, then the image areas surrounding the region of interest may appear less sharp than the region of interest appears. To display just the region of interest, crop the thumbnail when decompressing according to the returned region dimensions and offsets and display in a window of those dimensions. Alternatively, the thumbnail or its region of interest can be displayed in a window of smaller or larger size by resizing it to the display window size.

As an example, consider a JPEG2000 image whose ImageWidth = 768 and whose ImageHeight = 512 and that was encoded using five decomposition levels. The dimensions of each of the resolutions available within the image are:

    768 x 512

    384 x 256

    192 x 128

     96  x  64

     48  x  32

     24  x  16

If the client sets ViewWindowFrameWidth and ViewWindowFrameHeight to one of these dimensions, then the server will find an exact match and return the compressed bits that reconstruct up to that resolution level.  The client will add additional data if needed so the client's JPIP_Action_Output_Bitstream image is always a valid JPEG2000 image of size 768 x 512.  If the client sets ViewWindowFrameWidth and ViewWindowFrameHeight to values that do not exactly match any of the dimensions in the list, then the server will use the ViewWindowFrameRoundDirection to find a match from the list. For example, if the client's requested frame size is 144 x 96 and round direction is round-up, then the server will choose the matching frame size to be 192 x 128.  If round-down, then it will choose 96 x 64.

Now suppose requested frame size is 144 x 96, round direction is round-up, region size is 64 x 64, and region offset is 40,16. The client is requesting a square region of interest centered in a frame of size 144 x 96. The server finds a match and does the appropriate scaling to deliver compressed bits that satisfy frame size 192 x 128, region size 86 x 86, and offsets 53,21 which is a square region of interest centered in a frame of size 192 x 128. The client could decode the resulting JPEG2000 image to reconstruct a fuzzy image of size 768 x 512, but for best quality the client would decode to a thumbnail of size 192 x 128 and would then display that thumbnail in a window of the thumbnail's size.

Sample Usage Scenarios:

Simplest Case - A JPIP System providing progressively improved quality of the entire image.

In this case the client application will request a series of fixed sized data buffers from the server using stateless requests. These buffers will be used by the JPEG2000 decoder to create full size images with increasing detail over the full area of the image.

  1. The client application calls OP_JPIPCLIENT REQ_INIT and REQ_EXEC with a Target consisting of the filename on the server and the size of the buffers to receive in the JPIPServerResponseMaxLength field. The size set in JPIPServerResponseMaxLength will affect how the delivered quality is progressively improved.  For example, earlier responses will require less delivered data for the same perceived quality improvement than later responses.  The later responses may usefully have a larger size to reduce the number of responses needed.  The best size may also be affected by the network throughput so the selected response size can be transmitted in a short enough time that the client application can appear responsive enough to the user.  The application sets the JPIPStringFlags JSF_TARGET and JSF_MAX_LENGTH.  The application sets Action to JPIP_Action_Create_Request.
  2. In this simple case, to force the server to provide image data on the initial request, ViewWindowFrameWdith and ViewWindowFrameHeight are both set by the client application to values larger than the application would reasonably expect the Target image's width and height to be such as (DWORD)-1. The corresponding JSF_FRAME_SIZE flag is set.
  3. The opcode OP_JPIPCLIENT responds with RES_DONE and the JPIPRequestString formatted to make the request.
  4. The client application transmits the JPIPRequestString to the server.
  5. The server application provides the received data to the OP_JPIPSERVER union member JPIPRequestString, sets the Action to JPIP_Action_Input_Request and performs REQ_INIT and REQ_EXEC.
  6. The opcode OP_JPIPSERVER responds with RES_DONE setting the Target and JPIPServerResponseMaxLength fields and the JPIPStringFlags field with JSF_TARGET, JSF_FRAME_SIZE, and JSF_MAX_LENGTH flags set.
  7. The server application uses the Target value to determine the image data requested and makes it available to the opcode in the Get buffer. The server application allocates a Put buffer at least three bytes larger than the JPIPResponseMaxLength value and sets the Put buffer pointers appropriately (empty queue with Put.Front and Put.Rear both set to Put.Start).
  8. The server application sets Action to JPIP_Action_Ouput_Response, sets JPIPServerBlocksize to (DWORD)-1 (i.e., don't return until the entire response has been output) and performs REQ_EXEC.
  9. The opcode OP_JPIPSERVER responds with RES_DONE and JPIP data in the Put buffer. The EORReasonCode (End Of Response) field will contain JPIP_EOR_ByteLimitReached or JPIP_EOR_ImageDone. The EORReasonCode will also be included in the response output data in the Put queue.
  10. The server application transmits both the JPIPResponse string and the contents of the Put buffer to the client application.
  11. The server application performs REQ_TERM and frees application resources.
  12. The client application sets the OP_JPIPCLIENT JPIPResponseString to the server-provided JPIPResponseString and inputs the JPIP data to its Get buffer. The client application allocates a Put buffer to hold the full size compressed JPEG2000 image. The client application sets the OP_JPIPCLIENT Action to JPIP_Action_Input_Output and performs REQ_EXEC.
  13. The OP_JPIPCLIENT responds with RES_DONE and fills the Put Buffer with JPEG2000 compressed image data. The OP_JPIPCLIENT EORReasonCode will be set to the value set by the server, JSF_FRAME_SIZE will be set and ViewWindowFrameWidth and ViewWindowFrameHeight will be set to the actual dimensions of the Target image.
  14. The client application performs JPEG2000 decompression on the Put buffer to create a decompressed version of the image at the currently received quality.
  15. The client application repeats the REQ_EXEC with Action set to JPIP_Action_Create_Request with the now known ViewWindowFrameWidth and ViewWindowFrameHeight and sets JSF_FRAME_SIZE.
  16. The client OP_JPIPCLIENT provides a new JPIPRequestString to the client application to be transmitted to the server application.
  17. The server application repeats the entire REQ_INIT, REQ_EXEC with Action set to JPIP_Action_Input_Response, followed by REQ_EXEC with Action set to JPIP_Action_Output_Response, and REQ_TERM. The server again transmits the JPIPResponseString and JPIP data to the client.
  18. The client application repeats requesting, receiving, and decompressing data until receiving an EORReasonCode of JPIP_EOR_ImageDone.
  19. The client application performs REQ_TERM on OP_JPIPCLIENT.

 

Increasing Complexity - A JPIP System providing a reduced size view of the entire image.

In this case the client application will be viewing the entire image at a reduced size and will again be using stateless requests.  For example the entire image might be too large to be viewed at the current screen resolution and the client application might know it will shrink the image to a size that can be viewed.  A JPEG 2000 image, by virtue of the wavelet decomposition levels or resolutions that are contained in the compressed data, in effect contains different-sized versions of the image, from full size, to 1/2 area size (half-width and half-height), to 1/16th area size (quarter-width and quarter-height), and so on.  The JPIP protocol is designed to take advantage of this property of JPEG 2000 images in order to transit less compressed image data when the client knows the viewed image size will be smaller than the full image size.

Basically, compared to the previous scenario, the client application sets ViewWindowFrame* fields to the viewing dimensions for the image.  The server will select one of the available image sizes and return the selected dimensions to the client.  The client application may decompress directly to the corresponding thumbnail size if easiest and for best performance.  The client application might then separately enlarge or shrink to the desired size for viewing.

Referring to the simplest case scenario above for progressively improved quality, only a few steps are changed.  Then the received image quality is still progressively improved as more responses are received, but the server is able to reduce the amount of compressed data transmitted to the client by taking advantage of knowing that the client will shrink the image for viewing.

  1. The client application calls OP_JPIPCLIENT REQ_INIT and REQ_EXEC with a Target consisting of the filename on the server and the size of the buffers to receive in the JPIPServerResponseMaxLength field. The size set in JPIPServerResponseMaxLength will affect how the delivered quality is progressively improved.  For example, earlier responses will require less delivered data for the same perceived quality improvement than later responses.  The later responses may usefully have a larger size to reduce the number of responses needed.  The best size may also be affected by the network throughput so the selected response size can be transmitted in a short enough time that the client application can appear responsive enough to the user.  The application sets the JPIPStringFlags JSF_TARGET and JSF_MAX_LENGTH.  The application sets Action to JPIP_Action_Create_Request.
  2. ViewWindowFrameWdith and ViewWindowFrameHeight are set by the client application to the smaller viewing size the client intends to use.  The client application sets JSF_FRAME_SIZE.  The server can only return the compressed data for one of the different-sized versions actually contained in the requested JPEG 2000 image, but it won't have to transmit the compressed data for any of the versions if larger than the selected size.  The client may instruct the server about how to select one of the available sizes by setting ViewWindowFrameRoundDirection.
  3. The opcode OP_JPIPCLIENT responds with RES_DONE and the JPIPRequestString formatted to make the request.
  4. The client application transmits the JPIPRequestString to the server.
  5. The server application provides the received data to the OP_JPIPSERVER union member JPIPRequestString, sets the Action to JPIP_Action_Input_Request and performs REQ_INIT and REQ_EXEC.
  6. The opcode OP_JPIPSERVER responds with RES_DONE setting the Target and JPIPServerResponseMaxLength fields and the JPIPStringFlags field with JSF_TARGET, JSF_FRAME_SIZE, and JSF_MAX_LENGTH flags set.
  7. The server application uses the Target value to determine the image data requested and makes it available to the opcode in the Get buffer. The server application allocates a Put buffer at least three bytes larger than the JPIPResponseMaxLength value and sets the Put buffer pointers appropriately (empty queue with Put.Front and Put.Rear both set to Put.Start).
  8. The server application sets Action to JPIP_Action_Ouput_Response, sets JPIPServerBlocksize to (DWORD)-1 (i.e., don't return until the entire response has been output) and performs REQ_EXEC.
  9. The opcode OP_JPIPSERVER responds with RES_DONE and JPIP data in the Put buffer. The EORReasonCode (End Of Response) field will contain JPIP_EOR_ByteLimitReached or JPIP_EOR_ImageDone. The EORReasonCode will also be included in the response output data in the Put queue.
  10. The server application transmits both the JPIPResponse string and the contents of the Put buffer to the client application.
  11. The server application performs REQ_TERM and frees application resources.
  12. The client application sets the OP_JPIPCLIENT JPIPResponseString to the server-provided JPIPResponseString and inputs the JPIP data to its Get buffer. The client application allocates a Put buffer to hold the full size compressed JPEG2000 image. The client application sets the OP_JPIPCLIENT Action to JPIP_Action_Input_Output and performs REQ_EXEC.
  13. The OP_JPIPCLIENT responds with RES_DONE and fills the Put Buffer with JPEG2000 compressed image data. The OP_JPIPCLIENT EORReasonCode will be set to the value set by the server.  If the server selected a different frame size than the client application requested, then JSF_FRAME_SIZE will be set and ViewWindowFrameWidth and ViewWindowFrameHeight will be set to the actual dimensions of the image size that was selected by the server.
  14. The client application performs JPEG2000 decompression on the contents of the Put buffer to create a decompressed version of the image at the currently received quality.  For the fastest decompression speed, the client may decompress to an image thumbnail size that matches the ViewWindowFrameWidth and ViewWindowFrameHeight returned by the server.  Then, as a separate step after decompression, the client application may choose to enlarge or shrink the image as needed from the decompressed thumbnail size in order to achieve the desired viewing size. Alternatively, the client application may choose to view the image directly at the thumbnail size without additional enlarging or shrinking.
  15. The client application repeats the REQ_EXEC with Action set to JPIP_Action_Create_Request with the now known ViewWindowFrameWidth and ViewWindowFrameHeight and sets JSF_FRAME_SIZE.
  16. The client OP_JPIPCLIENT provides a new JPIPRequestString to the client application to be transmitted to the server application.
  17. The server application repeats the entire REQ_INIT, REQ_EXEC with Action set to JPIP_Action_Input_Response, followed by REQ_EXEC with Action set to JPIP_Action_Output_Response, and REQ_TERM. The server again transmits the JPIPResponseString and JPIP data to the client.
  18. The client application repeats requesting, receiving and decompressing data until receiving an EORReasonCode of JPIP_EOR_WindowDone or JPIP_EOR_ImageDone.
  19. The client application performs REQ_TERM on OP_JPIPCLIENT.

 

Increasing Complexity - A JPIP System adding client interaction to provide Region-Of-Interest viewing.

In this case the client application will be viewing only a subrectangle of the image or the client application is more interested in a specific image subrectangle or an image subrectangle is more important in some way.  For example, a client viewer application might scroll a window over the image where the window is not large enough to view the entire image.  Or a client viewer might want an important subrectangle delivered faster and at better quality than other regions of the image.  These requirements might be combined with viewing at reduced size and viewing at progressively improved quality.  The JPIP protocol takes advantage of the JPEG2000 image format so that the only compressed data transmitted is that data needed for the full quality subrectangle and any other compressed data not needed for the subrectangle doesn't have to be transmitted.

Basically, compared to the previous scenarios, the client application sets ViewWindowRegion* fields to the requested subrectangle.  The server will adjust the requested subrectangle if it adjusts the frame size so that the adjusted subrectangle describes the same relative region of the new frame as the client had requested relative to the old frame.  The client application might then crop to the subrectangle during decompression if easiest or for best performance.

As compared to the two scenarios above only a few steps are changed.  The received image quality is still progressively improved as more responses are received, but the server is still able to reduce the amount of compressed data transmitted to the client by taking advantage of knowing whether the client will shrink the image for viewing as well as, in this scenario, knowing whether the client only requires a subrectangle of the image at full quality. The client is making stateless requests.

  1. The client application calls OP_JPIPCLIENT REQ_INIT and REQ_EXEC with a Target consisting of the filename on the server and the size of the buffers to receive in the JPIPServerResponseMaxLength field. The size set in JPIPServerResponseMaxLength will affect how the delivered quality is progressively improved.  For example, earlier responses will require less delivered data for the same perceived quality improvement than later responses.  The later responses may usefully have a larger size to reduce the number of responses needed.  The best size may also be affected by the network throughput so the selected response size can be transmitted in a short enough time that the client application can appear responsive enough to the user.  The application sets the JPIPStringFlags JSF_TARGET and JSF_MAX_LENGTH.  The application sets Action to JPIP_Action_Create_Request.
  2. ViewWindowFrameWidth and ViewWindowFrameHeight are set by the client application to whatever viewing size the client intends to use, or impossibly large like (DWORD)-1 if the client knows it wants the image at full size.  The client application sets JSF_FRAME_SIZE.  The client may instruct the server about how to select one of the available sizes by setting ViewWindowFrameRoundDirection.  The client application also sets ViewWindowRegionOffsetX, ViewWindowRegionOffsetY, ViewWindowRegionWidth, and ViewWindowRegionHeight to the desired subrectangle.  The client application sets JSF_REGION_OFFSET and JSF_REGION_SIZE.  The coordinates to be used for the ViewWindowRegion fields are coordinates in the ViewWindowFrameWidth by ViewWindowFrameHeight frame.  So if the client application wanted to explicitly specify the entire image, it would set ViewWindowRegionOffsetX and ViewWindowRegionOffsetY both to 0 and it would set ViewWindowRegionWidth and ViewWindowRegionHeight to ViewWindowFrameWidth and ViewWindowFrameHeight, respectively.
  3. The opcode OP_JPIPCLIENT responds with RES_DONE and the JPIPRequestString formatted to make the request.
  4. The client application transmits the JPIPRequestString to the server.
  5. The server application provides the received data to the OP_JPIPSERVER union member JPIPRequestString, sets the Action to JPIP_Action_Input_Request and performs REQ_INIT and REQ_EXEC.
  6. The opcode OP_JPIPSERVER responds with RES_DONE setting the Target and JPIPServerResponseMaxLength fields and the JPIPStringFlags field with JSF_TARGET, JSF_FRAME_SIZE, JSF_REGION_OFFSET, JSF_REGION_SIZE, and JSF_MAX_LENGTH flags set.
  7. The server application uses the Target value to determine the image data requested and makes it available to the opcode in the Get buffer. The server application allocates a Put buffer at least three bytes larger than the JPIPResponseMaxLength value and sets the Put buffer pointers appropriately (empty queue with Put.Front and Put.Rear both set to Put.Start).
  8. The server application sets Action to JPIP_Action_Ouput_Response, sets JPIPServerBlocksize to (DWORD)-1 (i.e., don't return until the entire response has been output) and performs REQ_EXEC.
  9. The opcode OP_JPIPSERVER responds with RES_DONE and JPIP data in the Put buffer. The EORReasonCode (End Of Response) field will contain JPIP_EOR_ByteLimitReached or JPIP_EOR_ImageDone. The EORReasonCode will also be included in the response output data in the Put queue.
  10. The server application transmits both the JPIPResponse string and the contents of the Put buffer to the client application.
  11. The server application performs REQ_TERM and frees application resources.
  12. The client application sets the OP_JPIPCLIENT JPIPResponseString to the server-provided JPIPResponseString and inputs the JPIP data to its Get buffer. The client application allocates a Put buffer to hold the full size compressed JPEG2000 image. The client application sets the OP_JPIPCLIENT Action to JPIP_Action_Input_Output and performs REQ_EXEC.
  13. The OP_JPIPCLIENT responds with RES_DONE and fills the Put Buffer with JPEG2000 compressed image data. The OP_JPIPCLIENT EORReasonCode will be set to the value set by the server.  If the server selected a different frame size than the client application requested, then JSF_FRAME_SIZE will be set and ViewWindowFrameWidth and ViewWindowFrameHeight will be set to the actual dimensions of the Target image size that was selected by the server.   In that case, JSF_REGION_OFFSET and JSF_REGION_SIZE will also be set and ViewWindowRegionOffsetX, ViewWindowRegionOffsetY, ViewWindowRegionWidth, and ViewWindowRegionHeight will be returned as they were adjusted by the server.  The server adjusts the ViewWindowRegion values so they represent the same subrectangle in the returned ViewWindowFrame as the corresponding client's requested subrectangle represented in the client's requested ViewWindowFrame.
  14. The client application performs JPEG2000 decompression on the contents of the Put buffer to create a decompressed version of the image at the currently received quality.  For the fastest decompression speed, decompress to the image thumbnail size that matches the ViewWindowFrameWidth and ViewWindowFrameHeight returned by the server.  If the client is only viewing a requested subrectangle, then it may be easiest and decompression will usually be faster to crop to the returned ViewWindowRegion subrectangle as part of decompression.  Then, as a separate step after decompression, the client application may choose to enlarge or shrink the image as needed from the decompressed thumbnail size in order to achieve the desired viewing size. Alternatively, the client application may choose to view the image directly at the thumbnail size without enlarging or shrinking.
  15. The client application repeats the REQ_EXEC with Action set to JPIP_Action_Create_Request with the now known ViewWindowFrameWidth and ViewWindowFrameHeight and sets JSF_FRAME_SIZE.  The client application also sets the ViewWindowRegion values and sets JSF_REGION_OFFSET and JSF_REGION_SIZE before calling REQ_EXEC.
  16. The client OP_JPIPCLIENT provides a new JPIPRequestString to the client application to be transmitted to the server application.
  17. The server application repeats the entire REQ_INIT, REQ_EXEC with Action set to JPIP_Action_Input_Response, followed by REQ_EXEC with Action set to JPIP_Action_Output_Response, and REQ_TERM. The server again transmits the JPIPResponseString and JPIP data to the client.
  18. The client application repeats requesting, receiving and decompressing data until receiving an EORReasonCode of JPIP_EOR_WindowDone or JPIP_EOR_ImageDone.
  19. The client application performs REQ_TERM on OP_JPIPCLIENT.

 

Session Support - A JPIP System that maintains the connection and server state between requests.

When a JPIP client and server maintain their connection between requests, then the JPIP protocol can operate in stateful mode instead of in the stateless mode of the above scenarios.  There are advantages and disadvantages to doing this depending on the JPIP system.

In stateless mode, the client has to connect to a server, send its request, receive the server's response, and disconnect from the server.  From the server's perspective, each of these requests is an independent request and the server can't know whether the same instance of the same client application made earlier requests for the same image and already received some image data.  So in order that the server doesn't send compressed data in its response that the client had already received in earlier responses to requests for the same image, as part of its request the client has to tell the server about all the compressed data for the image that the client has received so far.  Depending on the image, it may take a few extra kilobytes of memory for the client to send this information - the cache model - to the server.  In some applications, over some physical connections, these few extra kilobytes might matter.  Being able to avoid sending this extra data from client to server is ordinarily the biggest advantage of stateful mode.

In stateful mode, the same instance of the server application on the same host will stay active to serve all requests of the client.  The server will keep track of all the image information it has already sent to the client so the server doesn't send that same information redundantly.  Keeping track of this information means the server application uses extra memory and stays active during the entire session with the client.  This is a disadvantage in some applications compared to stateless mode. 

Basically, compared to the previous scenarios, in order to use stateful mode the client application requests a new channel from the server as part of its first request.  The server sets one or more allowed channel transports before inputting the client's first request.  The server returns a granted channel id that the client uses as channel id in future requests in the session.  The server doesn't call REQ_TERM after each response, but only after the entire session.

Referring to the scenarios above, only a few steps are changed and then all the scenario features above still apply, but in stateful mode instead of stateless mode.

  1. The client application calls OP_JPIPCLIENT REQ_INIT and REQ_EXEC with a Target consisting of the filename on the server and the size of the buffers to receive in the JPIPServerResponseMaxLength field. The size set in JPIPServerResponseMaxLength will affect how the delivered quality is progressively improved.  For example, earlier responses will require less delivered data for the same perceived quality improvement than later responses.  The later responses may usefully have a larger size to reduce the number of responses needed.  The best size may also be affected by the network throughput so the selected response size can be transmitted in a short enough time that the client application can appear responsive enough to the user.  The application sets the JPIPStringFlags JSF_TARGET and JSF_MAX_LENGTH.  The client application sets JSF_CHANNEL_NEW.  The application sets Action to JPIP_Action_Create_Request.
  2. ViewWindowFrameWidth and ViewWindowFrameHeight are set by the client application to whatever viewing size the client intends to use, or impossibly large like (DWORD)-1 if the client knows it wants the image at full size.  The client application sets JSF_FRAME_SIZE.  The client may instruct the server about how to select one of the available sizes by setting ViewWindowFrameRoundDirection.  The client application also sets ViewWindowRegionOffsetX, ViewWindowRegionOffsetY, ViewWindowRegionWidth, and ViewWindowRegionHeight to the desired subrectangle.  The client application sets JSF_REGION_OFFSET and JSF_REGION_SIZE.  The coordinates to be used for the ViewWindowRegion fields are coordinates in the ViewWindowFrameWidth by ViewWindowFrameHeight frame.  So if the client application wanted to explicitly specify the entire image, it would set ViewWindowRegionOffsetX and ViewWindowRegionOffsetY both to 0 and it would set ViewWindowRegionWidth and ViewWindowRegionHeight to ViewWindowFrameWidth and ViewWindowFrameHeight, respectively.
  3. The opcode OP_JPIPCLIENT responds with RES_DONE and the JPIPRequestString formatted to make the request.
  4. The client application transmits the JPIPRequestString to the server.
  5. The server application provides the received data to the OP_JPIPSERVER union member JPIPRequestString.  The server application sets one or more of the JCF_* flags in AllowedJPIPChannelTransportsFlags, for example JCF_HTTP.  When none of these flags is set, a client request for a channel - i.e., for stateful mode in this case - will not be granted by the server.  The server application sets the Action to JPIP_Action_Input_Request and performs REQ_INIT and REQ_EXEC.
  6. The opcode OP_JPIPSERVER responds with RES_DONE setting the Target and JPIPServerResponseMaxLength fields and the JPIPStringFlags field with JSF_CHANNEL_NEW, JSF_TARGET, JSF_FRAME_SIZE, JSF_REGION_OFFSET, JSF_REGION_SIZE, and JSF_MAX_LENGTH flags set.
  7. The server application uses the Target value to determine the image data requested and makes it available to the opcode in the Get buffer. The server application allocates a Put buffer at least three bytes larger than the JPIPResponseMaxLength value and sets the Put buffer pointers appropriately (empty queue with Put.Front and Put.Rear both set to Put.Start).
  8. The server application sets JSF_CHANNEL_ID to return a channel ID to the client allowing stateful mode and sets Action to JPIP_Action_Ouput_Response, sets JPIPServerBlocksize to (DWORD)‑1 (i.e., don't return until the entire response has been output) and performs REQ_EXEC.
  9. The opcode OP_JPIPSERVER responds with RES_DONE and JPIP data in the Put buffer. The EORReasonCode (End Of Response) field will contain JPIP_EOR_ByteLimitReached or JPIP_EOR_ImageDone. The EORReasonCode will also be included in the response output data in the Put queue.
  10. The server application transmits both the JPIPResponse string and the contents of the Put buffer to the client application.
  11. (Removed as compared to previous scenarios.)
  12. The client application sets the OP_JPIPCLIENT JPIPResponseString to the server-provided JPIPResponseString and inputs the JPIP data to its Get buffer. The client application allocates a Put buffer to hold the full size compressed JPEG2000 image. The client application sets the OP_JPIPCLIENT Action to JPIP_Action_Input_Output and performs REQ_EXEC.
  13. The OP_JPIPCLIENT responds with RES_DONE and fills the Put Buffer with JPEG2000 compressed image data. The OP_JPIPCLIENT EORReasonCode will be set to the value set by the server.  If the server selected a different frame size than the client application requested, then JSF_FRAME_SIZE will be set and ViewWindowFrameWidth and ViewWindowFrameHeight will be set to the actual dimensions of the Target image size that was selected by the server.   In that case, JSF_REGION_OFFSET and JSF_REGION_SIZE will also be set and ViewWindowRegionOffsetX, ViewWindowRegionOffsetY, ViewWindowRegionWidth, and ViewWindowRegionHeight will be returned as they were adjusted by the server.  The server adjusts the ViewWindowRegion values so they represent the same subrectangle in the returned ViewWindowFrame as the corresponding client's requested subrectangle represented in the client's requested ViewWindowFrame.
  14. The client application performs JPEG2000 decompression on the contents of the Put buffer to create a decompressed version of the image at the currently received quality.  For the fastest decompression speed, decompress to the image thumbnail size that matches the ViewWindowFrameWidth and ViewWindowFrameHeight returned by the server.  If the client is only viewing a requested subrectangle, then it may be easiest and decompression will usually be faster to decompress cropping to the returned ViewWindowRegion subrectangle.  Then, as a separate step after decompression, the client application may choose to enlarge or shrink the image as needed from the decompressed thumbnail size in order to achieve the desired viewing size   Alternatively, the client application may choose to view the image directly at the thumbnail size without enlarging or shrinking.
  15. The client application repeats the REQ_EXEC with Action set to JPIP_Action_Create_Request with the now known ViewWindowFrameWidth and ViewWindowFrameHeight and sets JSF_FRAME_SIZE.  The client application also sets the ViewWindowRegion values and sets JSF_REGION_OFFSET and JSF_REGION_SIZE.  The client also sets JSF_CHANNEL_ID and sets JPIPChannelID to JPIPGrantedChannelID which has the ChannelID that the server returned.
  16. The client OP_JPIPCLIENT provides a new JPIPRequestString to the client application to be transmitted to the server application.
  17. The server application repeats the entire REQ_INIT, REQ_EXEC with Action set to JPIP_Action_Input_Response, followed by REQ_EXEC with Action set to JPIP_Action_Output_Response. The server again transmits the JPIPResponseString and JPIP data to the client.
  18. The client application repeats requesting, receiving and decompressing data until receiving an EORReasonCode of JPIP_EOR_WindowDone or JPIP_EOR_ImageDone.
  19. The client application performs REQ_TERM on OP_JPIPCLIENT.
  20. (Inserted as compared to previous scenarios.)  The server application performs REQ_TERM and frees application resources.

 

 

 

 


©2022. Accusoft Corporation. All Rights Reserved.

Send Feedback