% Read/Write Palm Database ImageViewer Image Format %
% %
% Software Design %
-% John Cristy %
+% Cristy %
% July 1992 %
% %
% %
-% Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2017 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, %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%
- 20071202 TS * rewrote RLE decoder - old version could cause buffer overflows
- * failure of RLE decoding now thows error RLEDecoderError
- * fixed bug in RLE decoding - now all rows are decoded, not just
- the first one
- * fixed bug in reader - record offsets now handled correctly
- * fixed bug in reader - only bits 0..2 indicate compression type
- * in writer: now using image color count instead of depth
+% 20071202 TS * rewrote RLE decoder - old version could cause buffer overflows
+% * failure of RLE decoding now thows error RLEDecoderError
+% * fixed bug in RLE decoding - now all rows are decoded, not just
+% the first one
+% * fixed bug in reader - record offsets now handled correctly
+% * fixed bug in reader - only bits 0..2 indicate compression type
+% * in writer: now using image color count instead of depth
*/
\f
/*
#include "MagickCore/color-private.h"
#include "MagickCore/colormap.h"
#include "MagickCore/colorspace.h"
+#include "MagickCore/colorspace-private.h"
#include "MagickCore/constitute.h"
#include "MagickCore/exception.h"
#include "MagickCore/exception-private.h"
{
char
name[32],
- version,
- type;
+ version;
size_t
reserved_1,
reserved_2;
short int
- x_anchor,
- y_anchor,
width,
height;
+
+ unsigned char
+ type;
+
+ unsigned short
+ x_anchor,
+ y_anchor;
} PDBImage;
/*
Forward declarations.
*/
static MagickBooleanType
- WritePDBImage(const ImageInfo *,Image *);
+ WritePDBImage(const ImageInfo *,Image *,ExceptionInfo *);
\f
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
static Image *ReadPDBImage(const ImageInfo *image_info,ExceptionInfo *exception)
{
unsigned char
- attributes, /* TS */
+ attributes,
tag[3];
Image
size_t
bits_per_pixel,
- num_pad_bytes, /* TS */
+ num_pad_bytes,
one,
packets;
ssize_t
count,
- img_offset, /* TS */
+ img_offset,
comment_offset = 0,
y;
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);
- image=AcquireImage(image_info);
+ assert(exception->signature == MagickCoreSignature);
+ image=AcquireImage(image_info,exception);
status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
if (status == MagickFalse)
{
/*
Determine if this a PDB image file.
*/
- count=ReadBlob(image,32,(unsigned char *) pdb_info.name);
+ count=ReadBlob(image,sizeof(pdb_info.name),(unsigned char *) pdb_info.name);
+ if (count != sizeof(pdb_info.name))
+ ThrowReaderException(CorruptImageError,"ImproperImageHeader");
pdb_info.attributes=(short) ReadBlobMSBShort(image);
pdb_info.version=(short) ReadBlobMSBShort(image);
pdb_info.create_time=ReadBlobMSBLong(image);
pdb_info.modify_number=ReadBlobMSBLong(image);
pdb_info.application_info=ReadBlobMSBLong(image);
pdb_info.sort_info=ReadBlobMSBLong(image);
- count=ReadBlob(image,4,(unsigned char *) pdb_info.type);
- count=ReadBlob(image,4,(unsigned char *) pdb_info.id);
- if ((count == 0) || (memcmp(pdb_info.type,"vIMG",4) != 0) ||
- (memcmp(pdb_info.id,"View",4) != 0))
- ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+ (void) ReadBlob(image,4,(unsigned char *) pdb_info.type);
+ (void) ReadBlob(image,4,(unsigned char *) pdb_info.id);
pdb_info.seed=ReadBlobMSBLong(image);
pdb_info.next_record=ReadBlobMSBLong(image);
pdb_info.number_records=(short) ReadBlobMSBShort(image);
+ if ((memcmp(pdb_info.type,"vIMG",4) != 0) ||
+ (memcmp(pdb_info.id,"View",4) != 0))
+ ThrowReaderException(CorruptImageError,"ImproperImageHeader");
if (pdb_info.next_record != 0)
ThrowReaderException(CoderError,"MultipleRecordListNotSupported");
/*
Read record header.
*/
- img_offset=(int) ReadBlobMSBLong(image); /* TS */
+ img_offset=(ssize_t) ReadBlobMSBSignedLong(image);
attributes=(unsigned char) ReadBlobByte(image);
(void) attributes;
count=ReadBlob(image,3,(unsigned char *) tag);
ThrowReaderException(CorruptImageError,"CorruptImage");
if (pdb_info.number_records > 1)
{
- comment_offset=(int) ReadBlobMSBLong(image);
+ comment_offset=(ssize_t) ReadBlobMSBSignedLong(image);
attributes=(unsigned char) ReadBlobByte(image);
count=ReadBlob(image,3,(unsigned char *) tag);
if (count != 3 || memcmp(tag,"\x6f\x80\x01",3) != 0)
ThrowReaderException(CorruptImageError,"CorruptImage");
}
num_pad_bytes = (size_t) (img_offset - TellBlob( image ));
- while (num_pad_bytes--) ReadBlobByte( image );
+ while (num_pad_bytes-- != 0)
+ {
+ int
+ c;
+
+ c=ReadBlobByte(image);
+ if (c == EOF)
+ break;
+ }
/*
Read image header.
*/
- count=ReadBlob(image,32,(unsigned char *) pdb_image.name);
+ count=ReadBlob(image,sizeof(pdb_image.name),(unsigned char *) pdb_image.name);
+ if (count != sizeof(pdb_image.name))
+ ThrowReaderException(CorruptImageError,"ImproperImageHeader");
pdb_image.version=ReadBlobByte(image);
- pdb_image.type=ReadBlobByte(image);
+ pdb_image.type=(unsigned char) (ReadBlobByte(image));
pdb_image.reserved_1=ReadBlobMSBLong(image);
pdb_image.note=ReadBlobMSBLong(image);
pdb_image.x_last=(short) ReadBlobMSBShort(image);
pdb_image.y_last=(short) ReadBlobMSBShort(image);
pdb_image.reserved_2=ReadBlobMSBLong(image);
- pdb_image.x_anchor=(short) ReadBlobMSBShort(image);
- pdb_image.y_anchor=(short) ReadBlobMSBShort(image);
+ pdb_image.x_anchor=ReadBlobMSBShort(image);
+ pdb_image.y_anchor=ReadBlobMSBShort(image);
pdb_image.width=(short) ReadBlobMSBShort(image);
pdb_image.height=(short) ReadBlobMSBShort(image);
/*
image->storage_class=PseudoClass;
bits_per_pixel=pdb_image.type == 0 ? 2UL : pdb_image.type == 2 ? 4UL : 1UL;
one=1;
- if (AcquireImageColormap(image,one << bits_per_pixel) == MagickFalse)
+ if (AcquireImageColormap(image,one << bits_per_pixel,exception) == MagickFalse)
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
if (image_info->ping != MagickFalse)
{
(void) CloseBlob(image);
return(GetFirstImageInList(image));
}
- packets=bits_per_pixel*image->columns/8;
- pixels=(unsigned char *) AcquireQuantumMemory(packets+256UL,image->rows*
+ status=SetImageExtent(image,image->columns,image->rows,exception);
+ if (status == MagickFalse)
+ return(DestroyImageList(image));
+ packets=(bits_per_pixel*image->columns+7)/8;
+ pixels=(unsigned char *) AcquireQuantumMemory(packets+257UL,image->rows*
sizeof(*pixels));
if (pixels == (unsigned char *) NULL)
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
-
- switch (pdb_image.version & 7) /* TS */
+ switch (pdb_image.version & 0x07)
{
case 0:
{
image->compression=NoCompression;
- count=(ssize_t) ReadBlob(image, packets * image -> rows, pixels);
+ count=(ssize_t) ReadBlob(image,packets*image->rows,pixels);
break;
}
case 1:
{
image->compression=RLECompression;
- if (!DecodeImage(image, pixels, packets * image -> rows))
- ThrowReaderException( CorruptImageError, "RLEDecoderError" ); /* TS */
+ if (!DecodeImage(image,pixels,packets*image->rows))
+ {
+ pixels=(unsigned char *) RelinquishMagickMemory(pixels);
+ ThrowReaderException(CorruptImageError,"RLEDecoderError");
+ }
break;
}
default:
+ {
+ pixels=(unsigned char *) RelinquishMagickMemory(pixels);
ThrowReaderException(CorruptImageError,
- "UnrecognizedImageCompressionType" );
+ "UnrecognizedImageCompressionType");
+ }
}
p=pixels;
switch (bits_per_pixel)
for (y=0; y < (ssize_t) image->rows; y++)
{
q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
- if (q == (const Quantum *) NULL)
+ if (q == (Quantum *) NULL)
break;
for (x=0; x < ((ssize_t) image->columns-7); x+=8)
{
if (status == MagickFalse)
break;
}
- (void) SyncImage(image);
+ (void) SyncImage(image,exception);
break;
}
case 2:
for (y=0; y < (ssize_t) image->rows; y++)
{
q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
- if (q == (const Quantum *) NULL)
+ if (q == (Quantum *) NULL)
break;
- for (x=0; x < (ssize_t) image->columns; x+=4)
+ for (x=0; x < (ssize_t) image->columns-3; x+=4)
{
- index=ConstrainColormapIndex(image,3UL-((*p >> 6) & 0x03));
+ index=ConstrainColormapIndex(image,3UL-((*p >> 6) & 0x03),exception);
SetPixelIndex(image,index,q);
q+=GetPixelChannels(image);
- index=ConstrainColormapIndex(image,3UL-((*p >> 4) & 0x03));
+ index=ConstrainColormapIndex(image,3UL-((*p >> 4) & 0x03),exception);
SetPixelIndex(image,index,q);
q+=GetPixelChannels(image);
- index=ConstrainColormapIndex(image,3UL-((*p >> 2) & 0x03));
+ index=ConstrainColormapIndex(image,3UL-((*p >> 2) & 0x03),exception);
SetPixelIndex(image,index,q);
q+=GetPixelChannels(image);
- index=ConstrainColormapIndex(image,3UL-((*p) & 0x03));
+ index=ConstrainColormapIndex(image,3UL-((*p) & 0x03),exception);
SetPixelIndex(image,index,q);
p++;
q+=GetPixelChannels(image);
if (status == MagickFalse)
break;
}
- (void) SyncImage(image);
+ (void) SyncImage(image,exception);
break;
}
case 4:
for (y=0; y < (ssize_t) image->rows; y++)
{
q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
- if (q == (const Quantum *) NULL)
+ if (q == (Quantum *) NULL)
break;
- for (x=0; x < (ssize_t) image->columns; x+=2)
+ for (x=0; x < (ssize_t) image->columns-1; x+=2)
{
- index=ConstrainColormapIndex(image,15UL-((*p >> 4) & 0x0f));
+ index=ConstrainColormapIndex(image,15UL-((*p >> 4) & 0x0f),exception);
SetPixelIndex(image,index,q);
q+=GetPixelChannels(image);
- index=ConstrainColormapIndex(image,15UL-((*p) & 0x0f));
+ index=ConstrainColormapIndex(image,15UL-((*p) & 0x0f),exception);
SetPixelIndex(image,index,q);
p++;
q+=GetPixelChannels(image);
if (status == MagickFalse)
break;
}
- (void) SyncImage(image);
+ (void) SyncImage(image,exception);
break;
}
default:
+ {
+ pixels=(unsigned char *) RelinquishMagickMemory(pixels);
ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+ }
}
-
pixels=(unsigned char *) RelinquishMagickMemory(pixels);
if (EOFBlob(image) != MagickFalse)
ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
image->filename);
- if (pdb_info.number_records > 1) /* TS */
+ if (pdb_info.number_records > 1)
{
char
*comment;
length;
num_pad_bytes = (size_t) (comment_offset - TellBlob( image ));
- while (num_pad_bytes--) ReadBlobByte( image );
+ while (num_pad_bytes-- != 0)
+ {
+ int
+ c;
+
+ c=ReadBlobByte(image);
+ if (c == EOF)
+ break;
+ }
/*
Read comment.
*/
c=ReadBlobByte(image);
- length=MaxTextExtent;
+ length=MagickPathExtent;
comment=AcquireString((char *) NULL);
for (p=comment; c != EOF; p++)
{
- if ((size_t) (p-comment+MaxTextExtent) >= length)
+ if ((size_t) (p-comment+MagickPathExtent) >= length)
{
*p='\0';
length<<=1;
- length+=MaxTextExtent;
- comment=(char *) ResizeQuantumMemory(comment,length+MaxTextExtent,
+ length+=MagickPathExtent;
+ comment=(char *) ResizeQuantumMemory(comment,length+MagickPathExtent,
sizeof(*comment));
if (comment == (char *) NULL)
break;
*p='\0';
if (comment == (char *) NULL)
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
- (void) SetImageProperty(image,"comment",comment);
+ (void) SetImageProperty(image,"comment",comment,exception);
comment=DestroyString(comment);
}
(void) CloseBlob(image);
MagickInfo
*entry;
- entry=SetMagickInfo("PDB");
+ entry=AcquireMagickInfo("PDB","PDB","Palm Database ImageViewer Format");
entry->decoder=(DecodeImageHandler *) ReadPDBImage;
entry->encoder=(EncodeImageHandler *) WritePDBImage;
entry->magick=(IsImageFormatHandler *) IsPDB;
- entry->description=ConstantString("Palm Database ImageViewer Format");
- entry->module=ConstantString("PDB");
(void) RegisterMagickInfo(entry);
return(MagickImageCoderSignature);
}
%
% The format of the WritePDBImage method is:
%
-% MagickBooleanType WritePDBImage(const ImageInfo *image_info,Image *image)
+% MagickBooleanType WritePDBImage(const ImageInfo *image_info,
+% Image *image,ExceptionInfo *exception)
%
% A description of each parameter follows.
%
%
% o image: The image.
%
+% o exception: return any errors or warnings in this structure.
%
*/
return(destination);
}
-static MagickBooleanType WritePDBImage(const ImageInfo *image_info,Image *image)
+static MagickBooleanType WritePDBImage(const ImageInfo *image_info,Image *image,
+ ExceptionInfo *exception)
{
const char
*comment;
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);
- status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
+ assert(exception != (ExceptionInfo *) NULL);
+ assert(exception->signature == MagickCoreSignature);
+ status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
if (status == MagickFalse)
return(status);
- if (image->colorspace != RGBColorspace)
- (void) TransformImageColorspace(image,RGBColorspace);
-
- if (image -> colors <= 2 || GetImageType( image, &image -> exception ) == BilevelType) { /* TS */
- bits_per_pixel = 1;
- } else if (image -> colors <= 4) {
- bits_per_pixel = 2;
- } else if (image -> colors <= 8) {
- bits_per_pixel = 3;
+ (void) TransformImageColorspace(image,sRGBColorspace,exception);
+ if (SetImageMonochrome(image,exception) != MagickFalse) {
+ bits_per_pixel=1;
+ } else if (image->colors <= 4) {
+ bits_per_pixel=2;
+ } else if (image->colors <= 8) {
+ bits_per_pixel=3;
} else {
- bits_per_pixel = 4;
+ bits_per_pixel=4;
}
-
- (void) ResetMagickMemory(pdb_info.name,0,32);
- (void) CopyMagickString(pdb_info.name,image_info->filename,32);
+ (void) ResetMagickMemory(&pdb_info,0,sizeof(pdb_info));
+ (void) CopyMagickString(pdb_info.name,image_info->filename,
+ sizeof(pdb_info.name));
pdb_info.attributes=0;
pdb_info.version=0;
pdb_info.create_time=time(NULL);
(void) CopyMagickMemory(pdb_info.id,"View",4);
pdb_info.seed=0;
pdb_info.next_record=0;
- comment=GetImageProperty(image,"comment");
+ comment=GetImageProperty(image,"comment",exception);
pdb_info.number_records=(comment == (const char *) NULL ? 1 : 2);
- (void) WriteBlob(image,32,(unsigned char *) pdb_info.name);
+ (void) WriteBlob(image,sizeof(pdb_info.name),(unsigned char *) pdb_info.name);
(void) WriteBlobMSBShort(image,(unsigned short) pdb_info.attributes);
(void) WriteBlobMSBShort(image,(unsigned short) pdb_info.version);
(void) WriteBlobMSBLong(image,(unsigned int) pdb_info.create_time);
(void) WriteBlobMSBLong(image,(unsigned int) pdb_info.seed);
(void) WriteBlobMSBLong(image,(unsigned int) pdb_info.next_record);
(void) WriteBlobMSBShort(image,(unsigned short) pdb_info.number_records);
- (void) CopyMagickString(pdb_image.name,pdb_info.name,32);
+ (void) CopyMagickString(pdb_image.name,pdb_info.name,sizeof(pdb_image.name));
pdb_image.version=1; /* RLE Compressed */
switch (bits_per_pixel)
{
- case 1: pdb_image.type=(char) 0xff; break; /* monochrome */
- case 2: pdb_image.type=(char) 0x00; break; /* 2 bit gray */
- default: pdb_image.type=(char) 0x02; /* 4 bit gray */
+ case 1: pdb_image.type=(unsigned char) 0xff; break; /* monochrome */
+ case 2: pdb_image.type=(unsigned char) 0x00; break; /* 2 bit gray */
+ default: pdb_image.type=(unsigned char) 0x02; /* 4 bit gray */
}
pdb_image.reserved_1=0;
pdb_image.note=0;
pdb_image.x_last=0;
pdb_image.y_last=0;
pdb_image.reserved_2=0;
- pdb_image.x_anchor=(short) 0xffff;
- pdb_image.y_anchor=(short) 0xffff;
+ pdb_image.x_anchor=(unsigned short) 0xffff;
+ pdb_image.y_anchor=(unsigned short) 0xffff;
pdb_image.width=(short) image->columns;
if (image->columns % 16)
pdb_image.width=(short) (16*(image->columns/16+1));
pdb_image.height=(short) image->rows;
- packets=(bits_per_pixel*image->columns/8)*image->rows;
- runlength=(unsigned char *) AcquireQuantumMemory(2UL*packets,
- sizeof(*runlength));
+ packets=((bits_per_pixel*image->columns+7)/8);
+ runlength=(unsigned char *) AcquireQuantumMemory(9UL*packets,
+ image->rows*sizeof(*runlength));
if (runlength == (unsigned char *) NULL)
ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
- buffer=(unsigned char *) AcquireQuantumMemory(256UL,sizeof(*buffer));
+ buffer=(unsigned char *) AcquireQuantumMemory(512,sizeof(*buffer));
if (buffer == (unsigned char *) NULL)
ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
- packet_size=(size_t) (image->depth > 8 ? 2: 1);
+ packet_size=(size_t) (image->depth > 8 ? 2 : 1);
scanline=(unsigned char *) AcquireQuantumMemory(image->columns,packet_size*
sizeof(*scanline));
if (scanline == (unsigned char *) NULL)
ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
- if (image->colorspace != RGBColorspace)
- (void) TransformImageColorspace(image,RGBColorspace);
+ if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
+ (void) TransformImageColorspace(image,sRGBColorspace,exception);
/*
Convert to GRAY raster scanline.
*/
quantum_info=AcquireQuantumInfo(image_info,image);
if (quantum_info == (QuantumInfo *) NULL)
ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
+ status=SetQuantumDepth(image,quantum_info,image->depth > 8 ? 16 : 8);
bits=8/(int) bits_per_pixel-1; /* start at most significant bits */
literal=0;
repeat=0;
buffer[0]=0x00;
for (y=0; y < (ssize_t) image->rows; y++)
{
- p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
+ p=GetVirtualPixels(image,0,y,image->columns,1,exception);
if (p == (const Quantum *) NULL)
break;
(void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
- GrayQuantum,scanline,&image->exception);
- for (x=0; x < pdb_image.width; x++)
+ GrayQuantum,scanline,exception);
+ for (x=0; x < (ssize_t) pdb_image.width; x++)
{
if (x < (ssize_t) image->columns)
buffer[literal+repeat]|=(0xff-scanline[x*packet_size]) >>
}
}
status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
- image->rows);
+ image->rows);
if (status == MagickFalse)
break;
}
/*
Write the Image data.
*/
- (void) WriteBlob(image,32,(unsigned char *) pdb_image.name);
+ (void) WriteBlob(image,sizeof(pdb_image.name),(unsigned char *)
+ pdb_image.name);
(void) WriteBlobByte(image,(unsigned char) pdb_image.version);
- (void) WriteBlobByte(image,(unsigned char) pdb_image.type);
+ (void) WriteBlobByte(image,pdb_image.type);
(void) WriteBlobMSBLong(image,(unsigned int) pdb_image.reserved_1);
(void) WriteBlobMSBLong(image,(unsigned int) pdb_image.note);
(void) WriteBlobMSBShort(image,(unsigned short) pdb_image.x_last);
(void) WriteBlobMSBShort(image,(unsigned short) pdb_image.y_last);
(void) WriteBlobMSBLong(image,(unsigned int) pdb_image.reserved_2);
- (void) WriteBlobMSBShort(image,(unsigned short) pdb_image.x_anchor);
- (void) WriteBlobMSBShort(image,(unsigned short) pdb_image.y_anchor);
+ (void) WriteBlobMSBShort(image,pdb_image.x_anchor);
+ (void) WriteBlobMSBShort(image,pdb_image.y_anchor);
(void) WriteBlobMSBShort(image,(unsigned short) pdb_image.width);
(void) WriteBlobMSBShort(image,(unsigned short) pdb_image.height);
(void) WriteBlob(image,(size_t) (q-runlength),runlength);