GraphicsMagick: coders/bmp.c Ability to write JPG encoded image....

GraphicsMagick Commits <[email protected]> Sun, 17 Sep 2023 17:13:10 -0500
Newsgroups gmane.comp.video.graphicsmagick.cvs
Message-ID <mailman.1319.1694988801.7975.graphicsmagick-commit@lists.sourceforge.net>
changeset 677224a9b8e7 in /hg/GraphicsMagick
details: http://hg.GraphicsMagick.org/hg/GraphicsMagick?cmd=changeset;node=677224a9b8e7
summary: coders/bmp.c Ability to write JPG encoded image. Using a new command line switch: -define bmp:allow-jpeg

diffstat:

 ChangeLog    |    5 +
 coders/bmp.c |  194 ++++++++++++++++++++++++++++++++++++++++------------------
 2 files changed, 138 insertions(+), 61 deletions(-)

diffs (279 lines):

diff -r 19d29252e157 -r 677224a9b8e7 ChangeLog
--- a/ChangeLog	Sun Sep 17 14:01:55 2023 -0500
+++ b/ChangeLog	Mon Sep 18 00:12:50 2023 +0200
@@ -1,3 +1,8 @@
+2023-09-18  Fojtik Jaroslav  <[email protected]>
+
+	* coders/bmp.c Ability to write JPG encoded image.
+	Using a new command line switch: -define bmp:allow-jpeg
+
 2023-09-17  Bob Friesenhahn  <[email protected]>
 
 	* coders/jp2.c (BlobRead): For old libJasper, return 0 for size
diff -r 19d29252e157 -r 677224a9b8e7 coders/bmp.c
--- a/coders/bmp.c	Sun Sep 17 14:01:55 2023 -0500
+++ b/coders/bmp.c	Mon Sep 18 00:12:50 2023 +0200
@@ -1899,6 +1899,43 @@
   (void) UnregisterMagickInfo("BMP2");
   (void) UnregisterMagickInfo("BMP3");
 }
+
+
+static int StoreBlobJPG(Image * image, const ImageInfo * image_info)
+{
+ImageInfo *jpeg_image_info;
+Image *jpeg_image;
+void *Data;
+size_t DataSize = 0;
+
+  jpeg_image_info = (ImageInfo *)CloneImageInfo(image_info);
+  if(jpeg_image_info == (ImageInfo *) NULL)
+      ThrowWriterException(ResourceLimitError,MemoryAllocationFailed, image);
+  if(image->logging)
+      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                              "  Creating jpeg_image.");
+
+  jpeg_image = CloneImage(image,0,0,MagickTrue,&image->exception);
+
+  (void)strlcpy(jpeg_image_info->magick,"JPEG",MaxTextExtent);
+  (void)strlcpy(jpeg_image_info->filename,"JPEG:",MaxTextExtent);
+  (void)strlcpy(jpeg_image->magick,"JPEG",MaxTextExtent);
+  (void)strlcpy(jpeg_image->filename,"JPEG:",MaxTextExtent);
+
+  Data = ImageToBlob(jpeg_image_info,jpeg_image,&DataSize,&image->exception);
+  if(Data!=NULL)
+  {
+    WriteBlob(image,DataSize,Data);
+    MagickFreeMemory(Data);
+  }
+
+      /* Destroy JPEG image and image_info */
+  DestroyImage(jpeg_image);
+  DestroyImageInfo(jpeg_image_info);
+
+return 0;
+}
+
 
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1971,6 +2008,10 @@
     scene,
     type;
 
+  ExportPixelAreaOptions
+    export_options;
+
+
   /*   const unsigned char */
   /*     *color_profile=0; */
 
@@ -2005,6 +2046,8 @@
   scene=0;
   adjoin=image_info->adjoin;
 
+  ExportPixelAreaOptionsInit(&export_options);
+
   /*
     Retrieve color profile from Image (if any)
     FIXME: is color profile support writing not properly implemented?
@@ -2031,7 +2074,25 @@
       bmp_info.compression=BI_RGB;
       if ((image->storage_class != DirectClass) && (image->colors > 256))
         (void) SetImageType(image,TrueColorType);
-      if (image->storage_class != DirectClass)
+
+      if(type>2 && AccessDefinition(image_info,"bmp","allow-jpeg"))
+        {
+          image->compression = JPEGCompression;
+          bmp_info.number_colors = 0;
+          bmp_info.bits_per_pixel = 0;
+          bmp_info.compression = BI_JPEG;
+        }
+      else if (image->storage_class == DirectClass)
+        {
+          /*
+            Full color BMP raster.
+          */
+          bmp_info.number_colors=0;
+          bmp_info.bits_per_pixel=((type > 3) && image->matte) ? 32 : 24;
+          bmp_info.compression=
+            (type > 3) && image->matte ?  BI_BITFIELDS : BI_RGB;
+        }
+      else  /* image->storage_class != DirectClass*/
         {
           /*
             Colormapped BMP raster.
@@ -2060,16 +2121,7 @@
                   }
               }
         }
-      if (image->storage_class == DirectClass)
-        {
-          /*
-            Full color BMP raster.
-          */
-          bmp_info.number_colors=0;
-          bmp_info.bits_per_pixel=((type > 3) && image->matte) ? 32 : 24;
-          bmp_info.compression=
-            (type > 3) && image->matte ?  BI_BITFIELDS : BI_RGB;
-        }
+
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                             "Final: Scene %lu, storage_class %s, colors %u",
                             scene,
@@ -2079,17 +2131,26 @@
         Below emulates:
         bytes_per_line=4*((image->columns*bmp_info.bits_per_pixel+31)/32);
       */
-      bytes_per_line=MagickArraySize(image->columns,bmp_info.bits_per_pixel);
-      if ((bytes_per_line > 0) && (~((size_t) 0) - bytes_per_line) > 31)
-        bytes_per_line = MagickArraySize(4,(bytes_per_line+31)/32);
-      if (bytes_per_line == 0)
-        ThrowWriterException(CoderError,ArithmeticOverflow,image);
-      image_size=MagickArraySize(bytes_per_line,image->rows);
-      if ((image_size == 0) || ((image_size & 0xffffffff) != image_size))
-        ThrowWriterException(CoderError,ArithmeticOverflow,image);
+      if(bmp_info.compression == BI_JPEG)
+      {
+        bytes_per_line = 0;
+        image_size = 0;
+        have_color_info = 0;
+      }
+      else
+      {
+        bytes_per_line=MagickArraySize(image->columns,bmp_info.bits_per_pixel);
+        if ((bytes_per_line > 0) && (~((size_t) 0) - bytes_per_line) > 31)
+          bytes_per_line = MagickArraySize(4,(bytes_per_line+31)/32);
+        if (bytes_per_line==0)
+          ThrowWriterException(CoderError,ArithmeticOverflow,image);
+        image_size=MagickArraySize(bytes_per_line,image->rows);
+        if ((image_size == 0) || ((image_size & 0xffffffff) != image_size))
+          ThrowWriterException(CoderError,ArithmeticOverflow,image);
+        have_color_info=(int) ((image->rendering_intent != UndefinedIntent) ||
+                             (color_profile_length != 0) || (image->gamma != 0.0));
+      }
       bmp_info.ba_offset=0;
-      have_color_info=(int) ((image->rendering_intent != UndefinedIntent) ||
-                             (color_profile_length != 0) || (image->gamma != 0.0));
       if (type == 2)
         bmp_info.size=12;
       else
@@ -2153,9 +2214,14 @@
       /*
         Convert MIFF to BMP raster pixels.
       */
-      pixels=MagickAllocateResourceLimitedMemory(unsigned char *,bmp_info.image_size);
-      if (pixels == (unsigned char *) NULL)
-        ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image);
+      if(bmp_info.compression == BI_JPEG)
+        pixels=NULL;
+      else
+      {
+        pixels=MagickAllocateResourceLimitedMemory(unsigned char *,bmp_info.image_size);
+        if (pixels == (unsigned char *) NULL)
+          ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image);
+      }
       switch (bmp_info.bits_per_pixel)
         {
         case 1:
@@ -2482,56 +2548,62 @@
               (void) WriteBlobLSBLong(image,0x0);  /* reserved */
             }
         }
-      if (image->storage_class == PseudoClass)
+        if(pixels==NULL)
         {
-          unsigned char
-            *bmp_colormap;
+          StoreBlobJPG(image,image_info);
+        }
+        else
+        {
+          if (image->storage_class==PseudoClass)
+            {
+            unsigned char
+              *bmp_colormap;
 
           /*
             Dump colormap to file.
           */
-          if (logging)
-            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+            if (logging)
+              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                                   "  Colormap: %u entries",image->colors);
-          bmp_colormap=MagickAllocateResourceLimitedArray(unsigned char *,4,
+            bmp_colormap=MagickAllocateResourceLimitedArray(unsigned char *,4,
                                                           (size_t) (1L << bmp_info.bits_per_pixel));
-          if (bmp_colormap == (unsigned char *) NULL)
-            {
-              MagickFreeResourceLimitedMemory(pixels);
-              ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,
-                                   image);
-            }
-          q=bmp_colormap;
-          for (i=0; i < Min(image->colors,bmp_info.number_colors); i++)
-            {
-              *q++=ScaleQuantumToChar(image->colormap[i].blue);
-              *q++=ScaleQuantumToChar(image->colormap[i].green);
-              *q++=ScaleQuantumToChar(image->colormap[i].red);
-              if (type > 2)
+            if (bmp_colormap == (unsigned char *) NULL)
+              {
+                MagickFreeResourceLimitedMemory(pixels);
+                ThrowWriterException(ResourceLimitError,MemoryAllocationFailed, image);
+              }
+            q=bmp_colormap;
+            for (i=0; i < Min(image->colors,bmp_info.number_colors); i++)
+              {
+                *q++=ScaleQuantumToChar(image->colormap[i].blue);
+                *q++=ScaleQuantumToChar(image->colormap[i].green);
+                *q++=ScaleQuantumToChar(image->colormap[i].red);
+                if (type > 2)
+                  *q++=(Quantum) 0x0;
+              }
+            for ( ; i < (1UL << bmp_info.bits_per_pixel); i++)
+              {
+              *q++=(Quantum) 0x0;
                 *q++=(Quantum) 0x0;
-            }
-          for ( ; i < (1UL << bmp_info.bits_per_pixel); i++)
-            {
-              *q++=(Quantum) 0x0;
-              *q++=(Quantum) 0x0;
-              *q++=(Quantum) 0x0;
-              if (type > 2)
                 *q++=(Quantum) 0x0;
-            }
-          if (type <= 2)
-            (void) WriteBlob(image,3*(1UL << bmp_info.bits_per_pixel),
+                if (type > 2)
+                  *q++=(Quantum) 0x0;
+                }
+            if (type <= 2)
+              (void) WriteBlob(image,3*(1UL << bmp_info.bits_per_pixel),
                              (char *) bmp_colormap);
-          else
-            (void) WriteBlob(image,4*(1UL << bmp_info.bits_per_pixel),
+            else
+              (void) WriteBlob(image,4*(1UL << bmp_info.bits_per_pixel),
                              (char *) bmp_colormap);
-          MagickFreeResourceLimitedMemory(bmp_colormap);
-        }
-      if (logging)
-        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+            MagickFreeResourceLimitedMemory(bmp_colormap);
+          }
+        if (logging)
+          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                               "  Pixels:  %" MAGICK_SIZE_T_F "u bytes",
                               (MAGICK_SIZE_T) bmp_info.image_size);
-      (void) WriteBlob(image,bmp_info.image_size,(char *) pixels);
-      MagickFreeResourceLimitedMemory(pixels);
+        (void) WriteBlob(image,bmp_info.image_size,(char *) pixels);
+        MagickFreeResourceLimitedMemory(pixels);
+      }
       if (image->next == (Image *) NULL)
         {
           if (logging)