Commit 46389fea6 for imagemagick.org
commit 46389fea6efb50a1827f1a541c410bd7778112c7
Author: Dirk Lemstra <dirk@lemstra.org>
Date: Mon Oct 5 21:45:40 2026 +0200
Add dng:read-thumbnails to read embedded thumbnails as images.
diff --git a/coders/dng.c b/coders/dng.c
index 099730089..a2ba28ef2 100644
--- a/coders/dng.c
+++ b/coders/dng.c
@@ -528,6 +528,91 @@ static MagickBooleanType UnpackLibRawImage(Image *image,const ImageInfo *image_i
libraw_dcraw_clear_mem(raw_image);
return(MagickTrue);
}
+
+static Image* LibrawThumbnailBitmapToImage(const ImageInfo *image_info,
+ libraw_data_t *raw_info,ExceptionInfo *exception)
+{
+ Image
+ *image;
+
+ QuantumInfo
+ *quantum_info;
+
+ QuantumType
+ quantum_type;
+
+ Quantum
+ *q;
+
+ image=AcquireImage(image_info,exception);
+ image->columns=(size_t) raw_info->thumbnail.twidth;
+ image->rows=(size_t) raw_info->thumbnail.theight;
+ if (SetImageExtent(image,image->columns,image->rows,exception) == MagickFalse)
+ return(DestroyImage(image));
+ image->depth=8;
+ quantum_type=RGBQuantum;
+ if (raw_info->thumbnail.tcolors == 1)
+ {
+ image->colorspace=GRAYColorspace;
+ image->type=GrayscaleType;
+ quantum_type=GrayQuantum;
+ }
+ quantum_info=AcquireQuantumInfo(image_info,image);
+ q=QueueAuthenticPixels(image,0,0,image->columns,
+ image->rows,exception);
+ if (q != (Quantum *) NULL)
+ {
+ (void) ImportQuantumPixels(image,(CacheView *) NULL,
+ quantum_info,quantum_type,(const unsigned char *)
+ raw_info->thumbnail.thumb,exception);
+ (void) SyncAuthenticPixels(image,exception);
+ }
+ quantum_info=DestroyQuantumInfo(quantum_info);
+ return(image);
+}
+
+static MagickBooleanType UnpackLibRawThumbnails(Image **image,const ImageInfo *image_info,
+ libraw_data_t *raw_info,int *errcode,ExceptionInfo *exception)
+{
+ ImageInfo
+ *thumbnail_info;
+
+ int
+ i;
+
+ if (raw_info->thumbs_list.thumbcount == 0)
+ {
+ *errcode=LIBRAW_NO_THUMBNAIL;
+ return(MagickFalse);
+ }
+ if (AcquireMagickResource(ListLengthResource,raw_info->thumbs_list.thumbcount) == MagickFalse)
+ {
+ (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
+ "ListLengthExceedsLimit","`%s'",image_info->filename);
+ return(MagickFalse);
+ }
+ for(i=0; i < (ssize_t) raw_info->thumbs_list.thumbcount; i++)
+ {
+ Image
+ *thumbnail;
+
+ *errcode=libraw_unpack_thumb_ex(raw_info,i);
+ if (*errcode != LIBRAW_SUCCESS)
+ return(MagickFalse);
+ thumbnail_info=AcquireImageInfo();
+ if (raw_info->thumbnail.tformat == LIBRAW_THUMBNAIL_BITMAP)
+ thumbnail=LibrawThumbnailBitmapToImage(thumbnail_info,raw_info,exception);
+ else
+ thumbnail=BlobToImage(thumbnail_info,raw_info->thumbnail.thumb,
+ raw_info->thumbnail.tlength,exception);
+ thumbnail_info=DestroyImageInfo(thumbnail_info);
+ if (thumbnail == (Image*) NULL)
+ return(MagickFalse);
+ AppendImageToList(image,thumbnail);
+ }
+ (void) RemoveImageFromList(image);
+ return(MagickTrue);
+}
#endif
static Image *ReadDNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
@@ -560,6 +645,9 @@ static Image *ReadDNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
return(InvokeDNGDelegate(image_info,image,exception));
#if defined(MAGICKCORE_RAW_R_DELEGATE)
{
+ const char
+ *option;
+
int
errcode;
@@ -626,7 +714,11 @@ static Image *ReadDNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
libraw_close(raw_info);
return(image);
}
- status=UnpackLibRawImage(image,image_info,raw_info,&errcode,exception);
+ option=GetImageOption(image_info,"dng:read-thumbnails");
+ if (IsStringTrue(option) == MagickTrue)
+ status=UnpackLibRawThumbnails(&image,image_info,raw_info,&errcode,exception);
+ else
+ status=UnpackLibRawImage(image,image_info,raw_info,&errcode,exception);
libraw_close(raw_info);
if (status != MagickTrue)
{