]> granicus.if.org Git - imagemagick/blobdiff - coders/gif.c
(no commit message)
[imagemagick] / coders / gif.c
index 536cf6362c759ab5ae36fc0f55fcd5bb0f3b46a6..4d9ce5baeaadf53ce4e719e59edaa61ec828860e 100644 (file)
@@ -68,6 +68,7 @@
 #include "MagickCore/quantum-private.h"
 #include "MagickCore/static.h"
 #include "MagickCore/string_.h"
+#include "MagickCore/string-private.h"
 #include "MagickCore/module.h"
 \f
 /*
@@ -1051,7 +1052,6 @@ static Image *ReadGIFImage(const ImageInfo *image_info,ExceptionInfo *exception)
         /*
           GIF Extension block.
         */
-
         count=ReadBlob(image,1,&c);
         if (count != 1)
           {
@@ -1079,26 +1079,33 @@ static Image *ReadGIFImage(const ImageInfo *image_info,ExceptionInfo *exception)
             char
               *comments;
 
+            size_t
+              length;
+
             /*
               Read comment extension.
             */
             comments=AcquireString((char *) NULL);
-            for ( ; ; )
+            for (length=0; ; length+=count)
             {
               count=(ssize_t) ReadBlobBlock(image,header);
               if (count == 0)
                 break;
               header[count]='\0';
-              (void) ConcatenateString(&comments,(const char *) header);
+              comments=(char *) ResizeQuantumMemory(comments,length+count,
+                sizeof(*comments));
+              if (comments == (char *) NULL)
+                ThrowReaderException(ResourceLimitError,
+                  "MemoryAllocationFailed");
+              (void) CopyMagickMemory(comments+length,header,(size_t) count);
             }
+            comments[length+count]='\0';
             (void) SetImageProperty(image,"comment",comments,exception);
             comments=DestroyString(comments);
             break;
           }
           case 0xff:
           {
-            /* Read GIF application extension */
-
             MagickBooleanType
               loop;
 
@@ -1128,7 +1135,8 @@ static Image *ReadGIFImage(const ImageInfo *image_info,ExceptionInfo *exception)
                 MagickBooleanType
                   i8bim,
                   icc,
-                  iptc;
+                  iptc,
+                  magick;
 
                 StringInfo
                   *profile;
@@ -1139,10 +1147,12 @@ static Image *ReadGIFImage(const ImageInfo *image_info,ExceptionInfo *exception)
                 /*
                   Store GIF application extension as a generic profile.
                 */
-                i8bim=LocaleNCompare((char *) header,"MGK8BIM0000",11) == 0 ?
-                  MagickTrue : MagickFalse;
                 icc=LocaleNCompare((char *) header,"ICCRGBG1012",11) == 0 ?
                   MagickTrue : MagickFalse;
+                magick=LocaleNCompare((char *) header,"ImageMagick",11) == 0 ?
+                  MagickTrue : MagickFalse;
+                i8bim=LocaleNCompare((char *) header,"MGK8BIM0000",11) == 0 ?
+                  MagickTrue : MagickFalse;
                 iptc=LocaleNCompare((char *) header,"MGKIPTC0000",11) == 0 ?
                   MagickTrue : MagickFalse;
                 number_extensionss++;
@@ -1174,17 +1184,23 @@ static Image *ReadGIFImage(const ImageInfo *image_info,ExceptionInfo *exception)
                 if (profile == (StringInfo *) NULL)
                   ThrowReaderException(ResourceLimitError,
                     "MemoryAllocationFailed");
-                info=(unsigned char *) RelinquishMagickMemory(info);
                 if (i8bim == MagickTrue)
                   (void) CopyMagickString(name,"8bim",sizeof(name));
                 else if (icc == MagickTrue)
                   (void) CopyMagickString(name,"icc",sizeof(name));
                 else if (iptc == MagickTrue)
                   (void) CopyMagickString(name,"iptc",sizeof(name));
+                else if (magick == MagickTrue)
+                  {
+                    (void) CopyMagickString(name,"magick",sizeof(name));
+                    image->gamma=StringToDouble((char *) info+6,(char **) NULL);
+                  }
                 else
                   (void) FormatLocaleString(name,sizeof(name),"gif:%.11s",
                     header);
-                (void) SetImageProfile(image,name,profile,exception);
+                info=(unsigned char *) RelinquishMagickMemory(info);
+                if (magick == MagickFalse)
+                  (void) SetImageProfile(image,name,profile,exception);
                 profile=DestroyStringInfo(profile);
                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                   "      profile name=%s",name);
@@ -1267,12 +1283,12 @@ static Image *ReadGIFImage(const ImageInfo *image_info,ExceptionInfo *exception)
         p=global_colormap;
         for (i=0; i < (ssize_t) image->colors; i++)
         {
-          image->colormap[i].red=ScaleCharToQuantum(*p++);
-          image->colormap[i].green=ScaleCharToQuantum(*p++);
-          image->colormap[i].blue=ScaleCharToQuantum(*p++);
+          image->colormap[i].red=(double) ScaleCharToQuantum(*p++);
+          image->colormap[i].green=(double) ScaleCharToQuantum(*p++);
+          image->colormap[i].blue=(double) ScaleCharToQuantum(*p++);
           if (i == opacity)
             {
-              image->colormap[i].alpha=(Quantum) TransparentAlpha;
+              image->colormap[i].alpha=(double) TransparentAlpha;
               image->transparent_color=image->colormap[opacity];
             }
         }
@@ -1307,14 +1323,22 @@ static Image *ReadGIFImage(const ImageInfo *image_info,ExceptionInfo *exception)
         p=colormap;
         for (i=0; i < (ssize_t) image->colors; i++)
         {
-          image->colormap[i].red=ScaleCharToQuantum(*p++);
-          image->colormap[i].green=ScaleCharToQuantum(*p++);
-          image->colormap[i].blue=ScaleCharToQuantum(*p++);
+          image->colormap[i].red=(double) ScaleCharToQuantum(*p++);
+          image->colormap[i].green=(double) ScaleCharToQuantum(*p++);
+          image->colormap[i].blue=(double) ScaleCharToQuantum(*p++);
           if (i == opacity)
-            image->colormap[i].alpha=(Quantum) TransparentAlpha;
+            image->colormap[i].alpha=(double) TransparentAlpha;
         }
         colormap=(unsigned char *) RelinquishMagickMemory(colormap);
       }
+    if (image->gamma == 1.0)
+      {
+        for (i=0; i < (ssize_t) image->colors; i++)
+          if (IsPixelInfoGray(image->colormap+i) == MagickFalse)
+            break;
+        (void) SetImageColorspace(image,i == (ssize_t) image->colors ? 
+          GRAYColorspace : RGBColorspace,exception);
+      }
     if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
         break;
@@ -1548,7 +1572,7 @@ static MagickBooleanType WriteGIFImage(const ImageInfo *image_info,Image *image,
   one=1;
   do
   {
-    if (IsRGBColorspace(image->colorspace) == MagickFalse)
+    if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
       (void) TransformImageColorspace(image,sRGBColorspace,exception);
     opacity=(-1);
     if (IsImageOpaque(image,exception) != MagickFalse)
@@ -1616,9 +1640,9 @@ static MagickBooleanType WriteGIFImage(const ImageInfo *image_info,Image *image,
     q=colormap;
     for (i=0; i < (ssize_t) image->colors; i++)
     {
-      *q++=ScaleQuantumToChar(image->colormap[i].red);
-      *q++=ScaleQuantumToChar(image->colormap[i].green);
-      *q++=ScaleQuantumToChar(image->colormap[i].blue);
+      *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].red));
+      *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].green));
+      *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].blue));
     }
     for ( ; i < (ssize_t) (one << bits_per_pixel); i++)
     {
@@ -1671,20 +1695,19 @@ static MagickBooleanType WriteGIFImage(const ImageInfo *image_info,Image *image,
             const char
               *value;
 
-            register const char
+            register const char 
               *p;
 
             size_t
               count;
-
+    
             /*
-              Write Comment extension.
+              Write comment extension.
             */
             (void) WriteBlobByte(image,(unsigned char) 0x21);
             (void) WriteBlobByte(image,(unsigned char) 0xfe);
             value=GetImageProperty(image,"comment",exception);
-            p=value;
-            while (strlen(p) != 0)
+            for (p=value; *p != '\0'; )
             {
               count=MagickMin(strlen(p),255);
               (void) WriteBlobByte(image,(unsigned char) count);
@@ -1711,6 +1734,29 @@ static MagickBooleanType WriteGIFImage(const ImageInfo *image_info,Image *image,
             (void) WriteBlobLSBShort(image,(unsigned short) image->iterations);
             (void) WriteBlobByte(image,(unsigned char) 0x00);
           }
+        if ((image->gamma != 1.0f/2.2f))
+          {
+            char
+              attributes[MaxTextExtent];
+
+            ssize_t
+              length;
+
+            /*
+              Write ImageMagick extension.
+            */
+            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+               "  Writing GIF Extension %s","ImageMagick");
+            (void) WriteBlobByte(image,(unsigned char) 0x21);
+            (void) WriteBlobByte(image,(unsigned char) 0xff);
+            (void) WriteBlobByte(image,(unsigned char) 0x0b);
+            (void) WriteBlob(image,11,(unsigned char *) "ImageMagick");
+            length=FormatLocaleString(attributes,MaxTextExtent,"gamma=%g",
+              image->gamma);
+            (void) WriteBlobByte(image,(unsigned char) length);
+            (void) WriteBlob(image,length,(unsigned char *) attributes);
+            (void) WriteBlobByte(image,(unsigned char) 0x00);
+          }
         ResetImageProfileIterator(image);
         for ( ; ; )
         {
@@ -1752,7 +1798,7 @@ static MagickBooleanType WriteGIFImage(const ImageInfo *image_info,Image *image,
                    /*
                      Write ICC extension.
                    */
-                   (void) WriteBlob(image,11,(unsigned char *)"ICCRGBG1012");
+                   (void) WriteBlob(image,11,(unsigned char *) "ICCRGBG1012");
                    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                        "  Writing GIF Extension %s","ICCRGBG1012");
                  }
@@ -1760,9 +1806,9 @@ static MagickBooleanType WriteGIFImage(const ImageInfo *image_info,Image *image,
                  if ((LocaleCompare(name,"IPTC") == 0))
                    {
                      /*
-                       write IPTC extension.
+                       Write IPTC extension.
                      */
-                     (void) WriteBlob(image,11,(unsigned char *)"MGKIPTC0000");
+                     (void) WriteBlob(image,11,(unsigned char *) "MGKIPTC0000");
                      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                          "  Writing GIF Extension %s","MGKIPTC0000");
                    }
@@ -1770,7 +1816,7 @@ static MagickBooleanType WriteGIFImage(const ImageInfo *image_info,Image *image,
                    if ((LocaleCompare(name,"8BIM") == 0))
                      {
                        /*
-                         Write 8BIM extension>
+                         Write 8BIM extension.
                        */
                         (void) WriteBlob(image,11,(unsigned char *)
                           "MGK8BIM0000");
@@ -1782,7 +1828,9 @@ static MagickBooleanType WriteGIFImage(const ImageInfo *image_info,Image *image,
                        char
                          extension[MaxTextExtent];
 
-                       /* write generic extension */
+                       /*
+                         Write generic extension.
+                       */
                        (void) CopyMagickString(extension,name+4,
                          sizeof(extension));
                        (void) WriteBlob(image,11,(unsigned char *) extension);