]> granicus.if.org Git - imagemagick/commitdiff
Added support for writing 16-bit TGA files
authordirk <dirk@git.imagemagick.org>
Tue, 16 Dec 2014 09:48:03 +0000 (09:48 +0000)
committerdirk <dirk@git.imagemagick.org>
Tue, 16 Dec 2014 09:48:03 +0000 (09:48 +0000)
coders/tga.c

index 2168fac32d8fe76f85aa7300a9be9ea4a5c7de0d..d2ebcd018ef75fbaa0f07e8cd3981f0c1b0a791e 100644 (file)
@@ -660,7 +660,7 @@ static inline size_t MagickMin(const size_t x,const size_t y)
 }
 
 static inline void WriteTGAPixel(Image *image,TGAImageType image_type,
-  const Quantum *p)
+  const Quantum *p,const QuantumAny range,const double midpoint)
 {
   if (image_type == TGAColormap || image_type == TGARLEColormap)
     (void) WriteBlobByte(image,(unsigned char) GetPixelIndex(image,p));
@@ -669,6 +669,23 @@ static inline void WriteTGAPixel(Image *image,TGAImageType image_type,
       if (image_type == TGAMonochrome || image_type == TGARLEMonochrome)
         (void) WriteBlobByte(image,ScaleQuantumToChar(ClampToQuantum(
           GetPixelLuma(image,p))));
+      else if (image->depth == 5)
+        {
+          unsigned char
+            green,
+            value;
+
+            green=(unsigned char) ScaleQuantumToAny(ClampToQuantum(
+              GetPixelGreen(image,p)),range);
+            value=((unsigned char) ScaleQuantumToAny(ClampToQuantum(
+              GetPixelBlue(image,p)),range)) | ((green & 0x07) << 5);
+            (void) WriteBlobByte(image,value);
+            value=(((image->alpha_trait == BlendPixelTrait) && (ClampToQuantum(
+              GetPixelAlpha(image,p)) < midpoint)) ? 80 : 0) |
+              ((unsigned char) ScaleQuantumToAny(ClampToQuantum(
+              GetPixelRed(image,p)),range) << 2) | ((green & 0x18) >> 3);
+            (void) WriteBlobByte(image,value);
+        }
       else
         {
           (void) WriteBlobByte(image,ScaleQuantumToChar(GetPixelBlue(image,
@@ -692,9 +709,15 @@ static MagickBooleanType WriteTGAImage(const ImageInfo *image_info,Image *image,
   const char
     *value;
 
+  const double
+    midpoint=QuantumRange / 2.0;
+
   MagickBooleanType
     status;
 
+  QuantumAny
+    range;
+
   register const Quantum
     *p;
 
@@ -740,6 +763,7 @@ static MagickBooleanType WriteTGAImage(const ImageInfo *image_info,Image *image,
   compression=image->compression;
   if (image_info->compression != UndefinedCompression)
     compression=image_info->compression;
+  range=GetQuantumRange(5UL);
   tga_info.id_length=0;
   value=GetImageProperty(image,"comment",exception);
   if (value != (const char *) NULL)
@@ -769,11 +793,16 @@ static MagickBooleanType WriteTGAImage(const ImageInfo *image_info,Image *image,
         */
         tga_info.image_type=compression == RLECompression ? TGARLERGB :
           TGARGB;
-        tga_info.bits_per_pixel=24;
-        if (image->alpha_trait == BlendPixelTrait)
+        if (image_info->depth == 5)
+          tga_info.bits_per_pixel=16;
+        else
           {
-            tga_info.bits_per_pixel=32;
-            tga_info.attributes=8;  /* # of alpha bits */
+            tga_info.bits_per_pixel=24;
+            if (image->alpha_trait == BlendPixelTrait)
+              {
+                tga_info.bits_per_pixel=32;
+                tga_info.attributes=8;  /* # of alpha bits */
+              }
           }
       }
     else
@@ -785,7 +814,10 @@ static MagickBooleanType WriteTGAImage(const ImageInfo *image_info,Image *image,
           TGAColormap;
         tga_info.colormap_type=1;
         tga_info.colormap_length=(unsigned short) image->colors;
-        tga_info.colormap_size=24;
+        if (image_info->depth == 5)
+          tga_info.colormap_size=16;
+        else
+          tga_info.colormap_size=24;
       }
   /*
     Write TGA header.
@@ -808,24 +840,40 @@ static MagickBooleanType WriteTGAImage(const ImageInfo *image_info,Image *image,
   if (tga_info.colormap_type != 0)
     {
       unsigned char
+        green,
         *targa_colormap;
 
       /*
         Dump colormap to file (blue, green, red byte order).
       */
       targa_colormap=(unsigned char *) AcquireQuantumMemory((size_t)
-        tga_info.colormap_length,3UL*sizeof(*targa_colormap));
+        tga_info.colormap_length,(tga_info.colormap_size/8)*sizeof(
+        *targa_colormap));
       if (targa_colormap == (unsigned char *) NULL)
         ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
       q=targa_colormap;
       for (i=0; i < (ssize_t) image->colors; i++)
       {
-        *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].blue));
-        *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].green));
-        *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].red));
+        if (image_info->depth == 5)
+          {
+            green=(unsigned char) ScaleQuantumToAny(ClampToQuantum(
+              image->colormap[i].green),range);
+            *q++=((unsigned char) ScaleQuantumToAny(ClampToQuantum(
+              image->colormap[i].blue),range)) | ((green & 0x07) << 5);
+            *q++=(((image->alpha_trait == BlendPixelTrait) && (ClampToQuantum(
+              image->colormap[i].alpha) < midpoint)) ? 80 : 0) |
+              ((unsigned char) ScaleQuantumToAny(ClampToQuantum(
+              image->colormap[i].red),range) << 2) | ((green & 0x18) >> 3);
+          }
+        else
+          {
+            *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].blue));
+            *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].green));
+            *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].red));
+          }
       }
-      (void) WriteBlob(image,(size_t) (3*tga_info.colormap_length),
-        targa_colormap);
+      (void) WriteBlob(image,(size_t) ((tga_info.colormap_size/8)*
+        tga_info.colormap_length),targa_colormap);
       targa_colormap=(unsigned char *) RelinquishMagickMemory(targa_colormap);
     }
   /*
@@ -889,7 +937,7 @@ static MagickBooleanType WriteTGAImage(const ImageInfo *image_info,Image *image,
                   while (count >= 0)
                   {
                     WriteTGAPixel(image,tga_info.image_type,p-((count+1)*
-                      channels));
+                      channels),range,midpoint);
                     count--;
                   }
                   count=0;
@@ -898,7 +946,7 @@ static MagickBooleanType WriteTGAImage(const ImageInfo *image_info,Image *image,
           if (i >= 3)
             {
               WriteBlobByte(image,(unsigned char) ((i-1) | 0x80));
-              WriteTGAPixel(image,tga_info.image_type,p);
+              WriteTGAPixel(image,tga_info.image_type,p,range,midpoint);
               p+=(i*channels);
             }
           x+=i;
@@ -908,7 +956,7 @@ static MagickBooleanType WriteTGAImage(const ImageInfo *image_info,Image *image,
       {
         for (x=0; x < (ssize_t) image->columns; x++)
           {
-            WriteTGAPixel(image,tga_info.image_type,p);
+            WriteTGAPixel(image,tga_info.image_type,p,range,midpoint);
             p+=channels;
           }
       }