% Read/Write Truevision Targa Image Format %
% %
% Software Design %
-% John Cristy %
+% Cristy %
% July 1992 %
% %
% %
-% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2018 ImageMagick Studio LLC, a non-profit organization %
% dedicated to making software imaging solutions freely available. %
% %
% You may not use this file except in compliance with the License. You may %
% obtain a copy of the License at %
% %
-% http://www.imagemagick.org/script/license.php %
+% https://www.imagemagick.org/script/license.php %
% %
% Unless required by applicable law or agreed to in writing, software %
% distributed under the License is distributed on an "AS IS" BASIS, %
Include declarations.
*/
#include "MagickCore/studio.h"
+#include "MagickCore/artifact.h"
#include "MagickCore/attribute.h"
#include "MagickCore/blob.h"
#include "MagickCore/blob-private.h"
#include "MagickCore/memory_.h"
#include "MagickCore/monitor.h"
#include "MagickCore/monitor-private.h"
+#include "MagickCore/option.h"
#include "MagickCore/pixel-accessor.h"
#include "MagickCore/property.h"
#include "MagickCore/quantum-private.h"
#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;
Open image file.
*/
assert(image_info != (const ImageInfo *) NULL);
- assert(image_info->signature == MagickSignature);
+ assert(image_info->signature == MagickCoreSignature);
if (image_info->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
image_info->filename);
assert(exception != (ExceptionInfo *) NULL);
- assert(exception->signature == MagickSignature);
+ assert(exception->signature == MagickCoreSignature);
image=AcquireImage(image_info,exception);
status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
if (status == MagickFalse)
*/
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) &&
image->columns=tga_info.width;
image->rows=tga_info.height;
alpha_bits=(tga_info.attributes & 0x0FU);
- image->alpha_trait=(alpha_bits > 0) || (tga_info.bits_per_pixel == 32) ?
- MagickTrue : MagickFalse;
+ image->alpha_trait=(alpha_bits > 0) || (tga_info.bits_per_pixel == 32) ||
+ (tga_info.colormap_size == 32) ? BlendPixelTrait : UndefinedPixelTrait;
if ((tga_info.image_type != TGAColormap) &&
(tga_info.image_type != TGARLEColormap))
image->depth=(size_t) ((tga_info.bits_per_pixel <= 8) ? 8 :
- (tga_info.bits_per_pixel <= 16) ? 5 :
- (tga_info.bits_per_pixel == 24) ? 8 :
- (tga_info.bits_per_pixel == 32) ? 8 : 8);
+ (tga_info.bits_per_pixel <= 16) ? 5 : 8);
else
image->depth=(size_t) ((tga_info.colormap_size <= 8) ? 8 :
- (tga_info.colormap_size <= 16) ? 5 :
- (tga_info.colormap_size == 24) ? 8 :
- (tga_info.colormap_size == 32) ? 8 : 8);
+ (tga_info.colormap_size <= 16) ? 5 : 8);
if ((tga_info.image_type == TGAColormap) ||
(tga_info.image_type == TGAMonochrome) ||
(tga_info.image_type == TGARLEColormap) ||
image->storage_class=PseudoClass;
image->compression=NoCompression;
if ((tga_info.image_type == TGARLEColormap) ||
- (tga_info.image_type == TGARLEMonochrome))
+ (tga_info.image_type == TGARLEMonochrome) ||
+ (tga_info.image_type == TGARLERGB))
image->compression=RLECompression;
if (image->storage_class == PseudoClass)
{
if (tga_info.colormap_type != 0)
- image->colors=tga_info.colormap_length;
+ image->colors=tga_info.colormap_index+tga_info.colormap_length;
else
{
size_t
one=1;
image->colors=one << tga_info.bits_per_pixel;
+ if (image->colors > GetBlobSize(image))
+ ThrowReaderException(CorruptImageError,
+ "InsufficientImageDataInFile");
if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
}
*/
length=(size_t) tga_info.id_length;
comment=(char *) NULL;
- if (~length >= (MaxTextExtent-1))
- comment=(char *) AcquireQuantumMemory(length+MaxTextExtent,
+ if (~length >= (MagickPathExtent-1))
+ comment=(char *) AcquireQuantumMemory(length+MagickPathExtent,
sizeof(*comment));
if (comment == (char *) NULL)
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
- count=ReadBlob(image,tga_info.id_length,(unsigned char *) comment);
- comment[tga_info.id_length]='\0';
- (void) SetImageProperty(image,"comment",comment,exception);
+ count=ReadBlob(image,length,(unsigned char *) comment);
+ if (count == (ssize_t) length)
+ {
+ comment[length]='\0';
+ (void) SetImageProperty(image,"comment",comment,exception);
+ }
comment=DestroyString(comment);
}
- (void) ResetMagickMemory(&pixel,0,sizeof(pixel));
- pixel.alpha=(Quantum) OpaqueAlpha;
+ if (tga_info.attributes & (1UL << 4))
+ {
+ if (tga_info.attributes & (1UL << 5))
+ image->orientation=TopRightOrientation;
+ else
+ image->orientation=BottomRightOrientation;
+ }
+ else
+ {
+ if (tga_info.attributes & (1UL << 5))
+ image->orientation=TopLeftOrientation;
+ else
+ image->orientation=BottomLeftOrientation;
+ }
+ if (image_info->ping != MagickFalse)
+ {
+ (void) CloseBlob(image);
+ return(image);
+ }
+ status=SetImageExtent(image,image->columns,image->rows,exception);
+ if (status == MagickFalse)
+ return(DestroyImageList(image));
+ (void) memset(&pixel,0,sizeof(pixel));
+ pixel.alpha=(MagickRealType) OpaqueAlpha;
if (tga_info.colormap_type != 0)
{
/*
Read TGA raster colormap.
*/
+ if (image->colors < tga_info.colormap_index)
+ image->colors=tga_info.colormap_index;
if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
- for (i=0; i < (ssize_t) image->colors; i++)
+ for (i=0; i < (ssize_t) tga_info.colormap_index; i++)
+ image->colormap[i]=pixel;
+ for ( ; i < (ssize_t) image->colors; i++)
{
switch (tga_info.colormap_size)
{
/*
Gray scale.
*/
- pixel.red=ScaleCharToQuantum((unsigned char) ReadBlobByte(image));
+ pixel.red=(MagickRealType) ScaleCharToQuantum((unsigned char)
+ ReadBlobByte(image));
pixel.green=pixel.red;
pixel.blue=pixel.red;
break;
j=(unsigned char) ReadBlobByte(image);
k=(unsigned char) ReadBlobByte(image);
range=GetQuantumRange(5UL);
- pixel.red=ScaleAnyToQuantum(1UL*(k & 0x7c) >> 2,range);
- pixel.green=ScaleAnyToQuantum((1UL*(k & 0x03) << 3)+
- (1UL*(j & 0xe0) >> 5),range);
- pixel.blue=ScaleAnyToQuantum(1UL*(j & 0x1f),range);
+ pixel.red=(MagickRealType) ScaleAnyToQuantum(1UL*(k & 0x7c) >> 2,
+ range);
+ pixel.green=(MagickRealType) ScaleAnyToQuantum((1UL*(k & 0x03)
+ << 3)+(1UL*(j & 0xe0) >> 5),range);
+ pixel.blue=(MagickRealType) ScaleAnyToQuantum(1UL*(j & 0x1f),range);
break;
}
case 24:
- case 32:
{
/*
8 bits each of blue, green and red.
*/
- pixel.blue=ScaleCharToQuantum((unsigned char) ReadBlobByte(image));
- pixel.green=ScaleCharToQuantum((unsigned char) ReadBlobByte(image));
- pixel.red=ScaleCharToQuantum((unsigned char) ReadBlobByte(image));
+ pixel.blue=(MagickRealType) ScaleCharToQuantum((unsigned char)
+ ReadBlobByte(image));
+ pixel.green=(MagickRealType) ScaleCharToQuantum((unsigned char)
+ ReadBlobByte(image));
+ pixel.red=(MagickRealType) ScaleCharToQuantum((unsigned char)
+ ReadBlobByte(image));
+ break;
+ }
+ case 32:
+ {
+ /*
+ 8 bits each of blue, green, red, and alpha.
+ */
+ pixel.blue=(MagickRealType) ScaleCharToQuantum((unsigned char)
+ ReadBlobByte(image));
+ pixel.green=(MagickRealType) ScaleCharToQuantum((unsigned char)
+ ReadBlobByte(image));
+ pixel.red=(MagickRealType) ScaleCharToQuantum((unsigned char)
+ ReadBlobByte(image));
+ pixel.alpha=(MagickRealType) ScaleCharToQuantum((unsigned char)
+ ReadBlobByte(image));
break;
}
}
else
{
count=ReadBlob(image,1,&runlength);
- if (count == 0)
+ if (count != 1)
ThrowReaderException(CorruptImageError,"UnableToReadImageData");
flag=runlength & 0x80;
if (flag != 0)
/*
Gray scale.
*/
- index=(Quantum) ReadBlobByte(image);
+ if (ReadBlob(image,1,pixels) != 1)
+ ThrowReaderException(CorruptImageError,"UnableToReadImageData");
+ index=(Quantum) pixels[0];
if (tga_info.colormap_type != 0)
pixel=image->colormap[(ssize_t) ConstrainColormapIndex(image,
- 1UL*index,exception)];
+ (ssize_t) index,exception)];
else
{
- pixel.red=ScaleCharToQuantum((unsigned char) index);
- pixel.green=ScaleCharToQuantum((unsigned char) index);
- pixel.blue=ScaleCharToQuantum((unsigned char) index);
+ pixel.red=(MagickRealType) ScaleCharToQuantum((unsigned char)
+ index);
+ pixel.green=(MagickRealType) ScaleCharToQuantum((unsigned char)
+ index);
+ pixel.blue=(MagickRealType) ScaleCharToQuantum((unsigned char)
+ index);
}
break;
}
j=pixels[0];
k=pixels[1];
range=GetQuantumRange(5UL);
- pixel.red=ScaleAnyToQuantum(1UL*(k & 0x7c) >> 2,range);
- pixel.green=ScaleAnyToQuantum((1UL*(k & 0x03) << 3)+
- (1UL*(j & 0xe0) >> 5),range);
- pixel.blue=ScaleAnyToQuantum(1UL*(j & 0x1f),range);
- if (image->alpha_trait == BlendPixelTrait)
- pixel.alpha=(k & 0x80) == 0 ? (Quantum) OpaqueAlpha : (Quantum)
- TransparentAlpha;
+ pixel.red=(MagickRealType) ScaleAnyToQuantum(1UL*(k & 0x7c) >> 2,
+ range);
+ pixel.green=(MagickRealType) ScaleAnyToQuantum((1UL*
+ (k & 0x03) << 3)+(1UL*(j & 0xe0) >> 5),range);
+ pixel.blue=(MagickRealType) ScaleAnyToQuantum(1UL*(j & 0x1f),range);
+ if (image->alpha_trait != UndefinedPixelTrait)
+ pixel.alpha=(MagickRealType) ((k & 0x80) == 0 ? (Quantum)
+ TransparentAlpha : (Quantum) OpaqueAlpha);
if (image->storage_class == PseudoClass)
- index=ConstrainColormapIndex(image,((size_t) k << 8)+j,exception);
+ index=(Quantum) ConstrainColormapIndex(image,((ssize_t) (k << 8))+
+ j,exception);
break;
}
case 24:
*/
if (ReadBlob(image,3,pixels) != 3)
ThrowReaderException(CorruptImageError,"UnableToReadImageData");
- pixel.blue=ScaleCharToQuantum(pixels[0]);
- pixel.green=ScaleCharToQuantum(pixels[1]);
- pixel.red=ScaleCharToQuantum(pixels[2]);
+ pixel.blue=(MagickRealType) ScaleCharToQuantum(pixels[0]);
+ pixel.green=(MagickRealType) ScaleCharToQuantum(pixels[1]);
+ pixel.red=(MagickRealType) ScaleCharToQuantum(pixels[2]);
break;
}
case 32:
*/
if (ReadBlob(image,4,pixels) != 4)
ThrowReaderException(CorruptImageError,"UnableToReadImageData");
- pixel.blue=ScaleCharToQuantum(pixels[0]);
- pixel.green=ScaleCharToQuantum(pixels[1]);
- pixel.red=ScaleCharToQuantum(pixels[2]);
- pixel.alpha=ScaleCharToQuantum(pixels[3]);
+ pixel.blue=(MagickRealType) ScaleCharToQuantum(pixels[0]);
+ pixel.green=(MagickRealType) ScaleCharToQuantum(pixels[1]);
+ pixel.red=(MagickRealType) ScaleCharToQuantum(pixels[2]);
+ pixel.alpha=(MagickRealType) ScaleCharToQuantum(pixels[3]);
break;
}
}
ThrowReaderException(CorruptImageError,"UnableToReadImageData");
if (image->storage_class == PseudoClass)
SetPixelIndex(image,index,q);
- SetPixelRed(image,pixel.red,q);
- SetPixelGreen(image,pixel.green,q);
- SetPixelBlue(image,pixel.blue,q);
- if (image->alpha_trait == BlendPixelTrait)
- SetPixelAlpha(image,pixel.alpha,q);
+ SetPixelRed(image,ClampToQuantum(pixel.red),q);
+ SetPixelGreen(image,ClampToQuantum(pixel.green),q);
+ SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
+ if (image->alpha_trait != UndefinedPixelTrait)
+ SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
q+=GetPixelChannels(image);
}
- if (((unsigned char) (tga_info.attributes & 0xc0) >> 6) == 4)
- offset+=4;
- else
+ /*
+ if (((unsigned char) (tga_info.attributes & 0xc0) >> 6) == 4)
+ offset+=4;
+ else
+ */
if (((unsigned char) (tga_info.attributes & 0xc0) >> 6) == 2)
offset+=2;
else
MagickInfo
*entry;
- entry=SetMagickInfo("ICB");
+ entry=AcquireMagickInfo("TGA","ICB","Truevision Targa image");
entry->decoder=(DecodeImageHandler *) ReadTGAImage;
entry->encoder=(EncodeImageHandler *) WriteTGAImage;
- entry->adjoin=MagickFalse;
- entry->description=ConstantString("Truevision Targa image");
- entry->module=ConstantString("TGA");
+ entry->flags|=CoderDecoderSeekableStreamFlag;
+ entry->flags^=CoderAdjoinFlag;
(void) RegisterMagickInfo(entry);
- entry=SetMagickInfo("TGA");
+ entry=AcquireMagickInfo("TGA","TGA","Truevision Targa image");
entry->decoder=(DecodeImageHandler *) ReadTGAImage;
entry->encoder=(EncodeImageHandler *) WriteTGAImage;
- entry->adjoin=MagickFalse;
- entry->description=ConstantString("Truevision Targa image");
- entry->module=ConstantString("TGA");
+ entry->flags|=CoderDecoderSeekableStreamFlag;
+ entry->flags^=CoderAdjoinFlag;
(void) RegisterMagickInfo(entry);
- entry=SetMagickInfo("VDA");
+ entry=AcquireMagickInfo("TGA","VDA","Truevision Targa image");
entry->decoder=(DecodeImageHandler *) ReadTGAImage;
entry->encoder=(EncodeImageHandler *) WriteTGAImage;
- entry->adjoin=MagickFalse;
- entry->description=ConstantString("Truevision Targa image");
- entry->module=ConstantString("TGA");
+ entry->flags|=CoderDecoderSeekableStreamFlag;
+ entry->flags^=CoderAdjoinFlag;
(void) RegisterMagickInfo(entry);
- entry=SetMagickInfo("VST");
+ entry=AcquireMagickInfo("TGA","VST","Truevision Targa image");
entry->decoder=(DecodeImageHandler *) ReadTGAImage;
entry->encoder=(EncodeImageHandler *) WriteTGAImage;
- entry->adjoin=MagickFalse;
- entry->description=ConstantString("Truevision Targa image");
- entry->module=ConstantString("TGA");
+ entry->flags|=CoderDecoderSeekableStreamFlag;
+ entry->flags^=CoderAdjoinFlag;
(void) RegisterMagickInfo(entry);
return(MagickImageCoderSignature);
}
% o image: The image.
%
*/
-
-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 QuantumAny range,const double midpoint)
{
- if (x < y)
- return(x);
- return(y);
+ 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
+ if (image->depth == 5)
+ {
+ unsigned char
+ green,
+ value;
+
+ green=(unsigned char) ScaleQuantumToAny(GetPixelGreen(image,p),
+ range);
+ value=((unsigned char) ScaleQuantumToAny(GetPixelBlue(image,p),
+ range)) | ((green & 0x07) << 5);
+ (void) WriteBlobByte(image,value);
+ value=(((image->alpha_trait != UndefinedPixelTrait) &&
+ ((double) GetPixelAlpha(image,p) > midpoint)) ? 0x80 : 0) |
+ ((unsigned char) ScaleQuantumToAny(GetPixelRed(image,p),range) <<
+ 2) | ((green & 0x18) >> 3);
+ (void) WriteBlobByte(image,value);
+ }
+ 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 != UndefinedPixelTrait)
+ (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;
+ *comment;
+
+ const double
+ midpoint = QuantumRange/2.0;
MagickBooleanType
status;
+ QuantumAny
+ range;
+
register const Quantum
*p;
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.
*/
assert(image_info != (const ImageInfo *) NULL);
- assert(image_info->signature == MagickSignature);
+ assert(image_info->signature == MagickCoreSignature);
assert(image != (Image *) NULL);
- assert(image->signature == MagickSignature);
+ assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(exception != (ExceptionInfo *) NULL);
- assert(exception->signature == MagickSignature);
+ assert(exception->signature == MagickCoreSignature);
status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
if (status == MagickFalse)
return(status);
*/
if ((image->columns > 65535L) || (image->rows > 65535L))
ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
- if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
- (void) TransformImageColorspace(image,sRGBColorspace,exception);
- targa_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;
+ (void) TransformImageColorspace(image,sRGBColorspace,exception);
+ compression=image->compression;
+ if (image_info->compression != UndefinedCompression)
+ compression=image_info->compression;
+ range=GetQuantumRange(5UL);
+ tga_info.id_length=0;
+ comment=GetImageProperty(image,"comment",exception);
+ if (comment != (const char *) NULL)
+ tga_info.id_length=(unsigned char) MagickMin(strlen(comment),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 != TrueColorAlphaType) &&
(image_info->type != PaletteType) &&
- (image->alpha_trait != BlendPixelTrait) &&
- (IsImageGray(image,exception) != MagickFalse))
- targa_info.image_type=TargaMonochrome;
+ (image->alpha_trait == UndefinedPixelTrait) &&
+ (SetImageGray(image,exception) != MagickFalse))
+ 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;
- if (image->alpha_trait == BlendPixelTrait)
+ tga_info.image_type=compression == RLECompression ? TGARLERGB : TGARGB;
+ if (image_info->depth == 5)
{
- targa_info.bits_per_pixel=32;
- targa_info.attributes=8; /* # of alpha bits */
+ tga_info.bits_per_pixel=16;
+ if (image->alpha_trait != UndefinedPixelTrait)
+ tga_info.attributes=1; /* # of alpha bits */
+ }
+ else
+ {
+ tga_info.bits_per_pixel=24;
+ if (image->alpha_trait != UndefinedPixelTrait)
+ {
+ 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;
+ if (image_info->depth == 5)
+ tga_info.colormap_size=16;
+ else
+ tga_info.colormap_size=24;
}
+ if ((image->orientation == BottomRightOrientation) ||
+ (image->orientation == TopRightOrientation))
+ tga_info.attributes|=(1UL << 4);
+ if ((image->orientation == TopLeftOrientation) ||
+ (image->orientation == TopRightOrientation))
+ tga_info.attributes|=(1UL << 5);
/*
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 *)
- value);
- if (targa_info.image_type == TargaColormap)
+ (void) WriteBlobByte(image,tga_info.id_length);
+ (void) WriteBlobByte(image,tga_info.colormap_type);
+ (void) WriteBlobByte(image,(unsigned char) 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 *) comment);
+ 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)
- targa_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(image->colormap[i].blue);
- *q++=ScaleQuantumToChar(image->colormap[i].green);
- *q++=ScaleQuantumToChar(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 != UndefinedPixelTrait) && ((double)
+ ClampToQuantum(image->colormap[i].alpha) > midpoint)) ? 0x80 : 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*targa_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);
}
/*
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(GetPixelIntensity(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 != UndefinedPixelTrait) &&
+ (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)
+ {
+ (void) WriteBlobByte(image,(unsigned char) (--count));
+ while (count >= 0)
+ {
+ WriteTGAPixel(image,tga_info.image_type,p-((count+1)*
+ channels),range,midpoint);
+ count--;
+ }
+ count=0;
+ }
+ }
+ if (i >= 3)
+ {
+ (void) WriteBlobByte(image,(unsigned char) ((i-1) | 0x80));
+ WriteTGAPixel(image,tga_info.image_type,p,range,midpoint);
+ p+=(i*channels);
+ }
+ x+=i;
+ }
+ }
+ else
+ {
+ for (x=0; x < (ssize_t) image->columns; x++)
+ {
+ WriteTGAPixel(image,tga_info.image_type,p,range,midpoint);
+ 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);
}