~ubuntu-branches/ubuntu/intrepid/graphicsmagick/intrepid

« back to all changes in this revision

Viewing changes to coders/tim.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Kobras
  • Date: 2006-05-06 16:28:08 UTC
  • Revision ID: james.westby@ubuntu.com-20060506162808-vt2ni3r5nytcszms
Tags: upstream-1.1.7
ImportĀ upstreamĀ versionĀ 1.1.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
% Copyright (C) 2003 GraphicsMagick Group
 
3
% Copyright (C) 2002 ImageMagick Studio
 
4
% Copyright 1991-1999 E. I. du Pont de Nemours and Company
 
5
%
 
6
% This program is covered by multiple licenses, which are described in
 
7
% Copyright.txt. You should have received a copy of Copyright.txt with this
 
8
% package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
 
9
%
 
10
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
11
%                                                                             %
 
12
%                                                                             %
 
13
%                                                                             %
 
14
%                            TTTTT  IIIII  M   M                              %
 
15
%                              T      I    MM MM                              %
 
16
%                              T      I    M M M                              %
 
17
%                              T      I    M   M                              %
 
18
%                              T    IIIII  M   M                              %
 
19
%                                                                             %
 
20
%                                                                             %
 
21
%                          Read PSX TIM Image Format.                         %
 
22
%                                                                             %
 
23
%                                                                             %
 
24
%                              Software Design                                %
 
25
%                                John Cristy                                  %
 
26
%                                 July 1992                                   %
 
27
%                                                                             %
 
28
%                                                                             %
 
29
%                                                                             %
 
30
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
31
%
 
32
%
 
33
*/
 
34
 
 
35
/*
 
36
  Include declarations.
 
37
*/
 
38
#include "magick/studio.h"
 
39
#include "magick/blob.h"
 
40
#include "magick/cache.h"
 
41
#include "magick/magick.h"
 
42
#include "magick/monitor.h"
 
43
#include "magick/utility.h"
 
44
 
 
45
/*
 
46
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
47
%                                                                             %
 
48
%                                                                             %
 
49
%                                                                             %
 
50
%  R e a d T I M I m a g e                                                    %
 
51
%                                                                             %
 
52
%                                                                             %
 
53
%                                                                             %
 
54
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
55
%
 
56
%  Method ReadTIMImage reads a PSX TIM image file and returns it.  It
 
57
%  allocates the memory necessary for the new Image structure and returns a
 
58
%  pointer to the new image.
 
59
%
 
60
%  Contributed by os@scee.sony.co.uk.
 
61
%
 
62
%  The format of the ReadTIMImage method is:
 
63
%
 
64
%      Image *ReadTIMImage(const ImageInfo *image_info,ExceptionInfo *exception)
 
65
%
 
66
%  A description of each parameter follows:
 
67
%
 
68
%    o image:  Method ReadTIMImage returns a pointer to the image after
 
69
%      reading.  A null image is returned if there is a memory shortage or
 
70
%      if the image cannot be read.
 
71
%
 
72
%    o image_info: Specifies a pointer to a ImageInfo structure.
 
73
%
 
74
%    o exception: return any errors or warnings in this structure.
 
75
%
 
76
%
 
77
*/
 
78
static Image *ReadTIMImage(const ImageInfo *image_info,ExceptionInfo *exception)
 
79
{
 
80
  typedef struct _TIMInfo
 
81
  {
 
82
    unsigned long
 
83
      id,
 
84
      flag;
 
85
  } TIMInfo;
 
86
 
 
87
  TIMInfo
 
88
    tim_info;
 
89
 
 
90
  Image
 
91
    *image;
 
92
 
 
93
  int
 
94
    bits_per_pixel,
 
95
    has_clut;
 
96
 
 
97
  long
 
98
    y;
 
99
 
 
100
  register IndexPacket
 
101
    *indexes;
 
102
 
 
103
  register long
 
104
    x;
 
105
 
 
106
  register PixelPacket
 
107
    *q;
 
108
 
 
109
  register long
 
110
    i;
 
111
 
 
112
  register unsigned char
 
113
    *p;
 
114
 
 
115
  unsigned char
 
116
    *tim_data,
 
117
    *tim_pixels;
 
118
 
 
119
  unsigned short
 
120
    word;
 
121
 
 
122
  unsigned int
 
123
    status;
 
124
 
 
125
  unsigned long
 
126
    bytes_per_line,
 
127
    height,
 
128
    image_size,
 
129
    pixel_mode,
 
130
    width;
 
131
 
 
132
  /*
 
133
    Open image file.
 
134
  */
 
135
  assert(image_info != (const ImageInfo *) NULL);
 
136
  assert(image_info->signature == MagickSignature);
 
137
  assert(exception != (ExceptionInfo *) NULL);
 
138
  assert(exception->signature == MagickSignature);
 
139
  image=AllocateImage(image_info);
 
140
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
 
141
  if (status == False)
 
142
    ThrowReaderException(FileOpenError,UnableToOpenFile,image);
 
143
  /*
 
144
    Determine if this is a TIM file.
 
145
  */
 
146
  tim_info.id=ReadBlobLSBLong(image);
 
147
  do
 
148
  {
 
149
    /*
 
150
      Verify TIM identifier.
 
151
    */
 
152
    if (tim_info.id != 0x00000010)
 
153
      ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
 
154
    tim_info.flag=ReadBlobLSBLong(image);
 
155
    has_clut=!!(tim_info.flag & (1 << 3));
 
156
    pixel_mode=tim_info.flag & 0x07;
 
157
    switch ((int) pixel_mode)
 
158
    {
 
159
      case 0: bits_per_pixel=4; break;
 
160
      case 1: bits_per_pixel=8; break;
 
161
      case 2: bits_per_pixel=16; break;
 
162
      case 3: bits_per_pixel=24; break;
 
163
      default: bits_per_pixel=4; break;
 
164
    }
 
165
    if (has_clut)
 
166
      {
 
167
        unsigned char
 
168
          *tim_colormap;
 
169
 
 
170
        /*
 
171
          Read TIM raster colormap.
 
172
        */
 
173
        (void)ReadBlobLSBLong(image);
 
174
        (void)ReadBlobLSBShort(image);
 
175
        (void)ReadBlobLSBShort(image);
 
176
        width=ReadBlobLSBShort(image);
 
177
        height=ReadBlobLSBShort(image);
 
178
        if (!AllocateImageColormap(image,pixel_mode == 1 ? 256 : 16))
 
179
          ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
 
180
            image);
 
181
        tim_colormap=MagickAllocateMemory(unsigned char *,image->colors*2);
 
182
        if (tim_colormap == (unsigned char *) NULL)
 
183
          ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
 
184
            image);
 
185
        (void) ReadBlob(image,2*image->colors,(char *) tim_colormap);
 
186
        p=tim_colormap;
 
187
        for (i=0; i < (long) image->colors; i++)
 
188
        {
 
189
          word=(*p++);
 
190
          word|=(unsigned short) (*p++ << 8);
 
191
          image->colormap[i].blue=ScaleCharToQuantum(ScaleColor5to8((word >> 10) & 0x1f));
 
192
          image->colormap[i].green=ScaleCharToQuantum(ScaleColor5to8((word >> 5) & 0x1f));
 
193
          image->colormap[i].red=ScaleCharToQuantum(ScaleColor5to8(word & 0x1f));
 
194
        }
 
195
        MagickFreeMemory(tim_colormap);
 
196
      }
 
197
    if (image_info->ping && (image_info->subrange != 0))
 
198
      if (image->scene >= (image_info->subimage+image_info->subrange-1))
 
199
        break;
 
200
    /*
 
201
      Read image data.
 
202
    */
 
203
    (void) ReadBlobLSBLong(image);
 
204
    (void) ReadBlobLSBShort(image);
 
205
    (void) ReadBlobLSBShort(image);
 
206
    width=ReadBlobLSBShort(image);
 
207
    height=ReadBlobLSBShort(image);
 
208
    image_size=2*width*height;
 
209
    bytes_per_line=width*2;
 
210
    width=(width*16)/bits_per_pixel;
 
211
    tim_data=MagickAllocateMemory(unsigned char *,image_size);
 
212
    if (tim_data == (unsigned char *) NULL)
 
213
      ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
 
214
    (void) ReadBlob(image,image_size,(char *) tim_data);
 
215
    tim_pixels=tim_data;
 
216
    /*
 
217
      Initialize image structure.
 
218
    */
 
219
    image->columns=width;
 
220
    image->rows=height;
 
221
    /*
 
222
      Convert TIM raster image to pixel packets.
 
223
    */
 
224
    switch (bits_per_pixel)
 
225
    {
 
226
      case 4:
 
227
      {
 
228
        /*
 
229
          Convert PseudoColor scanline.
 
230
        */
 
231
        for (y=(long) image->rows-1; y >= 0; y--)
 
232
        {
 
233
          q=SetImagePixels(image,0,y,image->columns,1);
 
234
          if (q == (PixelPacket *) NULL)
 
235
            break;
 
236
          indexes=GetIndexes(image);
 
237
          p=tim_pixels+y*bytes_per_line;
 
238
          for (x=0; x < ((long) image->columns-1); x+=2)
 
239
          {
 
240
            indexes[x]=(*p) & 0xf;
 
241
            indexes[x+1]=(*p >> 4) & 0xf;
 
242
            p++;
 
243
          }
 
244
          if ((image->columns % 2) != 0)
 
245
            {
 
246
              indexes[x]=(*p >> 4) & 0xf;
 
247
              p++;
 
248
            }
 
249
          if (!SyncImagePixels(image))
 
250
            break;
 
251
          if (QuantumTick(y,image->rows))
 
252
            {
 
253
              status=MagickMonitor(LoadImageText,image->rows-y-1,image->rows,
 
254
                exception);
 
255
              if (status == False)
 
256
                break;
 
257
            }
 
258
        }
 
259
        break;
 
260
      }
 
261
      case 8:
 
262
      {
 
263
        /*
 
264
          Convert PseudoColor scanline.
 
265
        */
 
266
        for (y=(long) image->rows-1; y >= 0; y--)
 
267
        {
 
268
          q=SetImagePixels(image,0,y,image->columns,1);
 
269
          if (q == (PixelPacket *) NULL)
 
270
            break;
 
271
          indexes=GetIndexes(image);
 
272
          p=tim_pixels+y*bytes_per_line;
 
273
          for (x=0; x < (long) image->columns; x++)
 
274
            indexes[x]=(*p++);
 
275
          if (!SyncImagePixels(image))
 
276
            break;
 
277
          if (QuantumTick(y,image->rows))
 
278
            {
 
279
              status=MagickMonitor(LoadImageText,image->rows-y-1,image->rows,
 
280
                exception);
 
281
              if (status == False)
 
282
                break;
 
283
            }
 
284
        }
 
285
        break;
 
286
      }
 
287
      case 16:
 
288
      {
 
289
        /*
 
290
          Convert DirectColor scanline.
 
291
        */
 
292
        for (y=(long) image->rows-1; y >= 0; y--)
 
293
        {
 
294
          p=tim_pixels+y*bytes_per_line;
 
295
          q=SetImagePixels(image,0,y,image->columns,1);
 
296
          if (q == (PixelPacket *) NULL)
 
297
            break;
 
298
          for (x=0; x < (long) image->columns; x++)
 
299
          {
 
300
            word=(*p++);
 
301
            word|=(*p++ << 8);
 
302
            q->blue=ScaleCharToQuantum(ScaleColor5to8((word >> 10) & 0x1f));
 
303
            q->green=ScaleCharToQuantum(ScaleColor5to8((word >> 5) & 0x1f));
 
304
            q->red=ScaleCharToQuantum(ScaleColor5to8(word & 0x1f));
 
305
            q++;
 
306
          }
 
307
          if (!SyncImagePixels(image))
 
308
            break;
 
309
          if (QuantumTick(y,image->rows))
 
310
            {
 
311
              status=MagickMonitor(LoadImageText,image->rows-y-1,image->rows,
 
312
                exception);
 
313
              if (status == False)
 
314
                break;
 
315
            }
 
316
        }
 
317
        break;
 
318
      }
 
319
      case 24:
 
320
      {
 
321
        /*
 
322
          Convert DirectColor scanline.
 
323
        */
 
324
        for (y=(long) image->rows-1; y >= 0; y--)
 
325
        {
 
326
          p=tim_pixels+y*bytes_per_line;
 
327
          q=SetImagePixels(image,0,y,image->columns,1);
 
328
          if (q == (PixelPacket *) NULL)
 
329
            break;
 
330
          for (x=0; x < (long) image->columns; x++)
 
331
          {
 
332
            q->red=ScaleCharToQuantum(*p++);
 
333
            q->green=ScaleCharToQuantum(*p++);
 
334
            q->blue=ScaleCharToQuantum(*p++);
 
335
            q++;
 
336
          }
 
337
          if (!SyncImagePixels(image))
 
338
            break;
 
339
          if (QuantumTick(y,image->rows))
 
340
            {
 
341
              status=MagickMonitor(LoadImageText,image->rows-y-1,image->rows,
 
342
                exception);
 
343
              if (status == False)
 
344
                break;
 
345
            }
 
346
        }
 
347
        break;
 
348
      }
 
349
      default:
 
350
        ThrowReaderException(CorruptImageError,ImproperImageHeader,image)
 
351
    }
 
352
    if (image->storage_class == PseudoClass)
 
353
      SyncImage(image);
 
354
    MagickFreeMemory(tim_pixels);
 
355
    if (EOFBlob(image))
 
356
      {
 
357
        ThrowException(exception,CorruptImageError,UnexpectedEndOfFile,
 
358
          image->filename);
 
359
        break;
 
360
      }
 
361
    /*
 
362
      Proceed to next image.
 
363
    */
 
364
    tim_info.id=ReadBlobLSBLong(image);
 
365
    if (tim_info.id == 0x00000010)
 
366
      {
 
367
        /*
 
368
          Allocate next image structure.
 
369
        */
 
370
        AllocateNextImage(image_info,image);
 
371
        if (image->next == (Image *) NULL)
 
372
          {
 
373
            DestroyImageList(image);
 
374
            return((Image *) NULL);
 
375
          }
 
376
        image=SyncNextImageInList(image);
 
377
        status=MagickMonitor(LoadImagesText,TellBlob(image),GetBlobSize(image),
 
378
          exception);
 
379
        if (status == False)
 
380
          break;
 
381
      }
 
382
  } while (tim_info.id == 0x00000010);
 
383
  while (image->previous != (Image *) NULL)
 
384
    image=image->previous;
 
385
  CloseBlob(image);
 
386
  return(image);
 
387
}
 
388
 
 
389
/*
 
390
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
391
%                                                                             %
 
392
%                                                                             %
 
393
%                                                                             %
 
394
%   R e g i s t e r T I M I m a g e                                           %
 
395
%                                                                             %
 
396
%                                                                             %
 
397
%                                                                             %
 
398
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
399
%
 
400
%  Method RegisterTIMImage adds attributes for the TIM image format to
 
401
%  the list of supported formats.  The attributes include the image format
 
402
%  tag, a method to read and/or write the format, whether the format
 
403
%  supports the saving of more than one frame to the same file or blob,
 
404
%  whether the format supports native in-memory I/O, and a brief
 
405
%  description of the format.
 
406
%
 
407
%  The format of the RegisterTIMImage method is:
 
408
%
 
409
%      RegisterTIMImage(void)
 
410
%
 
411
*/
 
412
ModuleExport void RegisterTIMImage(void)
 
413
{
 
414
  MagickInfo
 
415
    *entry;
 
416
 
 
417
  entry=SetMagickInfo("TIM");
 
418
  entry->decoder=(DecoderHandler) ReadTIMImage;
 
419
  entry->description=AcquireString("PSX TIM");
 
420
  entry->module=AcquireString("TIM");
 
421
  (void) RegisterMagickInfo(entry);
 
422
}
 
423
 
 
424
/*
 
425
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
426
%                                                                             %
 
427
%                                                                             %
 
428
%                                                                             %
 
429
%   U n r e g i s t e r T I M I m a g e                                       %
 
430
%                                                                             %
 
431
%                                                                             %
 
432
%                                                                             %
 
433
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
434
%
 
435
%  Method UnregisterTIMImage removes format registrations made by the
 
436
%  TIM module from the list of supported formats.
 
437
%
 
438
%  The format of the UnregisterTIMImage method is:
 
439
%
 
440
%      UnregisterTIMImage(void)
 
441
%
 
442
*/
 
443
ModuleExport void UnregisterTIMImage(void)
 
444
{
 
445
  (void) UnregisterMagickInfo("TIM");
 
446
}