GraphicsMagick: ReadJPEGImage(): Support libjpeg-turbo 3.X APIs ...
GraphicsMagick Commits <[email protected]> Sat, 10 Feb 2024 14:54:57 -0600
| Newsgroups | gmane.comp.video.graphicsmagick.cvs |
|---|---|
| Message-ID | <mailman.10771.1707598515.16032.graphicsmagick-commit@lists.sourceforge.net> |
changeset 0bdf6df7faf2 in /hg/GraphicsMagick details: http://hg.GraphicsMagick.org/hg/GraphicsMagick?cmd=changeset;node=0bdf6df7faf2 summary: ReadJPEGImage(): Support libjpeg-turbo 3.X APIs to read deep JPEG. diffstat: ChangeLog | 10 + VisualMagick/installer/inc/version.isx | 4 +- coders/jpeg.c | 713 ++++++++++++++++++++------------ coders/tiff.c | 56 +- magick/version.h | 4 +- www/ChangeLog.html | 10 + 6 files changed, 496 insertions(+), 301 deletions(-) diffs (truncated from 1236 to 500 lines): diff -r fc5cac9afb5c -r 0bdf6df7faf2 ChangeLog --- a/ChangeLog Tue Feb 06 08:26:53 2024 -0600 +++ b/ChangeLog Sat Feb 10 14:54:39 2024 -0600 @@ -1,3 +1,13 @@ +2024-02-10 Bob Friesenhahn <[email protected]> + + * coders/jpeg.c (WriteJPEGImage): Do some preparation to implement + support for libjpeg-turbo 3.X APIs while writing deep JPEG. + + * coders/tiff.c (AddIFDExifFields): Fix a compilation warning. + + * coders/jpeg.c (ReadJPEGImage): Support libjpeg-turbo 3.X APIs to + read deep JPEG. + 2024-02-06 Bob Friesenhahn <[email protected]> * coders/tiff.c (AddIFDExifFields): Add casts to prevent signed vs diff -r fc5cac9afb5c -r 0bdf6df7faf2 VisualMagick/installer/inc/version.isx --- a/VisualMagick/installer/inc/version.isx Tue Feb 06 08:26:53 2024 -0600 +++ b/VisualMagick/installer/inc/version.isx Sat Feb 10 14:54:39 2024 -0600 @@ -10,5 +10,5 @@ #define public MagickPackageName "GraphicsMagick" #define public MagickPackageVersion "1.4" -#define public MagickPackageVersionAddendum ".020240206" -#define public MagickPackageReleaseDate "snapshot-20240206" +#define public MagickPackageVersionAddendum ".020240210" +#define public MagickPackageReleaseDate "snapshot-20240210" diff -r fc5cac9afb5c -r 0bdf6df7faf2 coders/jpeg.c --- a/coders/jpeg.c Tue Feb 06 08:26:53 2024 -0600 +++ b/coders/jpeg.c Sat Feb 10 14:54:39 2024 -0600 @@ -136,6 +136,26 @@ static const char xmp_std_header[]="http://ns.adobe.com/xap/1.0/"; +/* + Struct to lessen the impact of multiple sample types + + This assumes a normal architecture where pointer size is consistent. +*/ +typedef struct +{ + union + { + void *v; + JSAMPLE *j; +#if defined(HAVE_JPEG12_READ_SCANLINES) && HAVE_JPEG12_READ_SCANLINES + J12SAMPLE *j12; +#endif /* if defined(HAVE_JPEG12_READ_SCANLINES) && HAVE_JPEG12_READ_SCANLINES */ +#if defined(HAVE_JPEG16_READ_SCANLINES) && HAVE_JPEG16_READ_SCANLINES + J16SAMPLE *j16; +#endif /* if defined(HAVE_JPEG16_READ_SCANLINES) && HAVE_JPEG16_READ_SCANLINES */ + } t; +} magick_jpeg_pixels_t; + typedef struct _DestinationManager { struct jpeg_destination_mgr @@ -178,7 +198,7 @@ unsigned char buffer[65537+200]; - void + magick_jpeg_pixels_t *jpeg_pixels; } MagickClientData; @@ -221,7 +241,7 @@ MagickFreeMemory(client_data->profiles[i].name); MagickFreeResourceLimitedMemory(client_data->profiles[i].info); } - MagickFreeResourceLimitedMemory(client_data->jpeg_pixels); + MagickFreeResourceLimitedMemory(client_data->jpeg_pixels->t.v); MagickFreeMemory(client_data); } @@ -1248,11 +1268,8 @@ long y; - JSAMPLE - *jpeg_pixels; - - JSAMPROW - scanline[1]; + magick_jpeg_pixels_t + jpeg_pixels; /* Contents freed by FreeMagickClientData() */ const char *value; @@ -1269,9 +1286,6 @@ struct jpeg_decompress_struct jpeg_info; - register JSAMPLE - *p; - MagickPassFail status; @@ -1299,17 +1313,18 @@ /* Initialize structures. */ + (void) memset(&jpeg_pixels,0,sizeof(jpeg_pixels)); (void) memset(&jpeg_progress,0,sizeof(jpeg_progress)); (void) memset(&jpeg_info,0,sizeof(jpeg_info)); (void) memset(&jpeg_error,0,sizeof(jpeg_error)); jpeg_info.err=jpeg_std_error(&jpeg_error); jpeg_info.err->emit_message=/*(void (*)(j_common_ptr,int))*/ JPEGDecodeMessageHandler; jpeg_info.err->error_exit=(void (*)(j_common_ptr)) JPEGErrorHandler; - jpeg_pixels=(JSAMPLE *) NULL; client_data->image=image; client_data->ping=image_info->ping; client_data->max_scan_number=100; client_data->max_warning_count=MaxWarningCount; + client_data->jpeg_pixels=&jpeg_pixels; /* Allow the user to set how many warnings of any given type are @@ -1699,11 +1714,37 @@ } } - jpeg_pixels=MagickAllocateResourceLimitedClearedArray(JSAMPLE *, - jpeg_info.output_components, - MagickArraySize(image->columns, - sizeof(JSAMPLE))); - if (jpeg_pixels == (JSAMPLE *) NULL) + switch (jpeg_info.data_precision) + { +#if defined(HAVE_JPEG16_READ_SCANLINES) && HAVE_JPEG16_READ_SCANLINES + case 16: + jpeg_pixels.t.j16 = + MagickAllocateResourceLimitedClearedArray(J16SAMPLE *, + jpeg_info.output_components, + MagickArraySize(image->columns, + sizeof(J16SAMPLE))); + break; +#endif /* if defined(HAVE_JPEG16_READ_SCANLINES) && HAVE_JPEG16_READ_SCANLINES */ +#if defined(HAVE_JPEG12_READ_SCANLINES) && HAVE_JPEG12_READ_SCANLINES + case 12: + jpeg_pixels.t.j12 = + MagickAllocateResourceLimitedClearedArray(J12SAMPLE *, + jpeg_info.output_components, + MagickArraySize(image->columns, + sizeof(J12SAMPLE))); + break; +#endif /* if defined(HAVE_JPEG12_READ_SCANLINES) && HAVE_JPEG12_READ_SCANLINES */ + default: + { + jpeg_pixels.t.j = + MagickAllocateResourceLimitedClearedArray(JSAMPLE *, + jpeg_info.output_components, + MagickArraySize(image->columns, + sizeof(JSAMPLE))); + } + } + + if (jpeg_pixels.t.v == (void *) NULL) { jpeg_destroy_decompress(&jpeg_info); ThrowJPEGReaderException(ResourceLimitError,MemoryAllocationFailed,image); @@ -1717,7 +1758,7 @@ (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Setjmp return from longjmp!"); /* Error handling code executed if longjmp was invoked */ - MagickFreeResourceLimitedMemory(jpeg_pixels); + MagickFreeResourceLimitedMemory(jpeg_pixels.t.v); jpeg_destroy_decompress(&jpeg_info); if (image->exception.severity > exception->severity) CopyException(exception,&image->exception); @@ -1730,10 +1771,10 @@ return((Image *) NULL); } + /* Convert JPEG pixels to pixel packets. */ - scanline[0]=(JSAMPROW) jpeg_pixels; for (y=0; y < (long) image->rows; y++) { register IndexPacket @@ -1746,14 +1787,52 @@ *q; /* - Read scanlines. Stop at first serious error. - */ - if ((jpeg_read_scanlines(&jpeg_info,scanline,1) != 1) || - (image->exception.severity >= ErrorException)) + Read scanlines (one scanline per cycle). Stop at first serious error. + */ +#if defined(HAVE_JPEG16_READ_SCANLINES) && HAVE_JPEG16_READ_SCANLINES + if (jpeg_info.data_precision == 16) { - status=MagickFail; - break; - } + { + J16SAMPROW + scanline[1]; + + scanline[0]=(J16SAMPROW) jpeg_pixels.t.j16; + if ((jpeg16_read_scanlines(&jpeg_info, scanline,1) != 1) || + (image->exception.severity >= ErrorException)) + { + status=MagickFail; + break; + } + } + } else +#endif /* if defined(HAVE_JPEG16_READ_SCANLINES) && HAVE_JPEG16_READ_SCANLINES */ +#if defined(HAVE_JPEG12_READ_SCANLINES) && HAVE_JPEG12_READ_SCANLINES + if (jpeg_info.data_precision == 12) + { + J12SAMPROW + scanline[1]; + + scanline[0]=(J12SAMPROW) jpeg_pixels.t.j12; + if ((jpeg12_read_scanlines(&jpeg_info, scanline,1) != 1) || + (image->exception.severity >= ErrorException)) + { + status=MagickFail; + break; + } + } else +#endif /* if defined(HAVE_JPEG12_READ_SCANLINES) && HAVE_JPEG12_READ_SCANLINES */ + { + JSAMPROW + scanline[1]; + + scanline[0]=(JSAMPROW) jpeg_pixels.t.j; + if ((jpeg_read_scanlines(&jpeg_info, scanline,1) != 1) || + (image->exception.severity >= ErrorException)) + { + status=MagickFail; + break; + } + } q=SetImagePixels(image,0,y,image->columns,1); if (q == (PixelPacket *) NULL) @@ -1763,80 +1842,159 @@ } indexes=AccessMutableIndexes(image); - p=jpeg_pixels; - if (jpeg_info.output_components == 1) { if (image->storage_class == PseudoClass) { - for (x=0; x < (long) image->columns; x++) + switch(jpeg_info.data_precision) { - index=(IndexPacket) (GETJSAMPLE(*p++)); - VerifyColormapIndex(image,index); - indexes[x]=index; - *q++=image->colormap[index]; +#if defined(HAVE_JPEG16_READ_SCANLINES) && HAVE_JPEG16_READ_SCANLINES + case 16: + { + for (x=0; x < (long) image->columns; x++) + { + index=(IndexPacket) ScaleQuantumToIndex((ScaleShortToQuantum(jpeg_pixels.t.j16[x]))); + VerifyColormapIndex(image,index); + indexes[x]=index; + *q++=image->colormap[index]; + } + break; + } +#endif /* if defined(HAVE_JPEG16_READ_SCANLINES) && HAVE_JPEG16_READ_SCANLINES */ +#if defined(HAVE_JPEG12_READ_SCANLINES) && HAVE_JPEG12_READ_SCANLINES + case 12: + { + const unsigned int + scale_short = 65535U/MAXJ12SAMPLE; + + for (x=0; x < (long) image->columns; x++) + { + index=(IndexPacket) ScaleQuantumToIndex((ScaleShortToQuantum(scale_short*((unsigned short)jpeg_pixels.t.j12[x])))); + VerifyColormapIndex(image,index); + indexes[x]=index; + *q++=image->colormap[index]; + } + break; + } +#endif /* if defined(HAVE_JPEG12_READ_SCANLINES) && HAVE_JPEG12_READ_SCANLINES */ + default: + { + for (x=0; x < (long) image->columns; x++) + { + index=(IndexPacket) (GETJSAMPLE(jpeg_pixels.t.j[x])); + VerifyColormapIndex(image,index); + indexes[x]=index; + *q++=image->colormap[index]; + } + } } } else { - if (jpeg_info.data_precision > 8) + switch(jpeg_info.data_precision) { - unsigned int - scale_short; - - scale_short=65535U/MaxValueGivenBits(jpeg_info.data_precision); - for (x=0; x < (long) image->columns; x++) +#if defined(HAVE_JPEG16_READ_SCANLINES) && HAVE_JPEG16_READ_SCANLINES + case 16: + { + /* J16SAMPLE is a 'unsigned short' with maximum value MAXJ16SAMPLE (65535) */ + for (x=0; x < (long) image->columns; x++) { - q->red=q->green=q->blue=ScaleShortToQuantum(scale_short*GETJSAMPLE(*p++)); + q->red=q->green=q->blue=ScaleShortToQuantum(jpeg_pixels.t.j16[x]); q->opacity=OpaqueOpacity; q++; } - } - else - { - for (x=0; x < (long) image->columns; x++) + break; + } +#endif /* if defined(HAVE_JPEG16_READ_SCANLINES) && HAVE_JPEG16_READ_SCANLINES */ +#if defined(HAVE_JPEG12_READ_SCANLINES) && HAVE_JPEG12_READ_SCANLINES + case 12: + { + /* J12SAMPLE is a 'short' with maximum value MAXJ12SAMPLE (4095) */ + const unsigned int + scale_short = 65535U/MAXJ12SAMPLE; + + for (x=0; x < (long) image->columns; x++) { - q->red=q->green=q->blue=ScaleCharToQuantum(GETJSAMPLE(*p++)); + q->red=q->green=q->blue=ScaleShortToQuantum(scale_short*((unsigned short)jpeg_pixels.t.j12[x])); q->opacity=OpaqueOpacity; q++; } + break; + } +#endif /* if defined(HAVE_JPEG12_READ_SCANLINES) && HAVE_JPEG12_READ_SCANLINES */ + default: + { + for (x=0; x < (long) image->columns; x++) + { + q->red=q->green=q->blue=ScaleCharToQuantum(GETJSAMPLE(jpeg_pixels.t.j[x])); + q->opacity=OpaqueOpacity; + q++; + } + } } } } else if ((jpeg_info.output_components == 3) || (jpeg_info.output_components == 4)) { - if (jpeg_info.data_precision > 8) + switch(jpeg_info.data_precision) { - unsigned int - scale_short; - - scale_short=65535U/MaxValueGivenBits(jpeg_info.data_precision); - for (x=0; x < (long) image->columns; x++) - { - q->red=ScaleShortToQuantum(scale_short*GETJSAMPLE(*p++)); - q->green=ScaleShortToQuantum(scale_short*GETJSAMPLE(*p++)); - q->blue=ScaleShortToQuantum(scale_short*GETJSAMPLE(*p++)); - if (jpeg_info.output_components > 3) - q->opacity=ScaleShortToQuantum(scale_short*GETJSAMPLE(*p++)); - else - q->opacity=OpaqueOpacity; - q++; - } - } - else - { - for (x=0; x < (long) image->columns; x++) - { - q->red=ScaleCharToQuantum(GETJSAMPLE(*p++)); - q->green=ScaleCharToQuantum(GETJSAMPLE(*p++)); - q->blue=ScaleCharToQuantum(GETJSAMPLE(*p++)); - if (jpeg_info.output_components > 3) - q->opacity=ScaleCharToQuantum(GETJSAMPLE(*p++)); - else - q->opacity=OpaqueOpacity; - q++; - } +#if defined(HAVE_JPEG16_READ_SCANLINES) && HAVE_JPEG16_READ_SCANLINES + case 16: + { + /* J16SAMPLE is a 'unsigned short' with maximum value MAXJ16SAMPLE (65535) */ + i = 0; + for (x=0; x < (long) image->columns; x++) + { + q->red=ScaleShortToQuantum(jpeg_pixels.t.j16[i++]); + q->green=ScaleShortToQuantum(jpeg_pixels.t.j16[i++]); + q->blue=ScaleShortToQuantum(jpeg_pixels.t.j16[i++]); + if (jpeg_info.output_components > 3) + q->opacity=ScaleShortToQuantum(jpeg_pixels.t.j16[i++]); + else + q->opacity=OpaqueOpacity; + q++; + } + break; + } +#endif /* if defined(HAVE_JPEG16_READ_SCANLINES) && HAVE_JPEG16_READ_SCANLINES */ +#if defined(HAVE_JPEG12_READ_SCANLINES) && HAVE_JPEG12_READ_SCANLINES + case 12: + { + /* J12SAMPLE is a 'short' with maximum value MAXJ12SAMPLE (4095) */ + const unsigned int + scale_short = 65535U/MAXJ12SAMPLE; + + i = 0; + for (x=0; x < (long) image->columns; x++) + { + q->red=ScaleShortToQuantum(scale_short*((unsigned short)jpeg_pixels.t.j12[i++])); + q->green=ScaleShortToQuantum(scale_short*((unsigned short)jpeg_pixels.t.j12[i++])); + q->blue=ScaleShortToQuantum(scale_short*((unsigned short)jpeg_pixels.t.j12[i++])); + if (jpeg_info.output_components > 3) + q->opacity=ScaleShortToQuantum(scale_short*((unsigned short)jpeg_pixels.t.j12[i++])); + else + q->opacity=OpaqueOpacity; + q++; + } + break; + } +#endif /* if defined(HAVE_JPEG12_READ_SCANLINES) && HAVE_JPEG12_READ_SCANLINES */ + default: + { + i = 0; + for (x=0; x < (long) image->columns; x++) + { + q->red=ScaleCharToQuantum(GETJSAMPLE(jpeg_pixels.t.j[i++])); + q->green=ScaleCharToQuantum(GETJSAMPLE(jpeg_pixels.t.j[i++])); + q->blue=ScaleCharToQuantum(GETJSAMPLE(jpeg_pixels.t.j[i++])); + if (jpeg_info.output_components > 3) + q->opacity=ScaleCharToQuantum(GETJSAMPLE(jpeg_pixels.t.j[i++])); + else + q->opacity=OpaqueOpacity; + q++; + } + } } if (image->colorspace == CMYKColorspace) { @@ -1897,7 +2055,7 @@ } } jpeg_destroy_decompress(&jpeg_info); - MagickFreeResourceLimitedMemory(jpeg_pixels); + MagickFreeResourceLimitedMemory(jpeg_pixels.t.v); client_data=FreeMagickClientData(client_data); CloseBlob(image); @@ -2500,8 +2658,8 @@ const ImageAttribute *attribute; - JSAMPLE - *jpeg_pixels = (JSAMPLE *) NULL; /* Freed by FreeMagickClientData() */ + magick_jpeg_pixels_t + jpeg_pixels; /* Contents freed by FreeMagickClientData() */ JSAMPROW scanline[1]; @@ -2523,9 +2681,11 @@ *q; register long - i, x; + register unsigned long + i; + struct jpeg_error_mgr jpeg_error; @@ -2564,6 +2724,7 @@ if (status == False) ThrowJPEGWriterException(FileOpenError,UnableToOpenFile,image); + (void) memset(&jpeg_pixels,0,sizeof(jpeg_pixels)); (void) memset(&jpeg_progress,0,sizeof(jpeg_progress)); (void) memset(&jpeg_info,0,sizeof(jpeg_info)); (void) memset(&jpeg_error,0,sizeof(jpeg_error)); @@ -2595,7 +2756,7 @@ } (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Write JPEG Image: image->orientation = %d",image->orientation); + " Write JPEG Image: image->orientation = %d",image->orientation);