2
% Copyright (C) 2003 GraphicsMagick Group
4
% This program is covered by multiple licenses, which are described in
5
% Copyright.txt. You should have received a copy of Copyright.txt with this
6
% package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
8
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11
% TTTTT OOO PPPP OOO L %
18
% Read/Write TOPOL X Image Raster Format. %
27
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35
#include "magick/studio.h"
36
#include "magick/blob.h"
37
#include "magick/cache.h"
38
#include "magick/color.h"
39
#include "magick/error.h"
40
#include "magick/list.h"
41
#include "magick/magick.h"
42
#include "magick/utility.h"
45
# define SWORD unsigned int
48
# define SDWORD unsigned long
54
# define BYTE unsigned char
62
SWORD TypSou; /* 0-binary, 1-8 bitu, 2-8 bits+PAL, 3-4 bits,
63
4-4 bits+PAL, 5-24 bits, 6-16 bits, 7-32
67
SWORD Komprese; /* 0 - uncompressed (from release 1) */
73
double Scale; /* from release 2 */
74
WORD TileWidth; /* tile width in pixels */
75
WORD TileHeight; /* tile height in pixels */
76
SDWORD TileOffsets; /* offset to array of longints that contains
77
adresses of tiles in the raster (adreses
78
are counted from 0) */
79
SDWORD TileByteCounts; /* offset to array of words, that contain amount of bytes stored in
80
tiles. The tile size might vary depending on
81
the value TileCompression */
82
BYTE TileCompression; /* 0 - uncompressed, 1 - variant TIFF
83
Packbits, 2 - CCITT G3 */
89
typedef struct The palette record inside TopoL
97
static void InsertRow(int depth, unsigned char *p, long y, Image * image, unsigned char *MEZ)
116
case 1: /* Convert bitmap scanline. */
118
q = SetImagePixels(image, 0, y, image->columns, 1);
119
if (q == (PixelPacket *) NULL)
121
indexes = GetIndexes(image);
122
for (x = 0; x < ((long) image->columns - 7); x += 8)
124
for (bit = 0; bit < 8; bit++)
126
index = ((*p) & (0x80 >> bit) ? 0x01 : 0x00);
127
indexes[x + bit] = MEZ[index];
128
*q++ = image->colormap[index];
132
if ((image->columns % 8) != 0)
134
for (bit = 0; bit < (long) (image->columns % 8); bit++)
136
index = ((*p) & (0x80 >> bit) ? 0x01 : 0x00);
137
indexes[x + bit] = MEZ[index];
138
*q++ = image->colormap[index];
142
if (!SyncImagePixels(image))
144
/* if (image->previous == (Image *) NULL)
145
if (QuantumTick(y,image->rows))
146
ProgressMonitor(LoadImageText,image->rows-y-1,image->rows); */
149
case 2: /* Convert PseudoColor scanline. */
151
q = SetImagePixels(image, 0, y, image->columns, 1);
152
if (q == (PixelPacket *) NULL)
154
indexes = GetIndexes(image);
155
for (x = 0; x < ((long) image->columns - 1); x += 2)
157
index = (IndexPacket) ((*p >> 6) & 0x3);
158
VerifyColormapIndex(image, index);
159
indexes[x] = MEZ[index];
160
*q++ = image->colormap[index];
161
index = (IndexPacket) ((*p >> 4) & 0x3);
162
VerifyColormapIndex(image, index);
163
indexes[x] = MEZ[index];
164
*q++ = image->colormap[index];
165
index = (IndexPacket) ((*p >> 2) & 0x3);
166
VerifyColormapIndex(image, index);
167
indexes[x] = MEZ[index];
168
*q++ = image->colormap[index];
169
index = (IndexPacket) ((*p) & 0x3);
170
VerifyColormapIndex(image, index);
171
indexes[x + 1] = MEZ[index];
172
*q++ = image->colormap[index];
175
if ((image->columns % 4) != 0)
177
index = (IndexPacket) ((*p >> 6) & 0x3);
178
VerifyColormapIndex(image, index);
179
indexes[x] = MEZ[index];
180
*q++ = image->colormap[index];
181
if ((image->columns % 4) >= 1)
183
index = (IndexPacket) ((*p >> 4) & 0x3);
184
VerifyColormapIndex(image, index);
185
indexes[x] = MEZ[index];
186
*q++ = image->colormap[index];
187
if ((image->columns % 4) >= 2)
189
index = (IndexPacket) ((*p >> 2) & 0x3);
190
VerifyColormapIndex(image, index);
191
indexes[x] = MEZ[index];
192
*q++ = image->colormap[index];
197
if (!SyncImagePixels(image))
199
/* if (image->previous == (Image *) NULL)
200
if (QuantumTick(y,image->rows))
201
ProgressMonitor(LoadImageText,image->rows-y-1,image->rows); */
205
case 4: /* Convert PseudoColor scanline. */
207
q = SetImagePixels(image, 0, y, image->columns, 1);
208
if (q == (PixelPacket *) NULL)
210
indexes = GetIndexes(image);
211
for (x = 0; x < ((long) image->columns - 1); x += 2)
213
index = (IndexPacket) ((*p >> 4) & 0xf);
214
VerifyColormapIndex(image, index);
215
indexes[x] = MEZ[index];
216
*q++ = image->colormap[index];
217
index = (IndexPacket) ((*p) & 0xf);
218
VerifyColormapIndex(image, index);
219
indexes[x + 1] = MEZ[index];
220
*q++ = image->colormap[index];
223
if ((image->columns % 2) != 0)
225
index = (IndexPacket) ((*p >> 4) & 0xf);
226
VerifyColormapIndex(image, index);
227
indexes[x] = MEZ[index];
228
*q++ = image->colormap[index];
231
if (!SyncImagePixels(image))
233
/* if (image->previous == (Image *) NULL)
234
if (QuantumTick(y,image->rows))
235
ProgressMonitor(LoadImageText,image->rows-y-1,image->rows); */
238
case 8: /* Convert PseudoColor scanline. */
240
q = SetImagePixels(image, 0, y, image->columns, 1);
241
if (q == (PixelPacket *) NULL)
243
indexes = GetIndexes(image);
245
for (x = 0; x < (long) image->columns; x++)
247
index = (IndexPacket) (*p);
248
VerifyColormapIndex(image, index);
249
indexes[x] = MEZ[index];
250
*q++ = image->colormap[index];
253
if (!SyncImagePixels(image))
255
/* if (image->previous == (Image *) NULL)
256
if (QuantumTick(y,image->rows))
257
ProgressMonitor(LoadImageText,image->rows-y-1,image->rows); */
263
static double ReadBlobLSBdouble(Image * image)
280
assert(image != (Image *) NULL);
281
assert(image->signature == MagickSignature);
283
if (ReadBlob(image, 8, (unsigned char *) &buffer) == 0)
286
if (*(char *) &lsb_first == 1)
290
buffer.chars[0] = buffer.chars[7];
293
buffer.chars[1] = buffer.chars[6];
296
buffer.chars[2] = buffer.chars[5];
299
buffer.chars[3] = buffer.chars[4];
304
/* This function reads one block of unsigned shortS */
305
static void ReadBlobWordLSB(Image * image, size_t len, unsigned short *data)
309
*data++ = ReadBlobLSBShort(image);
313
(void) SeekBlob(image, len, SEEK_CUR);
316
/* This function reads one block of unsigned longS */
317
static void ReadBlobDwordLSB(Image * image, size_t len, unsigned long *data)
321
*data++ = ReadBlobLSBLong(image);
325
(void) SeekBlob(image, len, SEEK_CUR);
329
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
333
% R e a d T O P O L I m a g e %
337
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
339
% Method ReadTOPOLImage reads an TOPOL X image file and returns it. It
340
% allocates the memory necessary for the new Image structure and returns a
341
% pointer to the new image.
343
% The format of the ReadTOPOLImage method is:
345
% Image *ReadTOPOLImage(const ImageInfo *image_info,ExceptionInfo *exception)
347
% A description of each parameter follows:
349
% o image: Method ReadTOPOLImage returns a pointer to the image after
350
% reading. A null image is returned if there is a memory shortage or if
351
% the image cannot be read.
353
% o image_info: The image info.
355
% o exception: return any errors or warnings in this structure.
359
static Image *ReadTOPOLImage(const ImageInfo * image_info, ExceptionInfo * exception)
394
assert(image_info != (const ImageInfo *) NULL);
395
assert(image_info->signature == MagickSignature);
396
assert(exception != (ExceptionInfo *) NULL);
397
assert(exception->signature == MagickSignature);
398
image = AllocateImage(image_info);
399
status = OpenBlob(image_info, image, ReadBinaryBlobMode, exception);
401
ThrowReaderException(FileOpenError, UnableToOpenFile, image);
404
Read TopoL RAS header.
406
memset(&Header, 0, sizeof(Header));
407
ReadBlob(image, 20, &Header.Name);
408
Header.Rows = ReadBlobLSBShort(image);
409
Header.Cols = ReadBlobLSBShort(image);
410
Header.TypSou = ReadBlobLSBShort(image);
411
Header.Zoom = ReadBlobLSBLong(image);
412
Header.Version = ReadBlobLSBShort(image);
413
if (Header.Version >= 1)
415
Header.Komprese = ReadBlobLSBShort(image);
416
Header.Stav = ReadBlobLSBShort(image);
417
Header.xRasMin = ReadBlobLSBdouble(image);
418
Header.yRasMin = ReadBlobLSBdouble(image);
419
Header.xRasMax = ReadBlobLSBdouble(image);
420
Header.yRasMax = ReadBlobLSBdouble(image);
421
if (Header.Version >= 2) /* from release 2 */
423
Header.Scale = ReadBlobLSBdouble(image);
424
Header.TileWidth = ReadBlobLSBShort(image);
425
Header.TileHeight = ReadBlobLSBShort(image);
426
Header.TileOffsets = ReadBlobLSBLong(image);
427
Header.TileByteCounts = ReadBlobLSBLong(image);
428
Header.TileCompression = ReadBlobByte(image);
429
/* BYTE Dummy[423]; */
433
for (i = 0; i < sizeof(Header.Name); i++)
435
if (Header.Name[i] < ' ')
436
TOPOL_KO:ThrowReaderException(CorruptImageError,ImproperImageHeader,
439
if (Header.Komprese != 0 || (Header.Version >= 2 && Header.TileCompression != 0))
440
ThrowReaderException(CorruptImageError, UnrecognizedImageCompression, image);
441
if (Header.Rows == 0 || Header.Cols == 0)
443
if (Header.Version > 2)
444
ThrowReaderException(CorruptImageError, InvalidFileFormatVersion, image); /* unknown version */
446
switch (Header.TypSou)
465
break; /* ????????? 24 bits */
469
break; /* ????????? 16 bits */
473
break; /* ????????? 32 bits */
478
image->columns = Header.Cols;
479
image->rows = Header.Rows;
481
/* ----- Handle the reindexing mez file ----- */
484
MEZ[i]=(unsigned char) i;
487
if(Header.TypSou>=5) goto NoMEZ;
489
if ((clone_info=CloneImageInfo(image_info)) == NULL) goto NoMEZ;
491
i=(long) strlen(clone_info->filename);
495
if(clone_info->filename[i]=='.')
499
if(clone_info->filename[i]=='/' || clone_info->filename[i]=='\\' ||
500
clone_info->filename[i]==':' )
507
(void) strcpy(clone_info->filename+i,".MEZ");
508
if((clone_info->file=fopen(clone_info->filename,"rb"))==NULL)
510
(void) strcpy(clone_info->filename+i,".mez");
511
if((clone_info->file=fopen(clone_info->filename,"rb"))==NULL)
513
DestroyImageInfo(clone_info);
519
if( (palette=AllocateImage(clone_info))==NULL ) goto NoMEZ;
520
status=OpenBlob(clone_info,palette,ReadBinaryBlobMode,exception);
521
if (status == False) goto NoMEZ;
523
ldblk=(long) GetBlobSize(palette);
524
if(ldblk>sizeof(MEZ)) ldblk=sizeof(MEZ);
525
ReadBlob(palette, ldblk, MEZ);
527
NoMEZ: /*Clean up palette and clone_info*/
528
if (palette != NULL) {DestroyImage(palette);palette=NULL;}
529
if (clone_info != NULL)
531
DestroyImageInfo(clone_info);
535
/* ----- Do something with palette ----- */
536
if ((clone_info=CloneImageInfo(image_info)) == NULL) goto NoPalette;
538
i=(long) strlen(clone_info->filename);
542
if(clone_info->filename[i]=='.')
546
if(clone_info->filename[i]=='/' || clone_info->filename[i]=='\\' ||
547
clone_info->filename[i]==':' )
554
(void) strcpy(clone_info->filename+i,".PAL");
555
if((clone_info->file=fopen(clone_info->filename,"rb"))==NULL)
557
(void) strcpy(clone_info->filename+i,".pal");
558
if((clone_info->file=fopen(clone_info->filename,"rb"))==NULL)
560
clone_info->filename[i]=0;
561
if((clone_info->file=fopen(clone_info->filename,"rb"))==NULL)
563
DestroyImageInfo(clone_info);
570
if( (palette=AllocateImage(clone_info))==NULL ) goto NoPalette;
571
status=OpenBlob(clone_info,palette,ReadBinaryBlobMode,exception);
575
DestroyImage(palette);
583
ldblk=ReadBlobByte(palette); /*size of palette*/
584
if(ldblk==EOF) goto ErasePalette;
585
image->colors=ldblk+1;
586
if (!AllocateImageColormap(image, image->colors)) goto NoMemory;
588
for(i=0;i<=ldblk;i++)
590
j=ReadBlobByte(palette); /* Flag */
591
if(j==EOF) break; /* unexpected end of file */
594
image->colormap[j].red=ScaleCharToQuantum(ReadBlobByte(palette));
595
image->colormap[j].green=ScaleCharToQuantum(ReadBlobByte(palette));
596
image->colormap[j].blue=ScaleCharToQuantum(ReadBlobByte(palette));
600
SeekBlob(palette, 3, SEEK_CUR);
601
fprintf(stderr,"TopoL: Wrong index inside palette %d!",(int)j);
608
if (palette == NULL && image->colors != 0)
610
if (!AllocateImageColormap(image, image->colors))
613
ThrowReaderException(ResourceLimitError, MemoryAllocationFailed, image);
616
for (i = 0; i < (long) image->colors; i++)
618
image->colormap[i].red = ScaleCharToQuantum(i);
619
image->colormap[i].green = ScaleCharToQuantum(i);
620
image->colormap[i].blue = ScaleCharToQuantum(i);
624
/* ----- Load TopoL raster ----- */
625
ldblk = (long) ((depth * image->columns + 7) / 8);
626
BImgBuff = (unsigned char *) AcquireMemory(ldblk); /*Ldblk was set in the check phase */
627
if (BImgBuff == NULL)
630
(void) SeekBlob(image, 512 /*sizeof(Header)*/, SEEK_SET);
631
for (i = 0; i < (int) Header.Rows; i++)
633
switch (Header.TypSou)
636
ReadBlobWordLSB(image, ldblk, (unsigned short *) BImgBuff);
639
ReadBlobDwordLSB(image, ldblk, (unsigned long *) BImgBuff);
642
(void) ReadBlob(image, ldblk, (char *) BImgBuff);
644
InsertRow(depth, BImgBuff, i, image, MEZ);
648
if (BImgBuff != NULL)
651
DestroyImage(palette);
652
if (clone_info != NULL)
653
DestroyImageInfo(clone_info);
654
/* if (EOFBlob(image))
655
ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image); */
661
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
665
% R e g i s t e r T O P O L I m a g e %
669
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
671
% Method RegisterTOPOLImage adds attributes for the TOPOL image format to
672
% the list of supported formats. The attributes include the image format
673
% tag, a method to read and/or write the format, whether the format
674
% supports the saving of more than one frame to the same file or blob,
675
% whether the format supports native in-memory I/O, and a brief
676
% description of the format.
678
% The format of the RegisterTOPOLImage method is:
680
% RegisterTOPOLImage(void)
683
ModuleExport void RegisterTOPOLImage(void)
687
entry = SetMagickInfo("TOPOL");
688
entry->decoder = (DecoderHandler) ReadTOPOLImage;
689
entry->seekable_stream = True;
690
entry->description = AcquireString("TOPOL X Image");
691
entry->module = AcquireString("TOPOL");
692
(void) RegisterMagickInfo(entry);
696
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
700
% U n r e g i s t e r T O P O L I m a g e %
704
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
706
% Method UnregisterTOPOLImage removes format registrations made by the
707
% TOPOL module from the list of supported formats.
709
% The format of the UnregisterTOPOLImage method is:
711
% UnregisterTOPOLImage(void)
714
ModuleExport void UnregisterTOPOLImage(void)
716
(void) UnregisterMagickInfo("TOPOL");