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

« back to all changes in this revision

Viewing changes to coders/cmyk.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
%                         CCCC  M   M  Y   Y  K   K                           %
 
15
%                        C      MM MM   Y Y   K  K                            %
 
16
%                        C      M M M    Y    KKK                             %
 
17
%                        C      M   M    Y    K  K                            %
 
18
%                         CCCC  M   M    Y    K   K                           %
 
19
%                                                                             %
 
20
%                                                                             %
 
21
%                     Read/Write RAW CMYK 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/cache.h"
 
40
#include "magick/constitute.h"
 
41
#include "magick/blob.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
  WriteCMYKImage(const ImageInfo *,Image *);
 
51
 
 
52
/*
 
53
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
54
%                                                                             %
 
55
%                                                                             %
 
56
%                                                                             %
 
57
%   R e a d C M Y K I m a g e                                                 %
 
58
%                                                                             %
 
59
%                                                                             %
 
60
%                                                                             %
 
61
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
62
%
 
63
%  Method ReadCMYKImage reads an image of raw cyan, magenta, yellow, and black
 
64
%  samples and returns it.  It allocates the memory necessary for the new
 
65
%  Image structure and returns a pointer to the new image.
 
66
%
 
67
%  The format of the ReadCMYKImage method is:
 
68
%
 
69
%      Image *ReadCMYKImage(const ImageInfo *image_info,
 
70
%        ExceptionInfo *exception)
 
71
%
 
72
%  A description of each parameter follows:
 
73
%
 
74
%    o image:  Method ReadCMYKImage returns a pointer to the image after
 
75
%      reading.  A null image is returned if there is a memory shortage or
 
76
%      if the image cannot be read.
 
77
%
 
78
%    o image_info: Specifies a pointer to a ImageInfo structure.
 
79
%
 
80
%    o exception: return any errors or warnings in this structure.
 
81
%
 
82
%
 
83
*/
 
84
static Image *ReadCMYKImage(const ImageInfo *image_info,
 
85
  ExceptionInfo *exception)
 
86
{
 
87
  Image
 
88
    *image;
 
89
 
 
90
  long
 
91
    y;
 
92
 
 
93
  register long
 
94
    i,
 
95
    x;
 
96
 
 
97
  register PixelPacket
 
98
    *q;
 
99
 
 
100
  size_t
 
101
    count;
 
102
 
 
103
  unsigned char
 
104
    *scanline;
 
105
 
 
106
  unsigned int
 
107
    status;
 
108
 
 
109
  unsigned long
 
110
    packet_size;
 
111
 
 
112
  assert(image_info != (const ImageInfo *) NULL);
 
113
  assert(image_info->signature == MagickSignature);
 
114
  assert(exception != (ExceptionInfo *) NULL);
 
115
  assert(exception->signature == MagickSignature);
 
116
  image=AllocateImage(image_info);
 
117
  if ((image->columns == 0) || (image->rows == 0))
 
118
    ThrowReaderException(OptionError,MustSpecifyImageSize,image);
 
119
  if (image_info->interlace != PartitionInterlace)
 
120
    {
 
121
      /*
 
122
        Open image file.
 
123
      */
 
124
      status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
 
125
      if (status == False)
 
126
        ThrowReaderException(FileOpenError,UnableToOpenFile,image);
 
127
      for (i=0; i < image->offset; i++)
 
128
        (void) ReadBlobByte(image);
 
129
    }
 
130
  /*
 
131
    Allocate memory for a scanline.
 
132
  */
 
133
  packet_size=image->depth > 8 ? 8 : 4;
 
134
  if (LocaleCompare(image_info->magick,"CMYKA") == 0)
 
135
    {
 
136
      image->matte=True;
 
137
      packet_size=image->depth > 8 ? 10 : 8;
 
138
    }
 
139
  scanline=MagickAllocateMemory(unsigned char *,
 
140
    packet_size*image->tile_info.width);
 
141
  if (scanline == (unsigned char *) NULL)
 
142
    ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
 
143
  if (image_info->subrange != 0)
 
144
    while (image->scene < image_info->subimage)
 
145
    {
 
146
      /*
 
147
        Skip to next image.
 
148
      */
 
149
      image->scene++;
 
150
      for (y=0; y < (long) image->rows; y++)
 
151
        (void) ReadBlob(image,packet_size*image->tile_info.width,scanline);
 
152
    }
 
153
  x=(long) (packet_size*image->tile_info.x);
 
154
  do
 
155
  {
 
156
    /*
 
157
      Convert raster image to pixel packets.
 
158
    */
 
159
    image->colorspace=CMYKColorspace;
 
160
    if (image_info->ping && (image_info->subrange != 0))
 
161
      if (image->scene >= (image_info->subimage+image_info->subrange-1))
 
162
        break;
 
163
    switch (image_info->interlace)
 
164
    {
 
165
      case NoInterlace:
 
166
      default:
 
167
      {
 
168
        /*
 
169
          No interlacing:  CMYKCMYKCMYKCMYKCMYKCMYK...
 
170
        */
 
171
        for (y=0; y < image->tile_info.y; y++)
 
172
          (void) ReadBlob(image,packet_size*image->tile_info.width,scanline);
 
173
        for (y=0; y < (long) image->rows; y++)
 
174
        {
 
175
          if ((y > 0) || (image->previous == (Image *) NULL))
 
176
            (void) ReadBlob(image,packet_size*image->tile_info.width,scanline);
 
177
          q=SetImagePixels(image,0,y,image->columns,1);
 
178
          if (q == (PixelPacket *) NULL)
 
179
            break;
 
180
          if (!image->matte)
 
181
            (void) PushImagePixels(image,CMYKQuantum,scanline+x);
 
182
          else
 
183
            (void) PushImagePixels(image,CMYKAQuantum,scanline+x);
 
184
          if (!SyncImagePixels(image))
 
185
            break;
 
186
          if (image->previous == (Image *) NULL)
 
187
            if (QuantumTick(y,image->rows))
 
188
              if (!MagickMonitor(LoadImageText,y,image->rows,exception))
 
189
                break;
 
190
        }
 
191
        count=image->tile_info.height-image->rows-image->tile_info.y;
 
192
        for (i=0; i < (long) count; i++)
 
193
          (void) ReadBlob(image,packet_size*image->tile_info.width,scanline);
 
194
        break;
 
195
      }
 
196
      case LineInterlace:
 
197
      {
 
198
        /*
 
199
          Line interlacing:  CCC...MMM...YYY...KKK...CCC...MMM...YYY...KKK...
 
200
        */
 
201
        packet_size=image->depth > 8 ? 2 : 1;
 
202
        for (y=0; y < image->tile_info.y; y++)
 
203
          (void) ReadBlob(image,packet_size*image->tile_info.width,scanline);
 
204
        for (y=0; y < (long) image->rows; y++)
 
205
        {
 
206
          if ((y > 0) || (image->previous == (Image *) NULL))
 
207
            (void) ReadBlob(image,packet_size*image->tile_info.width,scanline);
 
208
          q=SetImagePixels(image,0,y,image->columns,1);
 
209
          if (q == (PixelPacket *) NULL)
 
210
            break;
 
211
          (void) PushImagePixels(image,CyanQuantum,scanline+x);
 
212
          (void) ReadBlob(image,packet_size*image->tile_info.width,scanline);
 
213
          (void) PushImagePixels(image,MagentaQuantum,scanline+x);
 
214
          (void) ReadBlob(image,packet_size*image->tile_info.width,scanline);
 
215
          (void) PushImagePixels(image,YellowQuantum,scanline+x);
 
216
          (void) ReadBlob(image,packet_size*image->tile_info.width,scanline);
 
217
          (void) PushImagePixels(image,BlackQuantum,scanline+x);
 
218
          if (image->matte)
 
219
            {
 
220
              (void) ReadBlob(image,packet_size*image->tile_info.width,
 
221
                scanline);
 
222
              (void) PushImagePixels(image,AlphaQuantum,scanline+x);
 
223
            }
 
224
          if (!SyncImagePixels(image))
 
225
            break;
 
226
          if (image->previous == (Image *) NULL)
 
227
            if (QuantumTick(y,image->rows))
 
228
              if (!MagickMonitor(LoadImageText,y,image->rows,exception))
 
229
                break;
 
230
        }
 
231
        count=image->tile_info.height-image->rows-image->tile_info.y;
 
232
        for (i=0; i < (long) count; i++)
 
233
          (void) ReadBlob(image,packet_size*image->tile_info.width,scanline);
 
234
        break;
 
235
      }
 
236
      case PlaneInterlace:
 
237
      case PartitionInterlace:
 
238
      {
 
239
        unsigned long
 
240
          span;
 
241
 
 
242
        /*
 
243
          Plane interlacing:  CCCCCC...MMMMMM...YYYYYY...KKKKKK...
 
244
        */
 
245
        if (image_info->interlace == PartitionInterlace)
 
246
          {
 
247
            AppendImageFormat("C",image->filename);
 
248
            status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
 
249
            if (status == False)
 
250
              ThrowReaderException(FileOpenError,UnableToOpenFile,image);
 
251
          }
 
252
        packet_size=image->depth > 8 ? 2 : 1;
 
253
        for (y=0; y < image->tile_info.y; y++)
 
254
          (void) ReadBlob(image,packet_size*image->tile_info.width,scanline);
 
255
        i=0;
 
256
        span=image->rows*(image->matte ? 5 : 4);
 
257
        for (y=0; y < (long) image->rows; y++)
 
258
        {
 
259
          if ((y > 0) || (image->previous == (Image *) NULL))
 
260
            (void) ReadBlob(image,packet_size*image->tile_info.width,scanline);
 
261
          q=SetImagePixels(image,0,y,image->columns,1);
 
262
          if (q == (PixelPacket *) NULL)
 
263
            break;
 
264
          (void) PushImagePixels(image,CyanQuantum,scanline+x);
 
265
          if (!SyncImagePixels(image))
 
266
            break;
 
267
          if (image->previous == (Image *) NULL)
 
268
            if (QuantumTick(i,span))
 
269
              if (!MagickMonitor(LoadImageText,i,span,&image->exception))
 
270
                break;
 
271
          i++;
 
272
        }
 
273
        count=image->tile_info.height-image->rows-image->tile_info.y;
 
274
        for (i=0; i < (long) count; i++)
 
275
          (void) ReadBlob(image,packet_size*image->tile_info.width,scanline);
 
276
        if (image_info->interlace == PartitionInterlace)
 
277
          {
 
278
            CloseBlob(image);
 
279
            AppendImageFormat("M",image->filename);
 
280
            status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
 
281
            if (status == False)
 
282
              ThrowReaderException(FileOpenError,UnableToOpenFile,image);
 
283
          }
 
284
        for (y=0; y < image->tile_info.y; y++)
 
285
          (void) ReadBlob(image,packet_size*image->tile_info.width,scanline);
 
286
        for (y=0; y < (long) image->rows; y++)
 
287
        {
 
288
          (void) ReadBlob(image,packet_size*image->tile_info.width,scanline);
 
289
          q=GetImagePixels(image,0,y,image->columns,1);
 
290
          if (q == (PixelPacket *) NULL)
 
291
            break;
 
292
          (void) PushImagePixels(image,MagentaQuantum,scanline+x);
 
293
          if (!SyncImagePixels(image))
 
294
            break;
 
295
          if (image->previous == (Image *) NULL)
 
296
            if (QuantumTick(i,span))
 
297
              if (!MagickMonitor(LoadImageText,i,span,&image->exception))
 
298
                break;
 
299
          i++;
 
300
        }
 
301
        count=image->tile_info.height-image->rows-image->tile_info.y;
 
302
        for (i=0; i < (long) count; i++)
 
303
          (void) ReadBlob(image,packet_size*image->tile_info.width,scanline);
 
304
        if (image_info->interlace == PartitionInterlace)
 
305
          {
 
306
            CloseBlob(image);
 
307
            AppendImageFormat("Y",image->filename);
 
308
            status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
 
309
            if (status == False)
 
310
              ThrowReaderException(FileOpenError,UnableToOpenFile,image);
 
311
          }
 
312
        for (y=0; y < image->tile_info.y; y++)
 
313
          (void) ReadBlob(image,packet_size*image->tile_info.width,scanline);
 
314
        for (y=0; y < (long) image->rows; y++)
 
315
        {
 
316
          (void) ReadBlob(image,packet_size*image->tile_info.width,scanline);
 
317
          q=GetImagePixels(image,0,y,image->columns,1);
 
318
          if (q == (PixelPacket *) NULL)
 
319
            break;
 
320
          (void) PushImagePixels(image,YellowQuantum,scanline+x);
 
321
          if (!SyncImagePixels(image))
 
322
            break;
 
323
          if (image->previous == (Image *) NULL)
 
324
            if (QuantumTick(i,span))
 
325
              if (!MagickMonitor(LoadImageText,i,span,&image->exception))
 
326
                break;
 
327
          i++;
 
328
        }
 
329
        count=image->tile_info.height-image->rows-image->tile_info.y;
 
330
        for (i=0; i < (long) count; i++)
 
331
          (void) ReadBlob(image,packet_size*image->tile_info.width,scanline);
 
332
        if (image_info->interlace == PartitionInterlace)
 
333
          {
 
334
            CloseBlob(image);
 
335
            AppendImageFormat("K",image->filename);
 
336
            status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
 
337
            if (status == False)
 
338
              ThrowReaderException(FileOpenError,UnableToOpenFile,image);
 
339
          }
 
340
        for (y=0; y < image->tile_info.y; y++)
 
341
          (void) ReadBlob(image,packet_size*image->tile_info.width,scanline);
 
342
        for (y=0; y < (long) image->rows; y++)
 
343
        {
 
344
          (void) ReadBlob(image,packet_size*image->tile_info.width,scanline);
 
345
          q=GetImagePixels(image,0,y,image->columns,1);
 
346
          if (q == (PixelPacket *) NULL)
 
347
            break;
 
348
          (void) PushImagePixels(image,BlackQuantum,scanline+x);
 
349
          if (!SyncImagePixels(image))
 
350
            break;
 
351
          if (image->previous == (Image *) NULL)
 
352
            if (QuantumTick(i,span))
 
353
              if (!MagickMonitor(LoadImageText,i,span,&image->exception))
 
354
                break;
 
355
          i++;
 
356
        }
 
357
        count=image->tile_info.height-image->rows-image->tile_info.y;
 
358
        for (i=0; i < (long) count; i++)
 
359
          (void) ReadBlob(image,packet_size*image->tile_info.width,scanline);
 
360
        if (image->matte)
 
361
          {
 
362
            /*
 
363
              Read matte channel.
 
364
            */
 
365
            if (image_info->interlace == PartitionInterlace)
 
366
              {
 
367
                CloseBlob(image);
 
368
                AppendImageFormat("A",image->filename);
 
369
                status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
 
370
                if (status == False)
 
371
                  ThrowReaderException(FileOpenError,UnableToOpenFile,image);
 
372
              }
 
373
            for (y=0; y < image->tile_info.y; y++)
 
374
              (void) ReadBlob(image,packet_size*image->tile_info.width,
 
375
                scanline);
 
376
            for (y=0; y < (long) image->rows; y++)
 
377
            {
 
378
              (void) ReadBlob(image,packet_size*image->tile_info.width,
 
379
                scanline);
 
380
              q=GetImagePixels(image,0,y,image->columns,1);
 
381
              if (q == (PixelPacket *) NULL)
 
382
                break;
 
383
              (void) PushImagePixels(image,AlphaQuantum,scanline+x);
 
384
              if (!SyncImagePixels(image))
 
385
                break;
 
386
              if (image->previous == (Image *) NULL)
 
387
                if (QuantumTick(i,span))
 
388
                  if (!MagickMonitor(LoadImageText,i,span,&image->exception))
 
389
                    break;
 
390
              i++;
 
391
            }
 
392
            count=image->tile_info.height-image->rows-image->tile_info.y;
 
393
            for (i=0; i < (long) count; i++)
 
394
              (void) ReadBlob(image,packet_size*image->tile_info.width,
 
395
                scanline);
 
396
          }
 
397
        if (image_info->interlace == PartitionInterlace)
 
398
          (void) strncpy(image->filename,image_info->filename,MaxTextExtent-1);
 
399
        break;
 
400
      }
 
401
    }
 
402
    if (EOFBlob(image))
 
403
      {
 
404
        ThrowException(exception,CorruptImageError,UnexpectedEndOfFile,
 
405
          image->filename);
 
406
        break;
 
407
      }
 
408
    /*
 
409
      Proceed to next image.
 
410
    */
 
411
    if (image_info->subrange != 0)
 
412
      if (image->scene >= (image_info->subimage+image_info->subrange-1))
 
413
        break;
 
414
    if (image_info->interlace == PartitionInterlace)
 
415
      break;
 
416
    count=ReadBlob(image,packet_size*image->tile_info.width,scanline);
 
417
    if (count != 0)
 
418
      {
 
419
        /*
 
420
          Allocate next image structure.
 
421
        */
 
422
        AllocateNextImage(image_info,image);
 
423
        if (image->next == (Image *) NULL)
 
424
          {
 
425
            DestroyImageList(image);
 
426
            return((Image *) NULL);
 
427
          }
 
428
        image=SyncNextImageInList(image);
 
429
        status=MagickMonitor(LoadImagesText,TellBlob(image),GetBlobSize(image),
 
430
          exception);
 
431
        if (status == False)
 
432
          break;
 
433
      }
 
434
  } while (count != 0);
 
435
  MagickFreeMemory(scanline);
 
436
  while (image->previous != (Image *) NULL)
 
437
    image=image->previous;
 
438
  CloseBlob(image);
 
439
  return(image);
 
440
}
 
441
 
 
442
/*
 
443
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
444
%                                                                             %
 
445
%                                                                             %
 
446
%                                                                             %
 
447
%   R e g i s t e r C M Y K I m a g e                                         %
 
448
%                                                                             %
 
449
%                                                                             %
 
450
%                                                                             %
 
451
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
452
%
 
453
%  Method RegisterCMYKImage adds attributes for the CMYK image format to
 
454
%  the list of supported formats.  The attributes include the image format
 
455
%  tag, a method to read and/or write the format, whether the format
 
456
%  supports the saving of more than one frame to the same file or blob,
 
457
%  whether the format supports native in-memory I/O, and a brief
 
458
%  description of the format.
 
459
%
 
460
%  The format of the RegisterCMYKImage method is:
 
461
%
 
462
%      RegisterCMYKImage(void)
 
463
%
 
464
*/
 
465
ModuleExport void RegisterCMYKImage(void)
 
466
{
 
467
  MagickInfo
 
468
    *entry;
 
469
 
 
470
  entry=SetMagickInfo("CMYK");
 
471
  entry->decoder=(DecoderHandler) ReadCMYKImage;
 
472
  entry->encoder=(EncoderHandler) WriteCMYKImage;
 
473
  entry->raw=True;
 
474
  entry->description=
 
475
    AcquireString("Raw cyan, magenta, yellow, and black samples");
 
476
  entry->module=AcquireString("CMYK");
 
477
  (void) RegisterMagickInfo(entry);
 
478
  entry=SetMagickInfo("CMYKA");
 
479
  entry->decoder=(DecoderHandler) ReadCMYKImage;
 
480
  entry->encoder=(EncoderHandler) WriteCMYKImage;
 
481
  entry->raw=True;
 
482
  entry->description=
 
483
    AcquireString("Raw cyan, magenta, yellow, black, and opacity samples");
 
484
  entry->module=AcquireString("CMYK");
 
485
  (void) RegisterMagickInfo(entry);
 
486
}
 
487
 
 
488
/*
 
489
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
490
%                                                                             %
 
491
%                                                                             %
 
492
%                                                                             %
 
493
%   U n r e g i s t e r C M Y K I m a g e                                     %
 
494
%                                                                             %
 
495
%                                                                             %
 
496
%                                                                             %
 
497
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
498
%
 
499
%  Method UnregisterCMYKImage removes format registrations made by the
 
500
%  CMYK module from the list of supported formats.
 
501
%
 
502
%  The format of the UnregisterCMYKImage method is:
 
503
%
 
504
%      UnregisterCMYKImage(void)
 
505
%
 
506
*/
 
507
ModuleExport void UnregisterCMYKImage(void)
 
508
{
 
509
  (void) UnregisterMagickInfo("CMYK");
 
510
  (void) UnregisterMagickInfo("CMYKA");
 
511
}
 
512
 
 
513
/*
 
514
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
515
%                                                                             %
 
516
%                                                                             %
 
517
%                                                                             %
 
518
%   W r i t e C M Y K I m a g e                                               %
 
519
%                                                                             %
 
520
%                                                                             %
 
521
%                                                                             %
 
522
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
523
%
 
524
%  Method WriteCMYKImage writes an image to a file in red, green, and blue
 
525
%  rasterfile format.
 
526
%
 
527
%  The format of the WriteCMYKImage method is:
 
528
%
 
529
%      unsigned int WriteCMYKImage(const ImageInfo *image_info,Image *image)
 
530
%
 
531
%  A description of each parameter follows.
 
532
%
 
533
%    o status: Method WriteCMYKImage return True if the image is written.
 
534
%      False is returned is there is a memory shortage or if the image file
 
535
%      fails to write.
 
536
%
 
537
%    o image_info: Specifies a pointer to a ImageInfo structure.
 
538
%
 
539
%    o image:  A pointer to an Image structure.
 
540
%
 
541
%
 
542
*/
 
543
static unsigned int WriteCMYKImage(const ImageInfo *image_info,Image *image)
 
544
{
 
545
  int
 
546
    y;
 
547
 
 
548
  register const PixelPacket
 
549
    *p;
 
550
 
 
551
  unsigned char
 
552
    *pixels;
 
553
 
 
554
  unsigned int
 
555
    packet_size,
 
556
    scene,
 
557
    status;
 
558
 
 
559
  /*
 
560
    Allocate memory for pixels.
 
561
  */
 
562
  assert(image_info != (const ImageInfo *) NULL);
 
563
  assert(image_info->signature == MagickSignature);
 
564
  assert(image != (Image *) NULL);
 
565
  assert(image->signature == MagickSignature);
 
566
  packet_size=image->depth > 8 ? 8 : 4;
 
567
  if (LocaleCompare(image_info->magick,"CMYKA") == 0)
 
568
    packet_size=image->depth > 8 ? 10 : 8;
 
569
  pixels=MagickAllocateMemory(unsigned char *,packet_size*image->columns);
 
570
  if (pixels == (unsigned char *) NULL)
 
571
    ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image);
 
572
  if (image_info->interlace != PartitionInterlace)
 
573
    {
 
574
      /*
 
575
        Open output image file.
 
576
      */
 
577
      status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
 
578
      if (status == False)
 
579
        ThrowWriterException(FileOpenError,UnableToOpenFile,image);
 
580
    }
 
581
  scene=0;
 
582
  do
 
583
  {
 
584
    /*
 
585
      Convert MIFF to CMYK raster pixels.
 
586
    */
 
587
    TransformColorspace(image,CMYKColorspace);
 
588
    if (LocaleCompare(image_info->magick,"CMYKA") == 0)
 
589
      if (!image->matte)
 
590
        SetImageOpacity(image,OpaqueOpacity);
 
591
    switch (image_info->interlace)
 
592
    {
 
593
      case NoInterlace:
 
594
      default:
 
595
      {
 
596
        /*
 
597
          No interlacing:  CMYKCMYKCMYKCMYKCMYKCMYK...
 
598
        */
 
599
        for (y=0; y < (long) image->rows; y++)
 
600
        {
 
601
          p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
 
602
          if (p == (const PixelPacket *) NULL)
 
603
            break;
 
604
          if (LocaleCompare(image_info->magick,"CMYKA") != 0)
 
605
            {
 
606
              (void) PopImagePixels(image,CMYKQuantum,pixels);
 
607
              (void) WriteBlob(image,packet_size*image->columns,pixels);
 
608
            }
 
609
          else
 
610
            {
 
611
              (void) PopImagePixels(image,CMYKAQuantum,pixels);
 
612
              (void) WriteBlob(image,packet_size*image->columns,pixels);
 
613
            }
 
614
          if (image->previous == (Image *) NULL)
 
615
            if (QuantumTick(y,image->rows))
 
616
              if (!MagickMonitor(SaveImageText,y,image->rows,&image->exception))
 
617
                break;
 
618
        }
 
619
        break;
 
620
      }
 
621
      case LineInterlace:
 
622
      {
 
623
        /*
 
624
          Line interlacing:  CCC...MMM...YYY...KKK...CCC...MMM...YYY...KKK...
 
625
        */
 
626
        for (y=0; y < (long) image->rows; y++)
 
627
        {
 
628
          p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
 
629
          if (p == (const PixelPacket *) NULL)
 
630
            break;
 
631
          (void) PopImagePixels(image,CyanQuantum,pixels);
 
632
          (void) WriteBlob(image,image->columns,pixels);
 
633
          (void) PopImagePixels(image,MagentaQuantum,pixels);
 
634
          (void) WriteBlob(image,image->columns,pixels);
 
635
          (void) PopImagePixels(image,YellowQuantum,pixels);
 
636
          (void) WriteBlob(image,image->columns,pixels);
 
637
          (void) PopImagePixels(image,BlackQuantum,pixels);
 
638
          (void) WriteBlob(image,image->columns,pixels);
 
639
          if (LocaleCompare(image_info->magick,"CMYKA") == 0)
 
640
            {
 
641
              (void) PopImagePixels(image,AlphaQuantum,pixels);
 
642
              (void) WriteBlob(image,image->columns,pixels);
 
643
            }
 
644
          if (QuantumTick(y,image->rows))
 
645
            if (!MagickMonitor(SaveImageText,y,image->rows,&image->exception))
 
646
              break;
 
647
        }
 
648
        break;
 
649
      }
 
650
      case PlaneInterlace:
 
651
      case PartitionInterlace:
 
652
      {
 
653
        /*
 
654
          Plane interlacing:  CCCCCC...MMMMMM...YYYYYY...KKKKKK...
 
655
        */
 
656
        if (image_info->interlace == PartitionInterlace)
 
657
          {
 
658
            AppendImageFormat("C",image->filename);
 
659
            status=
 
660
              OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
 
661
            if (status == False)
 
662
              ThrowWriterException(FileOpenError,UnableToOpenFile,image);
 
663
          }
 
664
        for (y=0; y < (long) image->rows; y++)
 
665
        {
 
666
          p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
 
667
          if (p == (const PixelPacket *) NULL)
 
668
            break;
 
669
          (void) PopImagePixels(image,CyanQuantum,pixels);
 
670
          (void) WriteBlob(image,image->columns,pixels);
 
671
        }
 
672
        if (image_info->interlace == PartitionInterlace)
 
673
          {
 
674
            CloseBlob(image);
 
675
            AppendImageFormat("M",image->filename);
 
676
            status=OpenBlob(image_info,image,WriteBinaryBlobMode,
 
677
              &image->exception);
 
678
            if (status == False)
 
679
              ThrowWriterException(FileOpenError,UnableToOpenFile,image);
 
680
          }
 
681
        if (!MagickMonitor(SaveImageText,100,400,&image->exception))
 
682
          break;
 
683
        for (y=0; y < (long) image->rows; y++)
 
684
        {
 
685
          p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
 
686
          if (p == (const PixelPacket *) NULL)
 
687
            break;
 
688
          (void) PopImagePixels(image,MagentaQuantum,pixels);
 
689
          (void) WriteBlob(image,image->columns,pixels);
 
690
        }
 
691
        if (image_info->interlace == PartitionInterlace)
 
692
          {
 
693
            CloseBlob(image);
 
694
            AppendImageFormat("Y",image->filename);
 
695
            status=OpenBlob(image_info,image,WriteBinaryBlobMode,
 
696
              &image->exception);
 
697
            if (status == False)
 
698
              ThrowWriterException(FileOpenError,UnableToOpenFile,image);
 
699
          }
 
700
        if (!MagickMonitor(SaveImageText,200,400,&image->exception))
 
701
          break;
 
702
        for (y=0; y < (long) image->rows; y++)
 
703
        {
 
704
          p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
 
705
          if (p == (const PixelPacket *) NULL)
 
706
            break;
 
707
          (void) PopImagePixels(image,YellowQuantum,pixels);
 
708
          (void) WriteBlob(image,image->columns,pixels);
 
709
        }
 
710
        if (image_info->interlace == PartitionInterlace)
 
711
          {
 
712
            CloseBlob(image);
 
713
            AppendImageFormat("K",image->filename);
 
714
            status=OpenBlob(image_info,image,WriteBinaryBlobMode,
 
715
              &image->exception);
 
716
            if (status == False)
 
717
              ThrowWriterException(FileOpenError,UnableToOpenFile,image);
 
718
          }
 
719
        if (!MagickMonitor(SaveImageText,200,400,&image->exception))
 
720
          break;
 
721
        for (y=0; y < (long) image->rows; y++)
 
722
        {
 
723
          p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
 
724
          if (p == (const PixelPacket *) NULL)
 
725
            break;
 
726
          (void) PopImagePixels(image,BlackQuantum,pixels);
 
727
          (void) WriteBlob(image,image->columns,pixels);
 
728
        }
 
729
        if (LocaleCompare(image_info->magick,"CMYKA") == 0)
 
730
          {
 
731
            if (!MagickMonitor(SaveImageText,300,400,&image->exception))
 
732
              break;
 
733
            if (image_info->interlace == PartitionInterlace)
 
734
              {
 
735
                CloseBlob(image);
 
736
                AppendImageFormat("A",image->filename);
 
737
                status=OpenBlob(image_info,image,WriteBinaryBlobMode,
 
738
                  &image->exception);
 
739
                if (status == False)
 
740
                  ThrowWriterException(FileOpenError,UnableToOpenFile,image);
 
741
              }
 
742
            for (y=0; y < (long) image->rows; y++)
 
743
            {
 
744
              p=AcquireImagePixels(image,0,y,image->columns,1,
 
745
                &image->exception);
 
746
              if (p == (const PixelPacket *) NULL)
 
747
                break;
 
748
              (void) PopImagePixels(image,AlphaQuantum,pixels);
 
749
              (void) WriteBlob(image,image->columns,pixels);
 
750
            }
 
751
          }
 
752
        if (image_info->interlace == PartitionInterlace)
 
753
          (void) strncpy(image->filename,image_info->filename,MaxTextExtent-1);
 
754
        if (!MagickMonitor(SaveImageText,400,400,&image->exception))
 
755
          break;
 
756
        break;
 
757
      }
 
758
    }
 
759
    if (image->next == (Image *) NULL)
 
760
      break;
 
761
    image=SyncNextImageInList(image);
 
762
    status=MagickMonitor(SaveImagesText,scene++,GetImageListLength(image),
 
763
      &image->exception);
 
764
    if (status == False)
 
765
      break;
 
766
  } while (image_info->adjoin);
 
767
  MagickFreeMemory(pixels);
 
768
  if (image_info->adjoin)
 
769
    while (image->previous != (Image *) NULL)
 
770
      image=image->previous;
 
771
  CloseBlob(image);
 
772
  return(True);
 
773
}