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

« back to all changes in this revision

Viewing changes to coders/sun.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
%                            SSSSS  U   U  N   N                              %
 
15
%                            SS     U   U  NN  N                              %
 
16
%                             SSS   U   U  N N N                              %
 
17
%                               SS  U   U  N  NN                              %
 
18
%                            SSSSS   UUU   N   N                              %
 
19
%                                                                             %
 
20
%                                                                             %
 
21
%                   Read/Write Sun Rasterfile 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/color.h"
 
42
#include "magick/magick.h"
 
43
#include "magick/monitor.h"
 
44
#include "magick/utility.h"
 
45
 
 
46
/*
 
47
  Forward declarations.
 
48
*/
 
49
static unsigned int
 
50
  WriteSUNImage(const ImageInfo *,Image *);
 
51
 
 
52
/*
 
53
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
54
%                                                                             %
 
55
%                                                                             %
 
56
%                                                                             %
 
57
%   I s S U N                                                                 %
 
58
%                                                                             %
 
59
%                                                                             %
 
60
%                                                                             %
 
61
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
62
%
 
63
%  Method IsSUN returns True if the image format type, identified by the
 
64
%  magick string, is SUN.
 
65
%
 
66
%  The format of the IsSUN method is:
 
67
%
 
68
%      unsigned int IsSUN(const unsigned char *magick,const size_t length)
 
69
%
 
70
%  A description of each parameter follows:
 
71
%
 
72
%    o status:  Method IsSUN returns True if the image format type is SUN.
 
73
%
 
74
%    o magick: This string is generally the first few bytes of an image file
 
75
%      or blob.
 
76
%
 
77
%    o length: Specifies the length of the magick string.
 
78
%
 
79
%
 
80
*/
 
81
static unsigned int IsSUN(const unsigned char *magick,const size_t length)
 
82
{
 
83
  if (length < 4)
 
84
    return(False);
 
85
  if (memcmp(magick,"\131\246\152\225",4) == 0)
 
86
    return(True);
 
87
  return(False);
 
88
}
 
89
 
 
90
/*
 
91
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
92
%                                                                             %
 
93
%                                                                             %
 
94
%                                                                             %
 
95
%   D e c o d e I m a g e                                                     %
 
96
%                                                                             %
 
97
%                                                                             %
 
98
%                                                                             %
 
99
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
100
%
 
101
%  Method DecodeImage unpacks the packed image pixels into
 
102
%  runlength-encoded pixel packets.
 
103
%
 
104
%  The format of the DecodeImage method is:
 
105
%
 
106
%      unsigned int DecodeImage(const unsigned char *compressed_pixels,
 
107
%        const size_t length,unsigned char *pixels)
 
108
%
 
109
%  A description of each parameter follows:
 
110
%
 
111
%    o status:  Method DecodeImage returns True if all the pixels are
 
112
%      uncompressed without error, otherwise False.
 
113
%
 
114
%    o compressed_pixels:  The address of a byte (8 bits) array of compressed
 
115
%      pixel data.
 
116
%
 
117
%    o length:  An integer value that is the total number of bytes of the
 
118
%      source image (as just read by ReadBlob)
 
119
%
 
120
%    o pixels:  The address of a byte (8 bits) array of pixel data created by
 
121
%      the uncompression process.  The number of bytes in this array
 
122
%      must be at least equal to the number columns times the number of rows
 
123
%      of the source pixels.
 
124
%
 
125
%
 
126
*/
 
127
static unsigned int DecodeImage(const unsigned char *compressed_pixels,
 
128
  const size_t length,unsigned char *pixels)
 
129
{
 
130
  register const unsigned char
 
131
    *p;
 
132
 
 
133
  register long
 
134
    count;
 
135
 
 
136
  register unsigned char
 
137
    *q;
 
138
 
 
139
  unsigned char
 
140
    byte;
 
141
 
 
142
  assert(compressed_pixels != (unsigned char *) NULL);
 
143
  assert(pixels != (unsigned char *) NULL);
 
144
  p=compressed_pixels;
 
145
  q=pixels;
 
146
  while ((size_t) (p-compressed_pixels) < length)
 
147
  {
 
148
    byte=(*p++);
 
149
    if (byte != 128)
 
150
      *q++=byte;
 
151
    else
 
152
      {
 
153
        /*
 
154
          Runlength-encoded packet: <count><byte>
 
155
        */
 
156
        count=(*p++);
 
157
        if (count > 0)
 
158
          byte=(*p++);
 
159
        while (count >= 0)
 
160
        {
 
161
          *q++=byte;
 
162
          count--;
 
163
        }
 
164
     }
 
165
  }
 
166
  return(True);
 
167
}
 
168
 
 
169
/*
 
170
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
171
%                                                                             %
 
172
%                                                                             %
 
173
%                                                                             %
 
174
%   R e a d S U N I m a g e                                                   %
 
175
%                                                                             %
 
176
%                                                                             %
 
177
%                                                                             %
 
178
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
179
%
 
180
%  Method ReadSUNImage reads a SUN image file and returns it.  It allocates
 
181
%  the memory necessary for the new Image structure and returns a pointer to
 
182
%  the new image.
 
183
%
 
184
%  The format of the ReadSUNImage method is:
 
185
%
 
186
%      Image *ReadSUNImage(const ImageInfo *image_info,ExceptionInfo *exception)
 
187
%
 
188
%  A description of each parameter follows:
 
189
%
 
190
%    o image:  Method ReadSUNImage returns a pointer to the image after
 
191
%      reading.  A null image is returned if there is a memory shortage or
 
192
%      if the image cannot be read.
 
193
%
 
194
%    o image_info: Specifies a pointer to a ImageInfo structure.
 
195
%
 
196
%    o exception: return any errors or warnings in this structure.
 
197
%
 
198
%
 
199
*/
 
200
static Image *ReadSUNImage(const ImageInfo *image_info,ExceptionInfo *exception)
 
201
{
 
202
#define RMT_EQUAL_RGB  1
 
203
#define RMT_NONE  0
 
204
#define RMT_RAW  2
 
205
#define RT_STANDARD  1
 
206
#define RT_ENCODED  2
 
207
#define RT_FORMAT_RGB  3
 
208
 
 
209
  typedef struct _SUNInfo
 
210
  {
 
211
    unsigned long
 
212
      magic,
 
213
      width,
 
214
      height,
 
215
      depth,
 
216
      length,
 
217
      type,
 
218
      maptype,
 
219
      maplength;
 
220
  } SUNInfo;
 
221
 
 
222
  Image
 
223
    *image;
 
224
 
 
225
  int
 
226
    bit;
 
227
 
 
228
  long
 
229
    y;
 
230
 
 
231
  register IndexPacket
 
232
    *indexes;
 
233
 
 
234
  register long
 
235
    x;
 
236
 
 
237
  register PixelPacket
 
238
    *q;
 
239
 
 
240
  register long
 
241
    i;
 
242
 
 
243
  register unsigned char
 
244
    *p;
 
245
 
 
246
  size_t
 
247
    count;
 
248
 
 
249
  SUNInfo
 
250
    sun_info;
 
251
 
 
252
  unsigned char
 
253
    *sun_data,
 
254
    *sun_pixels;
 
255
 
 
256
  unsigned int
 
257
    status;
 
258
 
 
259
  unsigned long
 
260
    bytes_per_line;
 
261
 
 
262
  /*
 
263
    Open image file.
 
264
  */
 
265
  assert(image_info != (const ImageInfo *) NULL);
 
266
  assert(image_info->signature == MagickSignature);
 
267
  assert(exception != (ExceptionInfo *) NULL);
 
268
  assert(exception->signature == MagickSignature);
 
269
  image=AllocateImage(image_info);
 
270
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
 
271
  if (status == False)
 
272
    ThrowReaderException(FileOpenError,UnableToOpenFile,image);
 
273
  /*
 
274
    Read SUN raster header.
 
275
  */
 
276
  sun_info.magic=ReadBlobMSBLong(image);
 
277
  do
 
278
  {
 
279
    /*
 
280
      Verify SUN identifier.
 
281
    */
 
282
    if (sun_info.magic != 0x59a66a95)
 
283
      ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
 
284
    sun_info.width=ReadBlobMSBLong(image);
 
285
    sun_info.height=ReadBlobMSBLong(image);
 
286
    sun_info.depth=ReadBlobMSBLong(image);
 
287
    sun_info.length=ReadBlobMSBLong(image);
 
288
    sun_info.type=ReadBlobMSBLong(image);
 
289
    sun_info.maptype=ReadBlobMSBLong(image);
 
290
    sun_info.maplength=ReadBlobMSBLong(image);
 
291
    image->columns= sun_info.width;
 
292
    image->rows= sun_info.height;
 
293
    image->depth=sun_info.depth <= 8 ? 8 : QuantumDepth;
 
294
    if (sun_info.depth < 24)
 
295
      {
 
296
        image->storage_class=PseudoClass;
 
297
        image->colors=sun_info.maplength;
 
298
        if (sun_info.maptype == RMT_NONE)
 
299
          image->colors=1 << sun_info.depth;
 
300
        if (sun_info.maptype == RMT_EQUAL_RGB)
 
301
          image->colors=sun_info.maplength/3;
 
302
      }
 
303
    switch (sun_info.maptype)
 
304
    {
 
305
      case RMT_NONE:
 
306
      {
 
307
        if (sun_info.depth < 24)
 
308
          {
 
309
            /*
 
310
              Create linear color ramp.
 
311
            */
 
312
            if (!AllocateImageColormap(image,image->colors))
 
313
              ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
 
314
                image);
 
315
          }
 
316
        break;
 
317
      }
 
318
      case RMT_EQUAL_RGB:
 
319
      {
 
320
        unsigned char
 
321
          *sun_colormap;
 
322
 
 
323
        /*
 
324
          Read SUN raster colormap.
 
325
        */
 
326
        if (!AllocateImageColormap(image,image->colors))
 
327
          ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
 
328
            image);
 
329
        sun_colormap=MagickAllocateMemory(unsigned char *,image->colors);
 
330
        if (sun_colormap == (unsigned char *) NULL)
 
331
          ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
 
332
            image);
 
333
        (void) ReadBlob(image,image->colors,(char *) sun_colormap);
 
334
        for (i=0; i < (long) image->colors; i++)
 
335
          image->colormap[i].red=ScaleCharToQuantum(sun_colormap[i]);
 
336
        (void) ReadBlob(image,image->colors,(char *) sun_colormap);
 
337
        for (i=0; i < (long) image->colors; i++)
 
338
          image->colormap[i].green=ScaleCharToQuantum(sun_colormap[i]);
 
339
        (void) ReadBlob(image,image->colors,(char *) sun_colormap);
 
340
        for (i=0; i < (long) image->colors; i++)
 
341
          image->colormap[i].blue=ScaleCharToQuantum(sun_colormap[i]);
 
342
        MagickFreeMemory(sun_colormap);
 
343
        break;
 
344
      }
 
345
      case RMT_RAW:
 
346
      {
 
347
        unsigned char
 
348
          *sun_colormap;
 
349
 
 
350
        /*
 
351
          Read SUN raster colormap.
 
352
        */
 
353
        sun_colormap=MagickAllocateMemory(unsigned char *,sun_info.maplength);
 
354
        if (sun_colormap == (unsigned char *) NULL)
 
355
          ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
 
356
            image);
 
357
        (void) ReadBlob(image,sun_info.maplength,(char *) sun_colormap);
 
358
        MagickFreeMemory(sun_colormap);
 
359
        break;
 
360
      }
 
361
      default:
 
362
        ThrowReaderException(CoderError,ColormapTypeNotSupported,image)
 
363
    } 
 
364
    image->matte=(sun_info.depth == 32);
 
365
    image->columns=sun_info.width;
 
366
    image->rows=sun_info.height;
 
367
    if (image_info->ping)
 
368
      {
 
369
        CloseBlob(image);
 
370
        return(image);
 
371
      }
 
372
    sun_data=MagickAllocateMemory(unsigned char *,sun_info.length);
 
373
    if (sun_data == (unsigned char *) NULL)
 
374
      ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
 
375
    count=ReadBlob(image,sun_info.length,(char *) sun_data);
 
376
    if ((count == 0) && (sun_info.type != RT_ENCODED))
 
377
      ThrowReaderException(CorruptImageError,UnableToReadImageData,image);
 
378
    sun_pixels=sun_data;
 
379
    if (sun_info.type == RT_ENCODED)
 
380
      {
 
381
        unsigned long
 
382
          height;
 
383
 
 
384
        /*
 
385
          Read run-length encoded raster pixels.
 
386
        */
 
387
        height=sun_info.height;
 
388
        bytes_per_line=2*(sun_info.width*sun_info.depth+15)/16;
 
389
        sun_pixels=MagickAllocateMemory(unsigned char *,bytes_per_line*height);
 
390
        if (sun_pixels == (unsigned char *) NULL)
 
391
          ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
 
392
            image);
 
393
        (void) DecodeImage(sun_data,sun_info.length,sun_pixels);
 
394
        MagickFreeMemory(sun_data);
 
395
      }
 
396
    /*
 
397
      Convert SUN raster image to pixel packets.
 
398
    */
 
399
    p=sun_pixels;
 
400
    if (sun_info.depth == 1)
 
401
      for (y=0; y < (long) image->rows; y++)
 
402
      {
 
403
        q=SetImagePixels(image,0,y,image->columns,1);
 
404
        if (q == (PixelPacket *) NULL)
 
405
          break;
 
406
        indexes=GetIndexes(image);
 
407
        for (x=0; x < ((long) image->columns-7); x+=8)
 
408
        {
 
409
          for (bit=7; bit >= 0; bit--)
 
410
            indexes[x+7-bit]=((*p) & (0x01 << bit) ? 0x01 : 0x00);
 
411
          p++;
 
412
        }
 
413
        if ((image->columns % 8) != 0)
 
414
          {
 
415
            for (bit=7; bit >= (long) (8-(image->columns % 8)); bit--)
 
416
              indexes[x+7-bit]=((*p) & (0x01 << bit) ? 0x01 : 0x00);
 
417
            p++;
 
418
          }
 
419
        if ((((image->columns/8)+(image->columns % 8 ? 1 : 0)) % 2) != 0)
 
420
          p++;
 
421
        if (!SyncImagePixels(image))
 
422
          break;
 
423
        if (image->previous == (Image *) NULL)
 
424
          if (QuantumTick(y,image->rows))
 
425
            if (!MagickMonitor(LoadImageText,y,image->rows,exception))
 
426
              break;
 
427
      }
 
428
    else
 
429
      if (image->storage_class == PseudoClass)
 
430
        for (y=0; y < (long) image->rows; y++)
 
431
        {
 
432
          q=SetImagePixels(image,0,y,image->columns,1);
 
433
          if (q == (PixelPacket *) NULL)
 
434
            break;
 
435
          indexes=GetIndexes(image);
 
436
          for (x=0; x < (long) image->columns; x++)
 
437
            indexes[x]=(*p++);
 
438
          if ((image->columns % 2) != 0)
 
439
            p++;
 
440
          if (!SyncImagePixels(image))
 
441
            break;
 
442
          if (image->previous == (Image *) NULL)
 
443
            if (QuantumTick(y,image->rows))
 
444
              if (!MagickMonitor(LoadImageText,y,image->rows,exception))
 
445
                break;
 
446
        }
 
447
      else
 
448
        for (y=0; y < (long) image->rows; y++)
 
449
        {
 
450
          q=SetImagePixels(image,0,y,image->columns,1);
 
451
          if (q == (PixelPacket *) NULL)
 
452
            break;
 
453
          for (x=0; x < (long) image->columns; x++)
 
454
          {
 
455
            if (image->matte)
 
456
              q->opacity=(Quantum) (MaxRGB-ScaleCharToQuantum(*p++));
 
457
            if (sun_info.type == RT_STANDARD)
 
458
              {
 
459
                q->blue=ScaleCharToQuantum(*p++);
 
460
                q->green=ScaleCharToQuantum(*p++);
 
461
                q->red=ScaleCharToQuantum(*p++);
 
462
              }
 
463
            else
 
464
              {
 
465
                q->red=ScaleCharToQuantum(*p++);
 
466
                q->green=ScaleCharToQuantum(*p++);
 
467
                q->blue=ScaleCharToQuantum(*p++);
 
468
              }
 
469
            if (image->colors != 0)
 
470
              {
 
471
                q->red=image->colormap[q->red].red;
 
472
                q->green=image->colormap[q->green].green;
 
473
                q->blue=image->colormap[q->blue].blue;
 
474
              }
 
475
            q++;
 
476
          }
 
477
          if (((image->columns % 2) != 0) && (image->matte == False))
 
478
            p++;
 
479
          if (!SyncImagePixels(image))
 
480
            break;
 
481
          if (image->previous == (Image *) NULL)
 
482
            if (QuantumTick(y,image->rows))
 
483
              if (!MagickMonitor(LoadImageText,y,image->rows,exception))
 
484
                break;
 
485
        }
 
486
    if (image->storage_class == PseudoClass)
 
487
      SyncImage(image);
 
488
    MagickFreeMemory(sun_pixels);
 
489
    if (EOFBlob(image))
 
490
      {
 
491
        ThrowException(exception,CorruptImageError,UnexpectedEndOfFile,
 
492
          image->filename);
 
493
        break;
 
494
      }
 
495
    /*
 
496
      Proceed to next image.
 
497
    */
 
498
    if (image_info->subrange != 0)
 
499
      if (image->scene >= (image_info->subimage+image_info->subrange-1))
 
500
        break;
 
501
    sun_info.magic=ReadBlobMSBLong(image);
 
502
    if (sun_info.magic == 0x59a66a95)
 
503
      {
 
504
        /*
 
505
          Allocate next image structure.
 
506
        */
 
507
        AllocateNextImage(image_info,image);
 
508
        if (image->next == (Image *) NULL)
 
509
          {
 
510
            DestroyImageList(image);
 
511
            return((Image *) NULL);
 
512
          }
 
513
        image=SyncNextImageInList(image);
 
514
        if (!MagickMonitor(LoadImagesText,TellBlob(image),GetBlobSize(image),exception))
 
515
          break;
 
516
      }
 
517
  } while (sun_info.magic == 0x59a66a95);
 
518
  while (image->previous != (Image *) NULL)
 
519
    image=image->previous;
 
520
  CloseBlob(image);
 
521
  return(image);
 
522
}
 
523
 
 
524
/*
 
525
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
526
%                                                                             %
 
527
%                                                                             %
 
528
%                                                                             %
 
529
%   R e g i s t e r S U N I m a g e                                           %
 
530
%                                                                             %
 
531
%                                                                             %
 
532
%                                                                             %
 
533
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
534
%
 
535
%  Method RegisterSUNImage adds attributes for the SUN image format to
 
536
%  the list of supported formats.  The attributes include the image format
 
537
%  tag, a method to read and/or write the format, whether the format
 
538
%  supports the saving of more than one frame to the same file or blob,
 
539
%  whether the format supports native in-memory I/O, and a brief
 
540
%  description of the format.
 
541
%
 
542
%  The format of the RegisterSUNImage method is:
 
543
%
 
544
%      RegisterSUNImage(void)
 
545
%
 
546
*/
 
547
ModuleExport void RegisterSUNImage(void)
 
548
{
 
549
  MagickInfo
 
550
    *entry;
 
551
 
 
552
  entry=SetMagickInfo("RAS");
 
553
  entry->decoder=(DecoderHandler) ReadSUNImage;
 
554
  entry->encoder=(EncoderHandler) WriteSUNImage;
 
555
  entry->magick=(MagickHandler) IsSUN;
 
556
  entry->description=AcquireString("SUN Rasterfile");
 
557
  entry->module=AcquireString("SUN");
 
558
  (void) RegisterMagickInfo(entry);
 
559
  entry=SetMagickInfo("SUN");
 
560
  entry->decoder=(DecoderHandler) ReadSUNImage;
 
561
  entry->encoder=(EncoderHandler) WriteSUNImage;
 
562
  entry->description=AcquireString("SUN Rasterfile");
 
563
  entry->module=AcquireString("SUN");
 
564
  (void) RegisterMagickInfo(entry);
 
565
}
 
566
 
 
567
/*
 
568
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
569
%                                                                             %
 
570
%                                                                             %
 
571
%                                                                             %
 
572
%   U n r e g i s t e r S U N I m a g e                                       %
 
573
%                                                                             %
 
574
%                                                                             %
 
575
%                                                                             %
 
576
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
577
%
 
578
%  Method UnregisterSUNImage removes format registrations made by the
 
579
%  SUN module from the list of supported formats.
 
580
%
 
581
%  The format of the UnregisterSUNImage method is:
 
582
%
 
583
%      UnregisterSUNImage(void)
 
584
%
 
585
*/
 
586
ModuleExport void UnregisterSUNImage(void)
 
587
{
 
588
  (void) UnregisterMagickInfo("RAS");
 
589
  (void) UnregisterMagickInfo("SUN");
 
590
}
 
591
 
 
592
/*
 
593
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
594
%                                                                             %
 
595
%                                                                             %
 
596
%                                                                             %
 
597
%   W r i t e S U N I m a g e                                                 %
 
598
%                                                                             %
 
599
%                                                                             %
 
600
%                                                                             %
 
601
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
602
%
 
603
%  Method WriteSUNImage writes an image in the SUN rasterfile format.
 
604
%
 
605
%  The format of the WriteSUNImage method is:
 
606
%
 
607
%      unsigned int WriteSUNImage(const ImageInfo *image_info,Image *image)
 
608
%
 
609
%  A description of each parameter follows.
 
610
%
 
611
%    o status: Method WriteSUNImage return True if the image is written.
 
612
%      False is returned is there is a memory shortage or if the image file
 
613
%      fails to write.
 
614
%
 
615
%    o image_info: Specifies a pointer to a ImageInfo structure.
 
616
%
 
617
%    o image:  A pointer to an Image structure.
 
618
%
 
619
%
 
620
*/
 
621
static unsigned int WriteSUNImage(const ImageInfo *image_info,Image *image)
 
622
{
 
623
#define RMT_EQUAL_RGB  1
 
624
#define RMT_NONE  0
 
625
#define RMT_RAW  2
 
626
#define RT_STANDARD  1
 
627
#define RT_FORMAT_RGB  3
 
628
 
 
629
  typedef struct _SUNInfo
 
630
  {
 
631
    unsigned long
 
632
      magic,
 
633
      width,
 
634
      height,
 
635
      depth,
 
636
      length,
 
637
      type,
 
638
      maptype,
 
639
      maplength;
 
640
  } SUNInfo;
 
641
 
 
642
  long
 
643
    y;
 
644
 
 
645
  register const PixelPacket
 
646
    *p;
 
647
 
 
648
  register IndexPacket
 
649
    *indexes;
 
650
 
 
651
  register long
 
652
    x;
 
653
 
 
654
  register long
 
655
    i;
 
656
 
 
657
  SUNInfo
 
658
    sun_info;
 
659
 
 
660
  unsigned int
 
661
    status;
 
662
 
 
663
  unsigned long
 
664
    number_pixels,
 
665
    scene;
 
666
 
 
667
  /*
 
668
    Open output image file.
 
669
  */
 
670
  assert(image_info != (const ImageInfo *) NULL);
 
671
  assert(image_info->signature == MagickSignature);
 
672
  assert(image != (Image *) NULL);
 
673
  assert(image->signature == MagickSignature);
 
674
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
 
675
  if (status == False)
 
676
    ThrowWriterException(FileOpenError,UnableToOpenFile,image);
 
677
  scene=0;
 
678
  do
 
679
  {
 
680
    /*
 
681
      Initialize SUN raster file header.
 
682
    */
 
683
    TransformColorspace(image,RGBColorspace);
 
684
    sun_info.magic=0x59a66a95;
 
685
    sun_info.width=image->columns;
 
686
    sun_info.height=image->rows;
 
687
    sun_info.type=
 
688
      (image->storage_class == DirectClass ? RT_FORMAT_RGB : RT_STANDARD);
 
689
    sun_info.maptype=RMT_NONE;
 
690
    sun_info.maplength=0;
 
691
    number_pixels=image->columns*image->rows;
 
692
    if (image->storage_class == DirectClass)
 
693
      {
 
694
        /*
 
695
          Full color SUN raster.
 
696
        */
 
697
        sun_info.depth=(image->matte ? 32 : 24);
 
698
        sun_info.length=(image->matte ? 4 : 3)*number_pixels;
 
699
        sun_info.length+=image->columns & 0x01 ? image->rows : 0;
 
700
      }
 
701
    else
 
702
      if (IsMonochromeImage(image,&image->exception))
 
703
        {
 
704
          /*
 
705
            Monochrome SUN raster.
 
706
          */
 
707
          sun_info.depth=1;
 
708
          sun_info.length=((image->columns+7) >> 3)*image->rows;
 
709
          sun_info.length+=((image->columns/8)+(image->columns % 8 ? 1 : 0)) %
 
710
            2 ? image->rows : 0;
 
711
        }
 
712
      else
 
713
        {
 
714
          /*
 
715
            Colormapped SUN raster.
 
716
          */
 
717
          sun_info.depth=8;
 
718
          sun_info.length=number_pixels;
 
719
          sun_info.length+=image->columns & 0x01 ? image->rows : 0;
 
720
          sun_info.maptype=RMT_EQUAL_RGB;
 
721
          sun_info.maplength=image->colors*3;
 
722
        }
 
723
    /*
 
724
      Write SUN header.
 
725
    */
 
726
    (void) WriteBlobMSBLong(image,sun_info.magic);
 
727
    (void) WriteBlobMSBLong(image,sun_info.width);
 
728
    (void) WriteBlobMSBLong(image,sun_info.height);
 
729
    (void) WriteBlobMSBLong(image,sun_info.depth);
 
730
    (void) WriteBlobMSBLong(image,sun_info.length);
 
731
    (void) WriteBlobMSBLong(image,sun_info.type);
 
732
    (void) WriteBlobMSBLong(image,sun_info.maptype);
 
733
    (void) WriteBlobMSBLong(image,sun_info.maplength);
 
734
    /*
 
735
      Convert MIFF to SUN raster pixels.
 
736
    */
 
737
    x=0;
 
738
    y=0;
 
739
    if (image->storage_class == DirectClass)
 
740
      {
 
741
        register unsigned char
 
742
          *q;
 
743
 
 
744
        size_t
 
745
          length;
 
746
 
 
747
        unsigned char
 
748
          *pixels;
 
749
 
 
750
        /*
 
751
          Allocate memory for pixels.
 
752
        */
 
753
        length=image->columns*sizeof(PixelPacket);
 
754
        pixels=MagickAllocateMemory(unsigned char *,length);
 
755
        if (pixels == (unsigned char *) NULL)
 
756
          ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,
 
757
            image);
 
758
        /*
 
759
          Convert DirectClass packet to SUN RGB pixel.
 
760
        */
 
761
        for (y=0; y < (long) image->rows; y++)
 
762
        {
 
763
          p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
 
764
          if (p == (const PixelPacket *) NULL)
 
765
            break;
 
766
          q=pixels;
 
767
          for (x=0; x < (long) image->columns; x++)
 
768
          {
 
769
            if (image->matte)
 
770
              *q++=ScaleQuantumToChar(MaxRGB-p->opacity);
 
771
            *q++=ScaleQuantumToChar(p->red);
 
772
            *q++=ScaleQuantumToChar(p->green);
 
773
            *q++=ScaleQuantumToChar(p->blue);
 
774
            p++;
 
775
          }
 
776
          if (image->columns & 0x01)
 
777
            *q++=0;  /* pad scanline */
 
778
          (void) WriteBlob(image,q-pixels,(char *) pixels);
 
779
          if (image->previous == (Image *) NULL)
 
780
            if (QuantumTick(y,image->rows))
 
781
              if (!MagickMonitor(SaveImageText,y,image->rows,&image->exception))
 
782
                break;
 
783
        }
 
784
        MagickFreeMemory(pixels);
 
785
      }
 
786
    else
 
787
      if (IsMonochromeImage(image,&image->exception))
 
788
        {
 
789
          register unsigned char
 
790
            bit,
 
791
            byte,
 
792
            polarity;
 
793
 
 
794
          /*
 
795
            Convert PseudoClass image to a SUN monochrome image.
 
796
          */
 
797
          SetImageType(image,BilevelType);
 
798
          polarity=PixelIntensityToQuantum(&image->colormap[0]) < (MaxRGB/2);
 
799
          if (image->colors == 2)
 
800
            polarity=PixelIntensityToQuantum(&image->colormap[0]) <
 
801
              PixelIntensityToQuantum(&image->colormap[1]);
 
802
          for (y=0; y < (long) image->rows; y++)
 
803
          {
 
804
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
 
805
            if (p == (const PixelPacket *) NULL)
 
806
              break;
 
807
            indexes=GetIndexes(image);
 
808
            bit=0;
 
809
            byte=0;
 
810
            for (x=0; x < (long) image->columns; x++)
 
811
            {
 
812
              byte<<=1;
 
813
              if (indexes[x] == polarity)
 
814
                byte|=0x01;
 
815
              bit++;
 
816
              if (bit == 8)
 
817
                {
 
818
                  (void) WriteBlobByte(image,byte);
 
819
                  bit=0;
 
820
                  byte=0;
 
821
                }
 
822
              p++;
 
823
            }
 
824
            if (bit != 0)
 
825
              (void) WriteBlobByte(image,byte << (8-bit));
 
826
            if ((((image->columns/8)+
 
827
                (image->columns % 8 ? 1 : 0)) % 2) != 0)
 
828
              (void) WriteBlobByte(image,0);  /* pad scanline */
 
829
            if (image->previous == (Image *) NULL)
 
830
              if (QuantumTick(y,image->rows))
 
831
                if (!MagickMonitor(SaveImageText,y,image->rows,&image->exception))
 
832
                  break;
 
833
          }
 
834
        }
 
835
      else
 
836
        {
 
837
          /*
 
838
            Dump colormap to file.
 
839
          */
 
840
          for (i=0; i < (long) image->colors; i++)
 
841
            (void) WriteBlobByte(image,ScaleQuantumToChar(image->colormap[i].red));
 
842
          for (i=0; i < (long) image->colors; i++)
 
843
            (void) WriteBlobByte(image,ScaleQuantumToChar(image->colormap[i].green));
 
844
          for (i=0; i < (long) image->colors; i++)
 
845
            (void) WriteBlobByte(image,ScaleQuantumToChar(image->colormap[i].blue));
 
846
          /*
 
847
            Convert PseudoClass packet to SUN colormapped pixel.
 
848
          */
 
849
          for (y=0; y < (long) image->rows; y++)
 
850
          {
 
851
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
 
852
            if (p == (const PixelPacket *) NULL)
 
853
              break;
 
854
            indexes=GetIndexes(image);
 
855
            for (x=0; x < (long) image->columns; x++)
 
856
            {
 
857
              (void) WriteBlobByte(image,indexes[x]);
 
858
              p++;
 
859
            }
 
860
            if (image->columns & 0x01)
 
861
              (void) WriteBlobByte(image,0);  /* pad scanline */
 
862
            if (image->previous == (Image *) NULL)
 
863
              if (QuantumTick(y,image->rows))
 
864
                if (!MagickMonitor(SaveImageText,y,image->rows,&image->exception))
 
865
                  break;
 
866
          }
 
867
        }
 
868
    if (image->next == (Image *) NULL)
 
869
      break;
 
870
    image=SyncNextImageInList(image);
 
871
    if (!MagickMonitor(SaveImagesText,scene++,GetImageListLength(image),&image->exception))
 
872
      break;
 
873
  } while (image_info->adjoin);
 
874
  if (image_info->adjoin)
 
875
    while (image->previous != (Image *) NULL)
 
876
      image=image->previous;
 
877
  CloseBlob(image);
 
878
  return(True);
 
879
}