[prev in list] [next in list] [prev in thread] [next in thread]
List: imagemagick-developer
Subject: Re: [magick-developers] PDB format enhancements
From: Carl Osterwisch <costerwi () yahoo ! com>
Date: 2002-04-23 20:39:08
[Download RAW message or body]
Here is the patch to enable writing to Palm Pilot PDB files:
--- Bob Friesenhahn <bfriesen@simple.dallas.tx.us> wrote:
> On Wed, 20 Mar 2002, Carl Osterwisch wrote:
>
> > I have updated the Palm Pilot PDB read routine based on file format
> > information which is now publically available. I have also added
> the
> > capability to write files in this format.
> >
> > Assuming anyone else is interested, what is the procedure for me to
> > distribute the updated coder? I have anonymous access to the CVS
> but
> > I'm not sure that will allow me to commit my changes.
>
> You can mail us the output from
>
> cvs diff -c coders/coders/pdb.c
>
> or if this doesn't work, just mail the entire file.
>
> Bob
> ======================================
> Bob Friesenhahn
> bfriesen@simple.dallas.tx.us
> http://www.simplesystems.org/users/bfriesen
>
>
>
__________________________________________________
Do You Yahoo!?
Yahoo! Games - play chess, backgammon, pool and more
http://games.yahoo.com/
["pdb.diff" (text/plain)]
Index: coders/pdb.c
===================================================================
RCS file: /cvsroot/ImageMagick/coders/pdb.c,v
retrieving revision 1.41
diff -c -r1.41 pdb.c
*** coders/pdb.c 2002/04/13 18:04:04 1.41
--- coders/pdb.c 2002/04/23 20:29:56
***************
*** 52,59 ****
--- 52,114 ----
/*
Include declarations.
*/
+ #include <time.h>
#include "studio.h"
+ typedef struct _PDBInfo
+ {
+ char
+ name[32];
+
+ short int
+ attributes,
+ version;
+
+ unsigned long
+ create_time,
+ modify_time,
+ archive_time,
+ modify_number,
+ application_info,
+ sort_info;
+
+ char
+ type[4], /* database type identifier "vIMG" */
+ id[4]; /* database creator identifier "View" */
+
+ unsigned long
+ seed,
+ next_record;
+
+ short int
+ number_records;
+ } PDBInfo;
+
+ typedef struct _PDBImage
+ {
+ char
+ name[32],
+ version,
+ type;
+
+ unsigned long
+ reserved_1,
+ note;
+
+ short int
+ x_last,
+ y_last;
+
+ unsigned long
+ reserved_2;
+
+ short int
+ x_anchor,
+ y_anchor,
+ width,
+ height;
+ } PDBImage;
+
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
***************
*** 188,247 ****
*/
static Image *ReadPDBImage(const ImageInfo *image_info,ExceptionInfo *exception)
{
- typedef struct _PDBInfo
- {
- char
- name[32];
-
- short int
- flags,
- version;
-
- unsigned long
- create_time,
- modify_time,
- archive_time,
- modify_number,
- application_info,
- sort_info;
-
- char
- type[4], /* database type identifier "vIMG" */
- id[4]; /* database creator identifier "View" */
-
- unsigned long
- seed,
- next_record;
-
- short int
- number_records;
- } PDBInfo;
-
- typedef struct _PDBImage
- {
- char
- name[32],
- version,
- type;
- unsigned long
- reserved_1,
- note;
-
- short int
- x_last,
- y_last;
-
- unsigned long
- reserved_2;
-
- short int
- x_anchor,
- y_anchor,
- width,
- height;
- } PDBImage;
-
char
tag[3],
record_type;
--- 243,249 ----
***************
*** 302,308 ****
Determine if this is a PDB image file.
*/
count=ReadBlob(image,32,pdb_info.name);
! pdb_info.flags=ReadBlobMSBShort(image);
pdb_info.version=ReadBlobMSBShort(image);
pdb_info.create_time=ReadBlobMSBLong(image);
pdb_info.modify_time=ReadBlobMSBLong(image);
--- 304,310 ----
Determine if this is a PDB image file.
*/
count=ReadBlob(image,32,pdb_info.name);
! pdb_info.attributes=ReadBlobMSBShort(image);
pdb_info.version=ReadBlobMSBShort(image);
pdb_info.create_time=ReadBlobMSBLong(image);
pdb_info.modify_time=ReadBlobMSBLong(image);
***************
*** 311,329 ****
pdb_info.application_info=ReadBlobMSBLong(image);
pdb_info.sort_info=ReadBlobMSBLong(image);
(void) ReadBlob(image,4,pdb_info.type);
! (void) ReadBlob(image,4,pdb_info.id);
pdb_info.seed=ReadBlobMSBLong(image);
pdb_info.next_record=ReadBlobMSBLong(image);
pdb_info.number_records=ReadBlobMSBShort(image);
! if ((count == 0) || (memcmp(pdb_info.type,"vIMG",4) != 0) ||
! (memcmp(pdb_info.id,"View",4) != 0))
! ThrowReaderException(CorruptImageError,"Not a PDB image file",image);
/*
Read record header.
*/
offset=(long) ReadBlobMSBLong(image);
(void) ReadBlob(image,3,tag);
! record_type=ReadBlobByte(image);
if (((record_type != 0x00) && (record_type != 0x01)) ||
(memcmp(tag,"\x40\x6f\x80",3) != 0))
ThrowReaderException(CorruptImageError,"Corrupt PDB image file",image);
--- 313,341 ----
pdb_info.application_info=ReadBlobMSBLong(image);
pdb_info.sort_info=ReadBlobMSBLong(image);
(void) ReadBlob(image,4,pdb_info.type);
! (void) ReadBlob(image,4,pdb_info.id);
! if (image_info->debug) {
! (void) fprintf(stderr, "pdb_info.name=%s\n", pdb_info.name);
! }
! if ((count == 0) || (memcmp(pdb_info.type,"vIMG",4) != 0) ||
! (memcmp(pdb_info.id,"View",4) != 0))
! ThrowReaderException(CorruptImageWarning,"Not a supported PDB image file",image);
pdb_info.seed=ReadBlobMSBLong(image);
pdb_info.next_record=ReadBlobMSBLong(image);
pdb_info.number_records=ReadBlobMSBShort(image);
! if (image_info->debug) {
! (void) fprintf(stderr, "pdb_info.seed=%ld\n", pdb_info.seed);
! (void) fprintf(stderr, "pdb_info.nextRecordListID=%ld\n", pdb_info.next_record);
! (void) fprintf(stderr, "pdb_info.number_records=%d\n", pdb_info.number_records);
! }
! if (0 != pdb_info.next_record)
! ThrowReaderException(CorruptImageWarning, "Multiple Record List PDB Unsupported", image);
/*
Read record header.
*/
offset=(long) ReadBlobMSBLong(image);
(void) ReadBlob(image,3,tag);
! record_type=ReadBlobByte(image); /* RecordEntry attributes */
if (((record_type != 0x00) && (record_type != 0x01)) ||
(memcmp(tag,"\x40\x6f\x80",3) != 0))
ThrowReaderException(CorruptImageError,"Corrupt PDB image file",image);
***************
*** 380,391 ****
packets=(bits_per_pixel*image->columns/8)*image->rows;
pixels=(unsigned char *) AcquireMemory(packets+256);
if (pixels == (unsigned char *) NULL)
! ThrowReaderException(ResourceLimitError,"Memory allocation failed",image);
! if (pdb_image.version != 0)
! (void) DecodeImage(image,pixels,packets);
! else
! (void) ReadBlob(image,packets,(char *) pixels);
! p=pixels;
switch (bits_per_pixel)
{
case 1:
--- 392,419 ----
packets=(bits_per_pixel*image->columns/8)*image->rows;
pixels=(unsigned char *) AcquireMemory(packets+256);
if (pixels == (unsigned char *) NULL)
! ThrowReaderException(ResourceLimitWarning,"Memory allocation failed",image);
! if (image_info->debug) {
! (void) fprintf(stderr, "pdb_image.version, type: %x, %x\n", pdb_image.version, pdb_image.type);
! (void) fprintf(stderr, "pdb_image.width, height: %d, %d\n", pdb_image.width, pdb_image.height);
! (void) fprintf(stderr, "bits_per_pixel: %d\n", bits_per_pixel);
! (void) fprintf(stderr, "packets: %ld\n", packets);
! }
!
! switch (pdb_image.version) {
! case 0:
! image->compression = NoCompression;
! (void) ReadBlob(image,packets,(char *) pixels);
! break;
! case 1:
! image->compression = RunlengthEncodedCompression;
! (void) DecodeImage(image,pixels,packets);
! break;
! default:
! ThrowReaderException(CorruptImageWarning,"Unknown compression type",image);
! }
!
! p=pixels;
switch (bits_per_pixel)
{
case 1:
***************
*** 520,528 ****
break;
p=comment+strlen(comment);
}
- c=ReadBlobByte(image);
*p=c;
*(p+1)='\0';
}
if (comment == (char *) NULL)
ThrowReaderException(ResourceLimitError,"Memory allocation failed",
--- 548,556 ----
break;
p=comment+strlen(comment);
}
*p=c;
*(p+1)='\0';
+ c=ReadBlobByte(image);
}
if (comment == (char *) NULL)
ThrowReaderException(ResourceLimitError,"Memory allocation failed",
***************
*** 533,538 ****
--- 561,883 ----
CloseBlob(image);
return(image);
}
+
+ /*
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ % %
+ % %
+ % %
+ % E n c o d e R L E %
+ % %
+ % %
+ % %
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %
+ % Method EncodeRLE packs the packed image pixels into runlength-encoded
+ % pixel packets.
+ %
+ % The format of the DecodeImage method is:
+ %
+ % unsigned char *EncodeRLE(unsigned char *outbuff, unsigned char *inbuff,
+ % unsigned int literal, unsigned int repeated)
+ %
+ % A description of each parameter follows:
+ %
+ % o status: Method EncodeRLE returns an updated index to the end of
+ % the output buffer.
+ %
+ % o outbuff: Index into output buffer.
+ %
+ % o inbuff: Pointer to the uncompressed data.
+ %
+ % o literal: Count of non-repeated characters in inbuff.
+ %
+ % o repeated: Count of repeated characters in inbuff
+ %
+ %
+ */
+ unsigned char *EncodeRLE(unsigned char *outbuff, unsigned char *inbuff,
+ unsigned int literal, unsigned int repeated)
+ {
+ if (literal > 0)
+ *outbuff++ = literal - 1;
+ memcpy(outbuff, inbuff, literal);
+ outbuff += literal;
+
+ if (repeated > 0) {
+ *outbuff++ = 0x80 | (repeated - 1);
+ *outbuff++ = inbuff[literal];
+ }
+
+ return(outbuff);
+ }
+
+ /*
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ % %
+ % %
+ % %
+ % W r i t e P D B I m a g e %
+ % %
+ % %
+ % %
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %
+ % Method WritePDBImage writes an image
+ %
+ % The format of the WritePDBImage method is:
+ %
+ % unsigned int WritePDBImage(const ImageInfo *image_info,Image *image)
+ %
+ % A description of each parameter follows.
+ %
+ % o status: Method WritePDBImage return True if the image is written.
+ % False is returned is there is a memory shortage or if the image file
+ % fails to write.
+ %
+ % o image_info: Specifies a pointer to an ImageInfo structure.
+ %
+ % o image: A pointer to a Image structure.
+ %
+ %
+ */
+ static unsigned int WritePDBImage(const ImageInfo *image_info,Image *image)
+ {
+ PDBInfo
+ pdb_info;
+
+ PDBImage
+ pdb_image;
+
+ char
+ xx;
+
+ unsigned char
+ *scanline,
+ *rleBuff,
+ *pdbImageBuff,
+ *pdbImageEnd;
+
+ unsigned int
+ bits_per_pixel, // Override with -depth (1 | 2 | 4)
+ packet_size,
+ status,
+ literal,
+ repeated;
+
+ unsigned long
+ x, y,
+ packets;
+
+ const ImageAttribute
+ *comment;
+
+ /*
+ Open output image file.
+ */
+ assert(image_info != (const ImageInfo *) NULL);
+ assert(image_info->signature == MagickSignature);
+ assert(image != (Image *) NULL);
+ assert(image->signature == MagickSignature);
+ status=OpenBlob(image_info,image,WriteBinaryType,&image->exception);
+ if (status == False)
+ ThrowWriterException(FileOpenWarning,"Unable to open file",image);
+ (void) TransformRGBImage(image,RGBColorspace);
+
+ bits_per_pixel = image_info->depth;
+ if (GetImageType(image, &image->exception) == BilevelType) bits_per_pixel = 1;
+ if (bits_per_pixel != 1 && bits_per_pixel != 2)
+ bits_per_pixel = 4;
+
+ if (image_info->debug) {
+ (void) fprintf(stderr, "image->filename=%s\n", image->filename);
+ (void) fprintf(stderr, "image->depth=%ld\n", image->depth);
+ (void) fprintf(stderr, "image_info->filename=%s\n", image_info->filename);
+ (void) fprintf(stderr, "image_info->depth=%ld\n", image_info->depth);
+ }
+
+ memset(pdb_info.name, 0, 32);
+ strncpy(pdb_info.name, image_info->filename, 32);
+ pdb_info.attributes=0;
+ pdb_info.version=0;
+ pdb_info.create_time=time(NULL);
+ pdb_info.modify_time=pdb_info.create_time;
+ pdb_info.archive_time=0;
+ pdb_info.modify_number=0;
+ pdb_info.application_info=0;
+ pdb_info.sort_info=0;
+ memcpy(pdb_info.type, "vIMG", 4);
+ memcpy(pdb_info.id, "View", 4);
+ pdb_info.seed = 0;
+ pdb_info.next_record = 0;
+
+ comment=GetImageAttribute(image,"comment");
+ pdb_info.number_records = (comment == (ImageAttribute *) NULL ? 1 : 2);
+
+ (void) WriteBlob(image, 32, pdb_info.name);
+ (void) WriteBlobMSBShort(image, pdb_info.attributes);
+ (void) WriteBlobMSBShort(image, pdb_info.version);
+ (void) WriteBlobMSBLong(image, pdb_info.create_time);
+ (void) WriteBlobMSBLong(image, pdb_info.modify_time);
+ (void) WriteBlobMSBLong(image, pdb_info.archive_time);
+ (void) WriteBlobMSBLong(image, pdb_info.modify_number);
+ (void) WriteBlobMSBLong(image, pdb_info.application_info);
+ (void) WriteBlobMSBLong(image, pdb_info.sort_info);
+ (void) WriteBlob(image, 4, pdb_info.type);
+ (void) WriteBlob(image, 4, pdb_info.id);
+ (void) WriteBlobMSBLong(image, pdb_info.seed);
+ (void) WriteBlobMSBLong(image, pdb_info.next_record);
+ (void) WriteBlobMSBShort(image, pdb_info.number_records);
+
+ strncpy(pdb_image.name, pdb_info.name, 32);
+ pdb_image.version = 1; /* RLE Compressed */
+
+ switch(bits_per_pixel) {
+ case 1: pdb_image.type = 0xff; break; /* monochrome */
+ case 2: pdb_image.type = 0x00; break; /* 2 bit gray */
+ default: pdb_image.type = 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 = 0xffff;
+ pdb_image.y_anchor = 0xffff;
+
+ if (image->columns % 16) { /* Width should be multiple of 16 */
+ pdb_image.width = (image->columns/16 + 1)*16;
+ }
+ else {
+ pdb_image.width = image->columns;
+ }
+ pdb_image.height = image->rows;
+
+ packets = (bits_per_pixel*image->columns/8)*image->rows;
+ pdbImageBuff = (unsigned char *) AcquireMemory(packets + packets/128);
+ if (pdbImageBuff == (unsigned char *) NULL)
+ ThrowWriterException(ResourceLimitWarning,"Memory allocation failed",image);
+ rleBuff = (unsigned char *) AcquireMemory(256);
+ if (rleBuff == (unsigned char *) NULL)
+ ThrowWriterException(ResourceLimitWarning,"Memory allocation failed",image);
+ packet_size=image->depth > 8 ? 2: 1;
+ scanline=(unsigned char *) AcquireMemory(packet_size*image->columns);
+ if (scanline == (unsigned char *) NULL)
+ ThrowWriterException(ResourceLimitWarning,"Memory allocation failed",
+ image);
+ (void) TransformRGBImage(image,RGBColorspace);
+
+ /*
+ Convert to GRAY raster scanline.
+ */
+ xx = 8/bits_per_pixel - 1; /* start at most significant bits */
+ literal = 0;
+ repeated = 0;
+ pdbImageEnd = pdbImageBuff;
+ rleBuff[0] = 0x00;
+ for (y=0; y < (long) image->rows; y++) { /* Generate RLE encoded data */
+ if (NULL == AcquireImagePixels(image,0,y,image->columns,1,&image->exception))
+ break;
+ (void) PopImagePixels(image,GrayQuantum,scanline);
+
+ for (x=0; x < pdb_image.width; x++) {
+ if (x < image->columns) { /* This column exists in the image */
+ rleBuff[literal + repeated] |=
+ (0xff - scanline[x*packet_size]) >> (8 - bits_per_pixel) <<
+ xx*bits_per_pixel;
+ }
+
+ if (--xx < 0) { /* Completed a full byte of data */
+ if ((literal + repeated > 0) &&
+ (rleBuff[literal + repeated] == rleBuff[literal + repeated - 1])) {
+ if (0 == repeated) {
+ literal--;
+ repeated++;
+ }
+ repeated++;
+ if (0x7f < repeated) {
+ pdbImageEnd = EncodeRLE(pdbImageEnd, rleBuff, literal, repeated);
+ literal = 0;
+ repeated = 0;
+ }
+ }
+ else {
+ if (2 < repeated) {
+ pdbImageEnd = EncodeRLE(pdbImageEnd, rleBuff, literal, repeated);
+ rleBuff[0] = rleBuff[literal + repeated];
+ literal = 0;
+ }
+ else {
+ literal += repeated; /* move 2 or fewer repeats into literal */
+ }
+
+ literal++;
+ repeated = 0;
+
+ if (0x7f < literal) {
+ pdbImageEnd = EncodeRLE(pdbImageEnd, rleBuff, (literal < 0x80 ? literal : 0x80), 0);
+ memmove(rleBuff, rleBuff + literal + repeated, 0x80);
+ literal -= 0x80;
+ }
+
+ }
+
+ xx = 8/bits_per_pixel - 1;
+ rleBuff[literal + repeated] = 0x00;
+ }
+ }
+ if (QuantumTick(y,image->rows))
+ MagickMonitor(SaveImageText,y,image->rows);
+ }
+ pdbImageEnd = EncodeRLE(pdbImageEnd, rleBuff, literal, repeated);
+ LiberateMemory((void **) &scanline);
+ LiberateMemory((void **) &rleBuff);
+
+ /* Write the Image record header */
+ (void) WriteBlobMSBLong(image, TellBlob(image) + 8*pdb_info.number_records);
+ (void) WriteBlobByte(image, 0x40);
+ (void) WriteBlobByte(image, 0x6f);
+ (void) WriteBlobByte(image, 0x80);
+ (void) WriteBlobByte(image, 0);
+
+ if (pdb_info.number_records > 1) {
+ /* Write the comment record header */
+ if (image_info->debug) {
+ (void) fprintf(stderr, "Image size=%d\n", pdbImageEnd - pdbImageBuff);
+ }
+ (void) WriteBlobMSBLong(image, TellBlob(image) + 8 + 58 + pdbImageEnd - pdbImageBuff);
+ (void) WriteBlobByte(image, 0x40);
+ (void) WriteBlobByte(image, 0x6f);
+ (void) WriteBlobByte(image, 0x80);
+ (void) WriteBlobByte(image, 1);
+ }
+
+ /* Write the Image data */
+ (void) WriteBlob(image, 32, pdb_image.name);
+ (void) WriteBlobByte(image, pdb_image.version);
+ (void) WriteBlobByte(image, pdb_image.type);
+ (void) WriteBlobMSBLong(image, pdb_image.reserved_1);
+ (void) WriteBlobMSBLong(image, pdb_image.note);
+ (void) WriteBlobMSBShort(image, pdb_image.x_last);
+ (void) WriteBlobMSBShort(image, pdb_image.y_last);
+ (void) WriteBlobMSBLong(image, pdb_image.reserved_2);
+ (void) WriteBlobMSBShort(image, pdb_image.x_anchor);
+ (void) WriteBlobMSBShort(image, pdb_image.y_anchor);
+ (void) WriteBlobMSBShort(image, pdb_image.width);
+ (void) WriteBlobMSBShort(image, pdb_image.height);
+
+ (void) WriteBlob(image, pdbImageEnd - pdbImageBuff, pdbImageBuff);
+ LiberateMemory((void **) &pdbImageBuff);
+
+ if (pdb_info.number_records > 1) {
+ /* Write the comment data */
+ WriteBlobString(image, comment->value);
+ }
+
+ CloseBlob(image);
+ return(True);
+ }
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
***************
*** 563,571 ****
*entry;
entry=SetMagickInfo("PDB");
! entry->decoder=ReadPDBImage;
entry->magick=IsPDB;
! entry->description=AcquireString("Pilot Image Format");
entry->module=AcquireString("PDB");
(void) RegisterMagickInfo(entry);
}
--- 908,917 ----
*entry;
entry=SetMagickInfo("PDB");
! entry->decoder=ReadPDBImage;
! entry->encoder=WritePDBImage;
entry->magick=IsPDB;
! entry->description=AcquireString("Palm Database ImageViewer Format");
entry->module=AcquireString("PDB");
(void) RegisterMagickInfo(entry);
}
_______________________________________________
Magick-developers mailing list
Magick-developers@imagemagick.org
http://studio.imagemagick.org/mailman/listinfo/magick-developers
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic