OP_S2D, OP_SE2D, OP_SE2DPLUS: Expand sequential JPEG to DIB or RAW
|
This opcode contains optimizations specific to Pentium 3 / 4 processors that may need to be disabled using the PF2_P3OptDisable flag. See the section entitled "Intel P 3 / 4 Specific Notes". |
See the DIB_OUTPUT: OP_S2D section for additional information.
- OP_S2D provides baseline JPEG decompression.
- OP_SE2D adds support for the decompression of images compressed using the Accusoft enhanced coding algorithm (known as the ELS coder).
- OP_SEDPLUS adds support for grayscale data up to 12bpp inclusive and the ability to decompress cosited color 4-2-2 (= 2-1-1) subsampled JPEG data.
DICOM YBR_FULL_422 Output from Color JPEG Image Input
To decompress a color JPEG input image to a YBR_FULL_422 decompressed output image:
- In J2D.PicFlags2 set PF2_Cosited.
- In J2D.PicFlags2 set PF2_SmoothUpsample.
- Set J2D.YuvOutputType to BI_YUY2 or BI_UYVY
- Set DibSize to 16.
DICOM YBR_PARTIAL_422 Output From Color JPEG Image Input
To decompress a color JPEG input image to a YBR_FULL_422 decompressed output image:
- In J2D.PicFlags2 set PF2_Cosited.
- In J2D.PicFlags2 set PF2_SmoothUpsample.
- Set J2D.YuvOutputType to BI_YUY2 or BI_UYVY
- Set DibSize to 16.
- In J2D.PicFlags2 set PF2_CompressedYuv
Color JPEG Input Image
A. Creating a 16, 24 or 32 bit color DIB
- u.J2D.DibSize is set to 16, 24 or 32.
- PF_ConvertGray is not set.
- PF_Dither is not used for a 24 or 32-bit DIB. It may be set for a 16-bit DIB if desired.
- PF_CreateDibWithMadeColors is not used.
- PF_UseOnlyMadeColors is not used.
- PF_MakeColors may be used to create an optimum color table (see case B. following), otherwise u.J2D.PrimClrToMake, u.J2D.SecClrToMake and u.J2D.MadeColorTable are not used and RES_COLORS_MADE will not be returned.
- u.J2D.GraysToMake is not used.
- If R-G-B output is desired, set PF_SwapRB
B. Creating a 4- or 8-Bit Color DIB with Optimum Colors
- u.J2D.DibSize is set to 4 or 8.
- PF_ConvertGray is not set.
- PF_Dither may be set as desired.
- PF_MakeColors is set.
- PF_CreateDibWithMadeColors is set.
- PF_UseOnlyMadeColors is set unless you want to display an intermediate image using the color table saved with the JPEG image, if any, (see case C. following) or using another color table supplied in ColorTable (see case D. following).
- PrimClrToMake and SecClrToMake may be specified. Typically, PrimClrToMake will be set to 16 or 256 and SecClrToMake will be 0.
- RES_COLORS_MADE will be returned by Pegasus after the optimum colors are created.
- A buffer sufficiently large for the created colors can be allocated and MadeColorTable set to the buffer address, if desired. If so, then the optimum colors are copied to MadeColorTable in addition to being copied to ColorTable.
- Head.biClrUsed, Head.biClrImportant and ColorTable are ignored as input and are set to the created palette, primary or secondary, which is appropriate to u.J2D.DibSize on output.
C. Creating a 4- or 8-Bit Color DIB with an External Palette
- u.J2D.DibSize is set to 4 or 8.
- PF_ConvertGray is not set.
- PF_Dither may be set as desired.
- PF_MakeColors is not set.
- PF_CreateDibWithMadeColors is not set.
- PF_UseOnlyMadeColors is not set.
- PrimClrToMake and SecClrToMake are not set.
- RES_COLORS_MADE will not be returned.
- Head.biClrUsed, Head.biClrImportant and ColorTable are set on input according to the external palette.
- MadeColorTable is not used.
- Pegasus sets Head.biClrUsed to the number of colors in the primary or secondary palette which is appropriate to u.J2D.DibSize. Head.biClrImportant is set equal to Head.biClrUsed and the color values are copied to ColorTable.
D. Creating a 4- or 8-Bit Gray Scale DIB
- u.J2D.DibSize is set to 4 or 8.
- PF_ConvertGray is set.
- PF_Dither may be set as desired.
- PF_MakeColors may be set if ColorTable has a palette, but you wish to create a palette. (You could also set Head.biClrUsed to 0 to force colors to be made).
- PF_CreateDibWithMadeColors is not set.
- PF_UseOnlyMadeColors is not set.
- GraysToMake is set unless you want to use the default according to u.J2D.DibSize or unless you are supplying a gray scale color table in ColorTable.
- RES_COLORS_MADE will not be returned.
- Head.biClrUsed, Head.biClrImportant and ColorTable are set if you want to use that gray scale color table instead of creating one. These values are overridden by PF_MakeColors.
- MadeColorTable is not used.
- If gray levels were made, Pegasus sets Head.biClrUsed and Head.biClrImportant to the number of gray levels made and sets ColorTable according to the gray levels made.
E. Creating a YUV Output Image
- u.J2D.DibSize is set to 16.
- Set PF_YuvOuput.
- Set YuvOutputType to BI_YUY2 or BI_UYVY.
CMYK Color JPEG Input Image
CMYK JPEG images may only be decompressed to interleaved CMYK.
- u.J2D.DibSize is set to 32.
- PF_ConvertGray is not set.
- PF_Dither is not used.
- PF_CreateDibWithMadeColors is not used.
- PF_UseOnlyMadeColors is not used.
- PF_MakeColors is not used.
- u.J2D.GraysToMake is not used.
- Set PF2_NoYccTransform.
Gray Scale JPEG Input Image
A. Input is 12-bit gray scale JPG
- PegasusQuery will return Head.biBitCount = 12.
- Set J2D.PicFlags |= PF_NoDibPad to avoid any padding of output lines otherwise output lines are padded to a multiple of 4 bytes.
- Set the width of the output line, set J2D.PicFlags |= PF_WidthPadKnown, and set J2D.WidthPad to the desired width in bytes.
1. Create a 12-bit image
- Set J2D.DibSize = 16
- If J2D.GrayMap12Bit is Null, then the 12 bits for each pixel of the decompress image will be placed in the low-order 12 bits of the 16 bit field.
- If J2D.GrayMap12Bit is NOT Null, then it is assumed to be a table of 4096 16-bit words.
2. Create an 8-bit image
- Set J2D.DibSize = 8
- J2D.GrayMap12Bit MUST NOT be Null, it is assumed to be a table of 2^12 8-bit bytes.
- OR Set S2D.PicFlags |= PF_Quickview12, output will be the top 8 bits of the 12-bit field; it is less accurate because the low bits are thrown away during dequantization, but it is very fast.
Notes - Using J2D.GrayMap12Bit
The lookup table J2D.GrayMap12Bit may be constructed to map the 12 bits to either a 16-bit or 8-bit field in any way desired. The function BuildTranslationTable12 which is included in the test program jetest.c illustrates this for a choice of brightness, contrast, gamma-correction, output bits of precision, and effective input bits of precision. Ordinarily the effective input bits of precision would be 12, since the data was supposedly 12-bit. But the user may know, for example, that the original data was really 10 bits right-justified. The jpeg decompressor does not know this, and since it is lossy, some of the decompressed data may exceed 10 bits. So the user should set Num = 2^10 in the input of BuildTranslationTable12. The table will then accept inputs up to 12 bits, but the input values >= 2^10 will be clipped to have the same output as 2^10 - 1 has. This is the option -VS# in the command line test program; in this example # would be set to 10. For example if -VP8 and -VS10 are set in the command-line test program, the high 8 bits of the alleged 10-bit data are mapped to the output bytes, and anything above 10 bits gets mapped to the same value as 2^10 - 1 does.
B. Input is 8-Bit Gray Scale JPG - Creating a 4- or 8-Bit Gray Scale DIB
- u.J2D.DibSize is set to 4 or 8.
- PF_ConvertGray may be set.
- PF_Dither may be set as desired.
- PF_MakeColors may be set if ColorTable has a palette, but you wish to create a palette. (You could also set Head.biClrUsed to 0 to force colors to be made).
- PF_CreateDibWithMadeColors is not set.
- PF_UseOnlyMadeColors is not set.
- PrimClrToMake and SecClrToMake are not set.
- GraysToMake is set unless you want to use the default according to u.J2D.DibSize or unless you are supplying a gray scale color table in ColorTable.
- RES_COLORS_MADE will not be returned.
- Head.biClrUsed, Head.biClrImportant and ColorTable are set if you want to use that gray scale color table instead of creating one. These values are overriden by PF_MakeColors.
- MadeColorTable is not used.
- If gray levels were made, Pegasus sets Head.biClrUsed and Head.biClrImportant to the number of gray levels made and sets ColorTable according to the gray levels made.
- If the JPEG image were saved with a color table, and the color table has 256 colors, then the green components of the colors are used as for gamma correction of the created or supplied gray levels. There is no way to override this behavior.
Metadata
JPEG Metadata contained in the input GET queue is returned in the PIC2List. The following metadata is returned:
- APP marker segments are returned as P2P_RawData PIC2List packets.
- IPTC data contained in an APP13 marker segment is returned as P2PktIPTCDataSet PIC2List packets. Only the first IPTC Resource Block encountered is returned.
- Note that if an IPTC Resource Block spans multiple APP13 marker segments, the IPTC Resource Block will be ignored and not returned in the PIC2List.
Notes
- The Put queue is not accessed during REQ_INIT.
- The Put queue can be allocated during the REQ_EXEC response loop if desired.
- The Put queue size must be at least u.J2D.StripSize and must be an integer multiple of StripSize when using Q_REVERSE.
- The Get queue size must be at least 128 bytes.
- The Get queue must be allocated prior to REQ_INIT, although it need not contain any data until requested by RES_GET_NEED_DATA.
- REQ_INIT changes the PIC_PARM data in such a way that an OP_S2D operation cannot be restarted after an error by simply correcting the error and using the same PIC_PARM data.
- This opcode allows decompressing an image previously compressed with PICTools/AIMTools and password protected. See details in the section describing the PIC_PARM KeyField field.
Alternative Legacy Approach for Retrieving Comments and Application Data: Separate Comment and AppField Buffers
OP_S2D and OP_P2D support an alternative approach for retrieving comments and other data from an image and making it available to the application. This is a legacy approach and is more restrictive than the use of the newer PIC2List functions. When using this approach, an application would allocate a buffer where the data of interest will be eventually placed by Pegasus. There are two possibilities according to when the buffer space is allocated.
Application Pre-allocates a Buffer before Pegasus Operation
|
This technique is also supported by PegasusQuery. In fact, it is the only choice for retrieving comments and other data via PegasusQuery. |
In most cases, the application doesn't know how much data may be included in the comment or application data. In some cases an application either knows a probable maximum size or knows that it is acceptable to truncate the data over some maximum size. In these cases, the application may choose to pre-allocate a buffer for the data before calling Pegasus for initialization.
The application sets PIC_PARM.Comment (PIC_PARM.u.S2D.AppField) to the address of the buffer. PIC_PARM.CommentSize (PIC_PARM.u.S2D.AppFieldSize) is set to the allocated size of the buffer. When Pegasus encounters comment data or application data in the image, it copies as much of the data to the appropriate buffer as will fit. PIC_PARM.CommentLen (PIC_PARM.u.S2D.AppFieldLen) is set to the length of the copied data.
The application data should appear only once in the image. Comment data may appear more than once. When the application pre-allocates a comment buffer according to this section, the last comment data encountered prior to Pegasus returning a response is the comment data which appears in the PIC_PARM.Comment buffer any other prior comments are lost.
Application Allocates a Buffer during Pegasus Operation
When an application does not know the size of the image comment data, and must retrieve all available comment data, the application sets PIC_PARM.CommentSize to 0 and sets the PF_AlllocateComment flag in the PicFlags field of the operation-specific PIC_PARM union structure.
For application data, the application sets the PIC_PARM.u.S2D.AppFieldSize field to -1 and doesn't set a PicFlags flag.
When Pegasus encounters the comment (application data) it sets the PIC_PARM.CommentLen (PIC_PARM.u.S2D.AppFieldLen) field and returns to the application with a response of RES_ALLOCATE_COMMENT_BUF (RES_ALLOCATE_APP2_BUF). At this time the application can allocate a buffer and set PIC_PARM.Comment (PIC_PARM.u.S2D.AppField) and PIC_PARM.CommentSize (PIC_PARM.u.S2D.AppFieldSize). The comment is retrieved when the operation is continued by returning 0 from the application's DeferFn function.
Pegasus returns the RES_HAVE_COMMENT response when the PF_AllocateComment flag is set, and an image comment is encountered, and an image comment was previously retrieved. This response gives the application an opportunity to save the previous comment before overwriting it by retrieving the current comment. When the application continues the operation after saving the previous comment, a RES_ALLOCATE_COMMENT_BUF response is returned so a buffer can be allocated for the current comment.
The following example demonstrates this by storing the first 100 comments and their length in two, previously allocated, arrays: CommentsData and CommentsLen.
|
Copy Code |
PicParm.u.S2D.PicFlags |= PF_AllocateComment;
PicParm.u.S2D.AppFieldSize = -1;
resp = Pegasus(&PicParm, REQ_INIT);
if ( resp == RES_DONE )
resp = Pegasus(&PicParm, REQ_EXEC);
if ( resp == RES_DONE )
Pegasus(&PicParm, REQ_TERM);
///////////////////////////////////////////
LONG DeferFn(PIC_PARM* pp, RESPONSE resp)
{
switch (resp) {
case RES_GET_NEED_DATA:
Status = GetData(pp);
break;
case RES_PUT_NEED_SPACE:
Status = PutSpace(pp);
break;
case RES_ERR:
Status = pp->Status;
break;
case RES_ALLOCATE_APP2_BUF:
pp->u.S2D.AppFieldSize = pp->u.S2D.AppFieldLen;
pp->u.S2D.AppField = malloc(pp->u.S2D.AppFieldSize);
if ( pp->u.S2D.AppField == 0 ) {
pp->Status = ERR_OUT_OF_SPACE;
return ( 1 ); // abort the operation
}
break;
case RES_HAVE_COMMENT:
if (ncomments < 100) {
CommentsData[ncomments] = pp->Comment;
CommentsLen[ncomments++] = pp->CommentLen;
}
pp->CommentSize = 0;
break;
case RES_ALLOCATE_COMMENT_BUF:
pp->CommentSize = pp->CommentLen;
pp->Comment = malloc(pp->CommentSize);
if ( pp->Comment == 0 ) {
pp->Status = ERR_OUT_OF_SPACE;
return ( 1 ); // abort the operation
}
break;
}
// abort if Status != ERR_NONE
return ( Status != ERR_NONE );
}
|