#include "MagickCore/static.h"
#include "MagickCore/string_.h"
#include "MagickCore/module.h"
+
+/*
+ Enumerated declaractions.
+*/
+typedef enum
+{
+ TGAColormap = 1,
+ TGARGB = 2,
+ TGAMonochrome = 3,
+ TGARLEColormap = 9,
+ TGARLERGB = 10,
+ TGARLEMonochrome = 11
+} TGAImageType;
+
+/*
+ Typedef declaractions.
+*/
+typedef struct _TGAInfo
+{
+ TGAImageType
+ image_type;
+
+ unsigned char
+ id_length,
+ colormap_type;
+
+ unsigned short
+ colormap_index,
+ colormap_length;
+
+ unsigned char
+ colormap_size;
+
+ unsigned short
+ x_origin,
+ y_origin,
+ width,
+ height;
+
+ unsigned char
+ bits_per_pixel,
+ attributes;
+} TGAInfo;
\f
/*
Forward declarations.
% o exception: return any errors or warnings in this structure.
%
*/
-static Image *ReadTGAImage(const ImageInfo *image_info,ExceptionInfo *exception)
+static Image *ReadTGAImage(const ImageInfo *image_info,
+ ExceptionInfo *exception)
{
-#define TGAColormap 1
-#define TGARGB 2
-#define TGAMonochrome 3
-#define TGARLEColormap 9
-#define TGARLERGB 10
-#define TGARLEMonochrome 11
-
- typedef struct _TGAInfo
- {
- unsigned char
- id_length,
- colormap_type,
- image_type;
-
- unsigned short
- colormap_index,
- colormap_length;
-
- unsigned char
- colormap_size;
-
- unsigned short
- x_origin,
- y_origin,
- width,
- height;
-
- unsigned char
- bits_per_pixel,
- attributes;
- } TGAInfo;
-
Image
*image;
*/
count=ReadBlob(image,1,&tga_info.id_length);
tga_info.colormap_type=(unsigned char) ReadBlobByte(image);
- tga_info.image_type=(unsigned char) ReadBlobByte(image);
+ tga_info.image_type=(TGAImageType) ReadBlobByte(image);
if ((count != 1) ||
((tga_info.image_type != TGAColormap) &&
(tga_info.image_type != TGARGB) &&
return(y);
}
+static inline void WriteTGAPixel(Image *image,TGAImageType image_type,
+ const Quantum *p)
+{
+ if (image_type == TGAColormap || image_type == TGARLEColormap)
+ (void) WriteBlobByte(image,(unsigned char) GetPixelIndex(image,p));
+ else
+ {
+ if (image_type == TGAMonochrome || image_type == TGARLEMonochrome)
+ (void) WriteBlobByte(image,ScaleQuantumToChar(ClampToQuantum(
+ GetPixelLuma(image,p))));
+ else
+ {
+ (void) WriteBlobByte(image,ScaleQuantumToChar(GetPixelBlue(image,
+ p)));
+ (void) WriteBlobByte(image,ScaleQuantumToChar(GetPixelGreen(image,
+ p)));
+ (void) WriteBlobByte(image,ScaleQuantumToChar(GetPixelRed(image,p)));
+ if (image->alpha_trait == BlendPixelTrait)
+ (void) WriteBlobByte(image,ScaleQuantumToChar(GetPixelAlpha(image,
+ p)));
+ }
+ }
+}
+
static MagickBooleanType WriteTGAImage(const ImageInfo *image_info,Image *image,
ExceptionInfo *exception)
{
-#define TargaColormap 1
-#define TargaRGB 2
-#define TargaMonochrome 3
-#define TargaRLEColormap 9
-#define TargaRLERGB 10
-#define TargaRLEMonochrome 11
-
- typedef struct _TargaInfo
- {
- unsigned char
- id_length,
- colormap_type,
- image_type;
-
- unsigned short
- colormap_index,
- colormap_length;
-
- unsigned char
- colormap_size;
-
- unsigned short
- x_origin,
- y_origin,
- width,
- height;
-
- unsigned char
- bits_per_pixel,
- attributes;
- } TargaInfo;
+ CompressionType
+ compression;
const char
*value;
register unsigned char
*q;
+ size_t
+ channels;
+
ssize_t
count,
y;
- TargaInfo
- targa_info;
-
- unsigned char
- *targa_pixels;
+ TGAInfo
+ tga_info;
/*
Open output image file.
if ((image->columns > 65535L) || (image->rows > 65535L))
ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
(void) TransformImageColorspace(image,sRGBColorspace,exception);
- targa_info.id_length=0;
+ compression=image->compression;
+ if (image_info->compression != UndefinedCompression)
+ compression=image_info->compression;
+ tga_info.id_length=0;
value=GetImageProperty(image,"comment",exception);
if (value != (const char *) NULL)
- targa_info.id_length=(unsigned char) MagickMin(strlen(value),255);
- targa_info.colormap_type=0;
- targa_info.colormap_index=0;
- targa_info.colormap_length=0;
- targa_info.colormap_size=0;
- targa_info.x_origin=0;
- targa_info.y_origin=0;
- targa_info.width=(unsigned short) image->columns;
- targa_info.height=(unsigned short) image->rows;
- targa_info.bits_per_pixel=8;
- targa_info.attributes=0;
+ tga_info.id_length=(unsigned char) MagickMin(strlen(value),255);
+ tga_info.colormap_type=0;
+ tga_info.colormap_index=0;
+ tga_info.colormap_length=0;
+ tga_info.colormap_size=0;
+ tga_info.x_origin=0;
+ tga_info.y_origin=0;
+ tga_info.width=(unsigned short) image->columns;
+ tga_info.height=(unsigned short) image->rows;
+ tga_info.bits_per_pixel=8;
+ tga_info.attributes=0;
if ((image_info->type != TrueColorType) &&
(image_info->type != TrueColorMatteType) &&
(image_info->type != PaletteType) &&
(image->alpha_trait != BlendPixelTrait) &&
(IsImageGray(image,exception) != MagickFalse))
- targa_info.image_type=TargaMonochrome;
+ tga_info.image_type=compression == RLECompression ? TGARLEMonochrome :
+ TGAMonochrome;
else
if ((image->storage_class == DirectClass) || (image->colors > 256))
{
/*
Full color TGA raster.
*/
- targa_info.image_type=TargaRGB;
- targa_info.bits_per_pixel=24;
+ tga_info.image_type=compression == RLECompression ? TGARLERGB :
+ TGARGB;
+ tga_info.bits_per_pixel=24;
if (image->alpha_trait == BlendPixelTrait)
{
- targa_info.bits_per_pixel=32;
- targa_info.attributes=8; /* # of alpha bits */
+ tga_info.bits_per_pixel=32;
+ tga_info.attributes=8; /* # of alpha bits */
}
}
else
/*
Colormapped TGA raster.
*/
- targa_info.image_type=TargaColormap;
- targa_info.colormap_type=1;
- targa_info.colormap_length=(unsigned short) image->colors;
- targa_info.colormap_size=24;
+ tga_info.image_type=compression == RLECompression ? TGARLEColormap :
+ TGAColormap;
+ tga_info.colormap_type=1;
+ tga_info.colormap_length=(unsigned short) image->colors;
+ tga_info.colormap_size=24;
}
/*
Write TGA header.
*/
- (void) WriteBlobByte(image,targa_info.id_length);
- (void) WriteBlobByte(image,targa_info.colormap_type);
- (void) WriteBlobByte(image,targa_info.image_type);
- (void) WriteBlobLSBShort(image,targa_info.colormap_index);
- (void) WriteBlobLSBShort(image,targa_info.colormap_length);
- (void) WriteBlobByte(image,targa_info.colormap_size);
- (void) WriteBlobLSBShort(image,targa_info.x_origin);
- (void) WriteBlobLSBShort(image,targa_info.y_origin);
- (void) WriteBlobLSBShort(image,targa_info.width);
- (void) WriteBlobLSBShort(image,targa_info.height);
- (void) WriteBlobByte(image,targa_info.bits_per_pixel);
- (void) WriteBlobByte(image,targa_info.attributes);
- if (targa_info.id_length != 0)
- (void) WriteBlob(image,targa_info.id_length,(unsigned char *)
+ (void) WriteBlobByte(image,tga_info.id_length);
+ (void) WriteBlobByte(image,tga_info.colormap_type);
+ (void) WriteBlobByte(image,tga_info.image_type);
+ (void) WriteBlobLSBShort(image,tga_info.colormap_index);
+ (void) WriteBlobLSBShort(image,tga_info.colormap_length);
+ (void) WriteBlobByte(image,tga_info.colormap_size);
+ (void) WriteBlobLSBShort(image,tga_info.x_origin);
+ (void) WriteBlobLSBShort(image,tga_info.y_origin);
+ (void) WriteBlobLSBShort(image,tga_info.width);
+ (void) WriteBlobLSBShort(image,tga_info.height);
+ (void) WriteBlobByte(image,tga_info.bits_per_pixel);
+ (void) WriteBlobByte(image,tga_info.attributes);
+ if (tga_info.id_length != 0)
+ (void) WriteBlob(image,tga_info.id_length,(unsigned char *)
value);
- if (targa_info.image_type == TargaColormap)
+ if (tga_info.colormap_type != 0)
{
unsigned char
*targa_colormap;
Dump colormap to file (blue, green, red byte order).
*/
targa_colormap=(unsigned char *) AcquireQuantumMemory((size_t)
- targa_info.colormap_length,3UL*sizeof(*targa_colormap));
+ tga_info.colormap_length,3UL*sizeof(*targa_colormap));
if (targa_colormap == (unsigned char *) NULL)
ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
q=targa_colormap;
*q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].green));
*q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].red));
}
- (void) WriteBlob(image,(size_t) (3*targa_info.colormap_length),
+ (void) WriteBlob(image,(size_t) (3*tga_info.colormap_length),
targa_colormap);
targa_colormap=(unsigned char *) RelinquishMagickMemory(targa_colormap);
}
/*
Convert MIFF to TGA raster pixels.
*/
- count=(ssize_t) (targa_info.bits_per_pixel*targa_info.width)/8;
- targa_pixels=(unsigned char *) AcquireQuantumMemory((size_t) count,
- sizeof(*targa_pixels));
- if (targa_pixels == (unsigned char *) NULL)
- ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
+ channels=GetPixelChannels(image);
for (y=(ssize_t) (image->rows-1); y >= 0; y--)
{
p=GetVirtualPixels(image,0,y,image->columns,1,exception);
if (p == (const Quantum *) NULL)
break;
- q=targa_pixels;
- for (x=0; x < (ssize_t) image->columns; x++)
- {
- if (targa_info.image_type == TargaColormap)
- *q++=(unsigned char) GetPixelIndex(image,p);
- else
- if (targa_info.image_type == TargaMonochrome)
- *q++=(unsigned char) ScaleQuantumToChar((ClampToQuantum(
- GetPixelLuma(image,p))));
- else
+ if (compression == RLECompression)
+ {
+ x=0;
+ count=0;
+ while (x < (ssize_t) image->columns)
+ {
+ i=1;
+ while ((i < 128) && (count + i < 128) &&
+ ((x + i) < (ssize_t) image->columns))
{
- *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
- *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
- *q++=ScaleQuantumToChar(GetPixelRed(image,p));
- if (image->alpha_trait == BlendPixelTrait)
- *q++=(unsigned char) ScaleQuantumToChar(GetPixelAlpha(image,p));
+ if (tga_info.image_type == TGARLEColormap)
+ {
+ if (GetPixelIndex(image,p+(i*channels)) !=
+ GetPixelIndex(image,p+((i-1)*channels)))
+ break;
+ }
+ else if (tga_info.image_type == TGARLEMonochrome)
+ {
+ if (GetPixelLuma(image,p+(i*channels)) !=
+ GetPixelLuma(image,p+((i-1)*channels)))
+ break;
+ }
+ else
+ {
+ if ((GetPixelBlue(image,p+(i*channels)) !=
+ GetPixelBlue(image,p+((i-1)*channels))) ||
+ (GetPixelGreen(image,p+(i*channels)) !=
+ GetPixelGreen(image,p+((i-1)*channels))) ||
+ (GetPixelRed(image,p+(i*channels)) !=
+ GetPixelRed(image,p+((i-1)*channels))))
+ break;
+ if ((image->alpha_trait == BlendPixelTrait) &&
+ (GetPixelAlpha(image,p+(i*channels)) !=
+ GetPixelAlpha(image,p+(i-1)*channels)))
+ break;
+ }
+ i++;
}
- p+=GetPixelChannels(image);
- }
- (void) WriteBlob(image,(size_t) (q-targa_pixels),targa_pixels);
+ if (i < 3)
+ {
+ count+=i;
+ p+=(i*channels);
+ }
+ if ((i >= 3) || (count == 128) ||
+ ((x + i) == (ssize_t) image->columns))
+ {
+ if (count > 0)
+ {
+ WriteBlobByte(image,(unsigned char) (--count));
+ while (count >= 0)
+ {
+ WriteTGAPixel(image,tga_info.image_type,p-((count+1)*
+ channels));
+ count--;
+ }
+ count=0;
+ }
+ }
+ if (i >= 3)
+ {
+ WriteBlobByte(image,(unsigned char) (i-1 | 0x80));
+ WriteTGAPixel(image,tga_info.image_type,p);
+ p+=(i*channels);
+ }
+ x+=i;
+ }
+ }
+ else
+ {
+ for (x=0; x < (ssize_t) image->columns; x++)
+ {
+ WriteTGAPixel(image,tga_info.image_type,p);
+ p+=channels;
+ }
+ }
if (image->previous == (Image *) NULL)
{
status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
break;
}
}
- targa_pixels=(unsigned char *) RelinquishMagickMemory(targa_pixels);
(void) CloseBlob(image);
return(MagickTrue);
}