source: ImageMagick/trunk/coders/pcl.c @ 7547

Revision 7547, 31.4 KB checked in by cristy, 13 months ago (diff)
Line 
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%                            PPPP    CCCC  L                                  %
7%                            P   P  C      L                                  %
8%                            PPPP   C      L                                  %
9%                            P      C      L                                  %
10%                            P       CCCC  LLLLL                              %
11%                                                                             %
12%                                                                             %
13%                      Read/Write HP PCL Printer Format                       %
14%                                                                             %
15%                              Software Design                                %
16%                                John Cristy                                  %
17%                                 July 1992                                   %
18%                                                                             %
19%                                                                             %
20%  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
21%  dedicated to making software imaging solutions freely available.           %
22%                                                                             %
23%  You may not use this file except in compliance with the License.  You may  %
24%  obtain a copy of the License at                                            %
25%                                                                             %
26%    http://www.imagemagick.org/script/license.php                            %
27%                                                                             %
28%  Unless required by applicable law or agreed to in writing, software        %
29%  distributed under the License is distributed on an "AS IS" BASIS,          %
30%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31%  See the License for the specific language governing permissions and        %
32%  limitations under the License.                                             %
33%                                                                             %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40  Include declarations.
41*/
42#include "MagickCore/studio.h"
43#include "MagickCore/attribute.h"
44#include "MagickCore/blob.h"
45#include "MagickCore/blob-private.h"
46#include "MagickCore/cache.h"
47#include "MagickCore/color.h"
48#include "MagickCore/color-private.h"
49#include "MagickCore/colorspace.h"
50#include "MagickCore/colorspace-private.h"
51#include "MagickCore/constitute.h"
52#include "MagickCore/delegate.h"
53#include "MagickCore/draw.h"
54#include "MagickCore/exception.h"
55#include "MagickCore/exception-private.h"
56#include "MagickCore/geometry.h"
57#include "MagickCore/image.h"
58#include "MagickCore/image-private.h"
59#include "MagickCore/list.h"
60#include "MagickCore/magick.h"
61#include "MagickCore/memory_.h"
62#include "MagickCore/monitor.h"
63#include "MagickCore/monitor-private.h"
64#include "MagickCore/option.h"
65#include "MagickCore/pixel-accessor.h"
66#include "MagickCore/profile.h"
67#include "MagickCore/property.h"
68#include "MagickCore/resource_.h"
69#include "MagickCore/quantum-private.h"
70#include "MagickCore/static.h"
71#include "MagickCore/string_.h"
72#include "MagickCore/module.h"
73#include "MagickCore/token.h"
74#include "MagickCore/transform.h"
75#include "MagickCore/utility.h"
76
77/*
78  Forward declarations.
79*/
80static MagickBooleanType
81  WritePCLImage(const ImageInfo *,Image *,ExceptionInfo *);
82
83/*
84%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
85%                                                                             %
86%                                                                             %
87%                                                                             %
88%   I s P C L                                                                 %
89%                                                                             %
90%                                                                             %
91%                                                                             %
92%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
93%
94%  IsPCL() returns MagickTrue if the image format type, identified by the
95%  magick string, is PCL.
96%
97%  The format of the IsPCL method is:
98%
99%      MagickBooleanType IsPCL(const unsigned char *magick,const size_t length)
100%
101%  A description of each parameter follows:
102%
103%    o magick: compare image format pattern against these bytes.
104%
105%    o length: Specifies the length of the magick string.
106%
107*/
108static MagickBooleanType IsPCL(const unsigned char *magick,const size_t length)
109{
110  if (length < 4)
111    return(MagickFalse);
112  if (memcmp(magick,"\033E\033&",4) == 0)
113    return(MagickFalse);
114  if (memcmp(magick,"\033E\033",3) == 0)
115    return(MagickTrue);
116  return(MagickFalse);
117}
118
119/*
120%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
121%                                                                             %
122%                                                                             %
123%                                                                             %
124%   R e a d P C L I m a g e                                                   %
125%                                                                             %
126%                                                                             %
127%                                                                             %
128%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
129%
130%  ReadPCLImage() reads a Printer Control Language image file and returns it.
131%  It allocates the memory necessary for the new Image structure and returns a
132%  pointer to the new image.
133%
134%  The format of the ReadPCLImage method is:
135%
136%      Image *ReadPCLImage(const ImageInfo *image_info,ExceptionInfo *exception)
137%
138%  A description of each parameter follows:
139%
140%    o image_info: the image info.
141%
142%    o exception: return any errors or warnings in this structure.
143%
144*/
145static Image *ReadPCLImage(const ImageInfo *image_info,ExceptionInfo *exception)
146{
147#define CropBox  "CropBox"
148#define DeviceCMYK  "DeviceCMYK"
149#define MediaBox  "MediaBox"
150#define RenderPCLText  "  Rendering PCL...  "
151
152  char
153    command[MaxTextExtent],
154    density[MaxTextExtent],
155    filename[MaxTextExtent],
156    geometry[MaxTextExtent],
157    options[MaxTextExtent],
158    input_filename[MaxTextExtent];
159
160  const char
161    *option;
162
163  const DelegateInfo
164    *delegate_info;
165
166  Image
167    *image,
168    *next_image;
169
170  ImageInfo
171    *read_info;
172
173  MagickBooleanType
174    cmyk,
175    status;
176
177  PointInfo
178    delta;
179
180  RectangleInfo
181    bounding_box,
182    page;
183
184  register char
185    *p;
186
187  register ssize_t
188    c;
189
190  SegmentInfo
191    bounds;
192
193  size_t
194    height,
195    width;
196
197  ssize_t
198    count;
199
200  assert(image_info != (const ImageInfo *) NULL);
201  assert(image_info->signature == MagickSignature);
202  if (image_info->debug != MagickFalse)
203    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
204      image_info->filename);
205  assert(exception != (ExceptionInfo *) NULL);
206  assert(exception->signature == MagickSignature);
207  /*
208    Open image file.
209  */
210  image=AcquireImage(image_info,exception);
211  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
212  if (status == MagickFalse)
213    {
214      image=DestroyImageList(image);
215      return((Image *) NULL);
216    }
217  status=AcquireUniqueSymbolicLink(image_info->filename,input_filename);
218  if (status == MagickFalse)
219    {
220      ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
221        image_info->filename);
222      image=DestroyImageList(image);
223      return((Image *) NULL);
224    }
225  /*
226    Set the page density.
227  */
228  delta.x=DefaultResolution;
229  delta.y=DefaultResolution;
230  if ((image->resolution.x == 0.0) || (image->resolution.y == 0.0))
231    {
232      GeometryInfo
233        geometry_info;
234
235      MagickStatusType
236        flags;
237
238      flags=ParseGeometry(PSDensityGeometry,&geometry_info);
239      image->resolution.x=geometry_info.rho;
240      image->resolution.y=geometry_info.sigma;
241      if ((flags & SigmaValue) == 0)
242        image->resolution.y=image->resolution.x;
243    }
244  /*
245    Determine page geometry from the PCL media box.
246  */
247  cmyk=image->colorspace == CMYKColorspace ? MagickTrue : MagickFalse;
248  count=0;
249  (void) ResetMagickMemory(&bounding_box,0,sizeof(bounding_box));
250  (void) ResetMagickMemory(&bounds,0,sizeof(bounds));
251  (void) ResetMagickMemory(&page,0,sizeof(page));
252  (void) ResetMagickMemory(command,0,sizeof(command));
253  p=command;
254  for (c=ReadBlobByte(image); c != EOF; c=ReadBlobByte(image))
255  {
256    if (image_info->page != (char *) NULL)
257      continue;
258    /*
259      Note PCL elements.
260    */
261    *p++=(char) c;
262    if ((c != (int) '/') && (c != '\n') &&
263        ((size_t) (p-command) < (MaxTextExtent-1)))
264      continue;
265    *p='\0';
266    p=command;
267    /*
268      Is this a CMYK document?
269    */
270    if (LocaleNCompare(DeviceCMYK,command,strlen(DeviceCMYK)) == 0)
271      cmyk=MagickTrue;
272    if (LocaleNCompare(CropBox,command,strlen(CropBox)) == 0)
273      {
274        /*
275          Note region defined by crop box.
276        */
277        count=(ssize_t) sscanf(command,"CropBox [%lf %lf %lf %lf",
278          &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
279        if (count != 4)
280          count=(ssize_t) sscanf(command,"CropBox[%lf %lf %lf %lf",
281            &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
282      }
283    if (LocaleNCompare(MediaBox,command,strlen(MediaBox)) == 0)
284      {
285        /*
286          Note region defined by media box.
287        */
288        count=(ssize_t) sscanf(command,"MediaBox [%lf %lf %lf %lf",
289          &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
290        if (count != 4)
291          count=(ssize_t) sscanf(command,"MediaBox[%lf %lf %lf %lf",
292            &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
293      }
294    if (count != 4)
295      continue;
296    /*
297      Set PCL render geometry.
298    */
299    width=(size_t) floor(bounds.x2-bounds.x1+0.5);
300    height=(size_t) floor(bounds.y2-bounds.y1+0.5);
301    if (width > page.width)
302      page.width=width;
303    if (height > page.height)
304      page.height=height;
305  }
306  (void) CloseBlob(image);
307  /*
308    Render PCL with the GhostPCL delegate.
309  */
310  if ((page.width == 0) || (page.height == 0))
311    (void) ParseAbsoluteGeometry(PSPageGeometry,&page);
312  if (image_info->page != (char *) NULL)
313    (void) ParseAbsoluteGeometry(image_info->page,&page);
314  (void) FormatLocaleString(geometry,MaxTextExtent,"%.20gx%.20g",(double)
315    page.width,(double) page.height);
316  if (image_info->monochrome != MagickFalse)
317    delegate_info=GetDelegateInfo("pcl:mono",(char *) NULL,exception);
318  else
319     if (cmyk != MagickFalse)
320       delegate_info=GetDelegateInfo("pcl:cmyk",(char *) NULL,exception);
321     else
322       delegate_info=GetDelegateInfo("pcl:color",(char *) NULL,exception);
323  if (delegate_info == (const DelegateInfo *) NULL)
324    return((Image *) NULL);
325  *options='\0';
326  if ((page.width == 0) || (page.height == 0))
327    (void) ParseAbsoluteGeometry(PSPageGeometry,&page);
328  if (image_info->page != (char *) NULL)
329    (void) ParseAbsoluteGeometry(image_info->page,&page);
330  (void) FormatLocaleString(density,MaxTextExtent,"%gx%g",
331    image->resolution.x,image->resolution.y);
332  page.width=(size_t) floor(page.width*image->resolution.x/delta.x+0.5);
333  page.height=(size_t) floor(page.height*image->resolution.y/delta.y+
334    0.5);
335  (void) FormatLocaleString(options,MaxTextExtent,"-g%.20gx%.20g ",(double)
336     page.width,(double) page.height);
337  image=DestroyImage(image);
338  read_info=CloneImageInfo(image_info);
339  *read_info->magick='\0';
340  if (read_info->number_scenes != 0)
341    {
342      if (read_info->number_scenes != 1)
343        (void) FormatLocaleString(options,MaxTextExtent,"-dLastPage=%.20g",
344          (double) (read_info->scene+read_info->number_scenes));
345      else
346        (void) FormatLocaleString(options,MaxTextExtent,
347          "-dFirstPage=%.20g -dLastPage=%.20g",(double) read_info->scene+1,
348          (double) (read_info->scene+read_info->number_scenes));
349      read_info->number_scenes=0;
350      if (read_info->scenes != (char *) NULL)
351        *read_info->scenes='\0';
352    }
353  option=GetImageOption(read_info,"authenticate");
354  if (option != (const char *) NULL)
355    (void) FormatLocaleString(options+strlen(options),MaxTextExtent,
356      " -sPCLPassword=%s",option);
357  (void) CopyMagickString(filename,read_info->filename,MaxTextExtent);
358  (void) AcquireUniqueFilename(read_info->filename);
359  (void) FormatLocaleString(command,MaxTextExtent,
360    GetDelegateCommands(delegate_info),
361    read_info->antialias != MagickFalse ? 4 : 1,
362    read_info->antialias != MagickFalse ? 4 : 1,density,options,
363    read_info->filename,input_filename);
364  status=SystemCommand(MagickFalse,read_info->verbose,command,exception) != 0 ?
365    MagickTrue : MagickFalse;
366  image=ReadImage(read_info,exception);
367  (void) RelinquishUniqueFileResource(read_info->filename);
368  (void) RelinquishUniqueFileResource(input_filename);
369  read_info=DestroyImageInfo(read_info);
370  if (image == (Image *) NULL)
371    ThrowReaderException(DelegateError,"PCLDelegateFailed");
372  if (LocaleCompare(image->magick,"BMP") == 0)
373    {
374      Image
375        *cmyk_image;
376
377      cmyk_image=ConsolidateCMYKImages(image,exception);
378      if (cmyk_image != (Image *) NULL)
379        {
380          image=DestroyImageList(image);
381          image=cmyk_image;
382        }
383    }
384  do
385  {
386    (void) CopyMagickString(image->filename,filename,MaxTextExtent);
387    image->page=page;
388    next_image=SyncNextImageInList(image);
389    if (next_image != (Image *) NULL)
390      image=next_image;
391  } while (next_image != (Image *) NULL);
392  return(GetFirstImageInList(image));
393}
394
395/*
396%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
397%                                                                             %
398%                                                                             %
399%                                                                             %
400%   R e g i s t e r P C L I m a g e                                           %
401%                                                                             %
402%                                                                             %
403%                                                                             %
404%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
405%
406%  RegisterPCLImage() adds attributes for the PCL image format to
407%  the list of supported formats.  The attributes include the image format
408%  tag, a method to read and/or write the format, whether the format
409%  supports the saving of more than one frame to the i file or blob,
410%  whether the format supports native in-memory I/O, and a brief
411%  description of the format.
412%
413%  The format of the RegisterPCLImage method is:
414%
415%      size_t RegisterPCLImage(void)
416%
417*/
418ModuleExport size_t RegisterPCLImage(void)
419{
420  MagickInfo
421    *entry;
422
423  entry=SetMagickInfo("PCL");
424  entry->decoder=(DecodeImageHandler *) ReadPCLImage;
425  entry->encoder=(EncodeImageHandler *) WritePCLImage;
426  entry->magick=(IsImageFormatHandler *) IsPCL;
427  entry->blob_support=MagickFalse;
428  entry->seekable_stream=MagickTrue;
429  entry->thread_support=EncoderThreadSupport;
430  entry->description=ConstantString("Printer Control Language");
431  entry->module=ConstantString("PCL");
432  (void) RegisterMagickInfo(entry);
433  return(MagickImageCoderSignature);
434}
435
436/*
437%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
438%                                                                             %
439%                                                                             %
440%                                                                             %
441%   U n r e g i s t e r P C L I m a g e                                       %
442%                                                                             %
443%                                                                             %
444%                                                                             %
445%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
446%
447%  UnregisterPCLImage() removes format registrations made by the PCL module
448%  from the list of supported formats.
449%
450%  The format of the UnregisterPCLImage method is:
451%
452%      UnregisterPCLImage(void)
453%
454*/
455ModuleExport void UnregisterPCLImage(void)
456{
457  (void) UnregisterMagickInfo("PCL");
458}
459
460/*
461%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
462%                                                                             %
463%                                                                             %
464%                                                                             %
465%   W r i t e P C L I m a g e                                                 %
466%                                                                             %
467%                                                                             %
468%                                                                             %
469%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
470%
471%  WritePCLImage() writes an image in the Page Control Language encoded
472%  image format.
473%
474%  The format of the WritePCLImage method is:
475%
476%      MagickBooleanType WritePCLImage(const ImageInfo *image_info,
477%        Image *image,ExceptionInfo *exception)
478%
479%  A description of each parameter follows.
480%
481%    o image_info: the image info.
482%
483%    o image:  The image.
484%
485%    o exception: return any errors or warnings in this structure.
486%
487*/
488
489static size_t PCLDeltaCompressImage(const size_t length,
490  const unsigned char *previous_pixels,const unsigned char *pixels,
491  unsigned char *compress_pixels)
492{
493  int
494    delta,
495    j,
496    replacement;
497
498  register ssize_t
499    i,
500    x;
501
502  register unsigned char
503    *q;
504
505  q=compress_pixels;
506  for (x=0; x < (ssize_t) length; )
507  {
508    j=0;
509    for (i=0; x < (ssize_t) length; x++)
510    {
511      if (*pixels++ != *previous_pixels++)
512        {
513          i=1;
514          break;
515        }
516      j++;
517    }
518    while (x < (ssize_t) length)
519    {
520      x++;
521      if (*pixels == *previous_pixels)
522        break;
523      i++;
524      previous_pixels++;
525      pixels++;
526    }
527    if (i == 0)
528      break;
529    replacement=j >= 31 ? 31 : j;
530    j-=replacement;
531    delta=i >= 8 ? 8 : i;
532    *q++=(unsigned char) (((delta-1) << 5) | replacement);
533    if (replacement == 31)
534      {
535        for (replacement=255; j != 0; )
536        {
537          if (replacement > j)
538            replacement=j;
539          *q++=(unsigned char) replacement;
540          j-=replacement;
541        }
542        if (replacement == 255)
543          *q++='\0';
544      }
545    for (pixels-=i; i != 0; )
546    {
547      for (i-=delta; delta != 0; delta--)
548        *q++=(*pixels++);
549      if (i == 0)
550        break;
551      delta=i;
552      if (i >= 8)
553        delta=8;
554      *q++=(unsigned char) ((delta-1) << 5);
555    }
556  }
557  return((size_t) (q-compress_pixels));
558}
559
560static size_t PCLPackbitsCompressImage(const size_t length,
561  const unsigned char *pixels,unsigned char *compress_pixels)
562{
563  int
564    count;
565
566  register ssize_t
567    x;
568
569  register unsigned char
570    *q;
571
572  ssize_t
573    j;
574
575  unsigned char
576    packbits[128];
577
578  /*
579    Compress pixels with Packbits encoding.
580  */
581  q=compress_pixels;
582  for (x=(ssize_t) length; x != 0; )
583  {
584    switch (x)
585    {
586      case 1:
587      {
588        x--;
589        *q++=0;
590        *q++=(*pixels);
591        break;
592      }
593      case 2:
594      {
595        x-=2;
596        *q++=1;
597        *q++=(*pixels);
598        *q++=pixels[1];
599        break;
600      }
601      case 3:
602      {
603        x-=3;
604        if ((*pixels == *(pixels+1)) && (*(pixels+1) == *(pixels+2)))
605          {
606            *q++=(unsigned char) ((256-3)+1);
607            *q++=(*pixels);
608            break;
609          }
610        *q++=2;
611        *q++=(*pixels);
612        *q++=pixels[1];
613        *q++=pixels[2];
614        break;
615      }
616      default:
617      {
618        if ((*pixels == *(pixels+1)) && (*(pixels+1) == *(pixels+2)))
619          {
620            /*
621              Packed run.
622            */
623            count=3;
624            while (((ssize_t) count < x) && (*pixels == *(pixels+count)))
625            {
626              count++;
627              if (count >= 127)
628                break;
629            }
630            x-=count;
631            *q++=(unsigned char) ((256-count)+1);
632            *q++=(*pixels);
633            pixels+=count;
634            break;
635          }
636        /*
637          Literal run.
638        */
639        count=0;
640        while ((*(pixels+count) != *(pixels+count+1)) ||
641               (*(pixels+count+1) != *(pixels+count+2)))
642        {
643          packbits[count+1]=pixels[count];
644          count++;
645          if (((ssize_t) count >= (x-3)) || (count >= 127))
646            break;
647        }
648        x-=count;
649        *packbits=(unsigned char) (count-1);
650        for (j=0; j <= (ssize_t) count; j++)
651          *q++=packbits[j];
652        pixels+=count;
653        break;
654      }
655    }
656  }
657  *q++=128; /* EOD marker */
658  return((size_t) (q-compress_pixels));
659}
660
661static MagickBooleanType WritePCLImage(const ImageInfo *image_info,Image *image,
662  ExceptionInfo *exception)
663{
664  char
665    buffer[MaxTextExtent];
666
667  const char
668    *option;
669
670  MagickBooleanType
671    status;
672
673  MagickOffsetType
674    scene;
675
676  register const Quantum *p;
677
678  register ssize_t i, x;
679
680  register unsigned char *q;
681
682  size_t
683    density,
684    length,
685    one,
686    packets;
687
688  ssize_t
689    y;
690
691  unsigned char
692    bits_per_pixel,
693    *compress_pixels,
694    *pixels,
695    *previous_pixels;
696
697  /*
698    Open output image file.
699  */
700  assert(image_info != (const ImageInfo *) NULL);
701  assert(image_info->signature == MagickSignature);
702  assert(image != (Image *) NULL);
703  assert(image->signature == MagickSignature);
704  if (image->debug != MagickFalse)
705    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
706  assert(exception != (ExceptionInfo *) NULL);
707  assert(exception->signature == MagickSignature);
708  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
709  if (status == MagickFalse)
710    return(status);
711  density=75;
712  if (image_info->density != (char *) NULL)
713    {
714      GeometryInfo
715        geometry;
716
717      (void) ParseGeometry(image_info->density,&geometry);
718      density=(size_t) geometry.rho;
719    }
720  scene=0;
721  one=1;
722  do
723  {
724    if (IssRGBColorspace(image->colorspace) == MagickFalse)
725      (void) TransformImageColorspace(image,sRGBColorspace,exception);
726    /*
727      Initialize the printer.
728    */
729    (void) WriteBlobString(image,"\033E");  /* printer reset */
730    (void) WriteBlobString(image,"\033*r3F");  /* set presentation mode */
731    (void) FormatLocaleString(buffer,MaxTextExtent,"\033*r%.20gs%.20gT",
732      (double) image->columns,(double) image->rows);
733    (void) WriteBlobString(image,buffer);
734    (void) FormatLocaleString(buffer,MaxTextExtent,"\033*t%.20gR",(double)
735      density);
736    (void) WriteBlobString(image,buffer);
737    (void) WriteBlobString(image,"\033&l0E");  /* top margin 0 */
738    if (IsImageMonochrome(image,exception) != MagickFalse)
739      {
740        /*
741          Monochrome image: use default printer monochrome setup.
742        */
743        bits_per_pixel=1;
744      }
745    else
746      if (image->storage_class == DirectClass)
747        {
748          /*
749            DirectClass image.
750          */
751          bits_per_pixel=24;
752          (void) WriteBlobString(image,"\033*v6W"); /* set color mode */
753          (void) WriteBlobByte(image,0); /* RGB */
754          (void) WriteBlobByte(image,3); /* direct by pixel */
755          (void) WriteBlobByte(image,0); /* bits per index (ignored) */
756          (void) WriteBlobByte(image,8); /* bits per red component */
757          (void) WriteBlobByte(image,8); /* bits per green component */
758          (void) WriteBlobByte(image,8); /* bits per blue component */
759        }
760      else
761        {
762          /*
763            Colormapped image.
764          */
765          bits_per_pixel=8;
766          (void) WriteBlobString(image,"\033*v6W"); /* set color mode... */
767          (void) WriteBlobByte(image,0); /* RGB */
768          (void) WriteBlobByte(image,1); /* indexed by pixel */
769          (void) WriteBlobByte(image,bits_per_pixel); /* bits per index */
770          (void) WriteBlobByte(image,8); /* bits per red component */
771          (void) WriteBlobByte(image,8); /* bits per green component */
772          (void) WriteBlobByte(image,8); /* bits per blue component */
773          for (i=0; i < (ssize_t) image->colors; i++)
774          {
775            (void) FormatLocaleString(buffer,MaxTextExtent,
776              "\033*v%da%db%dc%.20gI",
777              ScaleQuantumToChar(image->colormap[i].red),
778              ScaleQuantumToChar(image->colormap[i].green),
779              ScaleQuantumToChar(image->colormap[i].blue),(double) i);
780            (void) WriteBlobString(image,buffer);
781          }
782          for (one=1; i < (ssize_t) (one << bits_per_pixel); i++)
783          {
784            (void) FormatLocaleString(buffer,MaxTextExtent,"\033*v%.20gI",
785              (double) i);
786            (void) WriteBlobString(image,buffer);
787          }
788        }
789    option=GetImageOption(image_info,"pcl:fit-to-page");
790    if (IfMagickTrue(IsStringTrue(option)))
791      (void) WriteBlobString(image,"\033*r3A");
792    else
793      (void) WriteBlobString(image,"\033*r1A");  /* start raster graphics */
794    (void) WriteBlobString(image,"\033*b0Y");  /* set y offset */
795    length=(image->columns*bits_per_pixel+7)/8;
796    pixels=(unsigned char *) AcquireQuantumMemory(length+1,sizeof(*pixels));
797    if (pixels == (unsigned char *) NULL)
798      ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
799    (void) ResetMagickMemory(pixels,0,(length+1)*sizeof(*pixels));
800    compress_pixels=(unsigned char *) NULL;
801    previous_pixels=(unsigned char *) NULL;
802    switch (image->compression)
803    {
804      case NoCompression:
805      {
806        (void) FormatLocaleString(buffer,MaxTextExtent,"\033*b0M");
807        (void) WriteBlobString(image,buffer);
808        break;
809      }
810      case RLECompression:
811      {
812        compress_pixels=(unsigned char *) AcquireQuantumMemory(length+256,
813          sizeof(*compress_pixels));
814        if (compress_pixels == (unsigned char *) NULL)
815          {
816            pixels=(unsigned char *) RelinquishMagickMemory(pixels);
817            ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
818          }
819        (void) ResetMagickMemory(compress_pixels,0,(length+256)*
820          sizeof(*compress_pixels));
821        (void) FormatLocaleString(buffer,MaxTextExtent,"\033*b2M");
822        (void) WriteBlobString(image,buffer);
823        break;
824      }
825      default:
826      {
827        compress_pixels=(unsigned char *) AcquireQuantumMemory(3*length+256,
828          sizeof(*compress_pixels));
829        if (compress_pixels == (unsigned char *) NULL)
830          {
831            pixels=(unsigned char *) RelinquishMagickMemory(pixels);
832            ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
833          }
834        (void) ResetMagickMemory(compress_pixels,0,(3*length+256)*
835          sizeof(*compress_pixels));
836        previous_pixels=(unsigned char *) AcquireQuantumMemory(length+1,
837          sizeof(*previous_pixels));
838        if (previous_pixels == (unsigned char *) NULL)
839          {
840            compress_pixels=(unsigned char *) RelinquishMagickMemory(
841              compress_pixels);
842            pixels=(unsigned char *) RelinquishMagickMemory(pixels);
843            ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
844          }
845        (void) ResetMagickMemory(previous_pixels,0,(length+1)*
846          sizeof(*previous_pixels));
847        (void) FormatLocaleString(buffer,MaxTextExtent,"\033*b3M");
848        (void) WriteBlobString(image,buffer);
849        break;
850      }
851    }
852    for (y=0; y < (ssize_t) image->rows; y++)
853    {
854      p=GetVirtualPixels(image,0,y,image->columns,1,exception);
855      if (p == (const Quantum *) NULL)
856        break;
857      q=pixels;
858      switch (bits_per_pixel)
859      {
860        case 1:
861        {
862          register unsigned char
863            bit,
864            byte;
865
866          /*
867            Monochrome image.
868          */
869          bit=0;
870          byte=0;
871          for (x=0; x < (ssize_t) image->columns; x++)
872          {
873            byte<<=1;
874            if (GetPixelIntensity(image,p) < ((MagickRealType) QuantumRange/2.0))
875              byte|=0x01;
876            bit++;
877            if (bit == 8)
878              {
879                *q++=byte;
880                bit=0;
881                byte=0;
882              }
883            p+=GetPixelChannels(image);
884          }
885          if (bit != 0)
886            *q++=byte << (8-bit);
887          break;
888        }
889        case 8:
890        {
891          /*
892            Colormapped image.
893          */
894          for (x=0; x < (ssize_t) image->columns; x++)
895          {
896            *q++=(unsigned char) GetPixelIndex(image,p);
897            p+=GetPixelChannels(image);
898          }
899          break;
900        }
901        case 24:
902        case 32:
903        {
904          /*
905            Truecolor image.
906          */
907          for (x=0; x < (ssize_t) image->columns; x++)
908          {
909            *q++=ScaleQuantumToChar(GetPixelRed(image,p));
910            *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
911            *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
912            p+=GetPixelChannels(image);
913          }
914          break;
915        }
916      }
917      switch (image->compression)
918      {
919        case NoCompression:
920        {
921          (void) FormatLocaleString(buffer,MaxTextExtent,"\033*b%.20gW",
922            (double) length);
923          (void) WriteBlobString(image,buffer);
924          (void) WriteBlob(image,length,pixels);
925          break;
926        }
927        case RLECompression:
928        {
929          packets=PCLPackbitsCompressImage(length,pixels,compress_pixels);
930          (void) FormatLocaleString(buffer,MaxTextExtent,"\033*b%.20gW",
931            (double) packets);
932          (void) WriteBlobString(image,buffer);
933          (void) WriteBlob(image,packets,compress_pixels);
934          break;
935        }
936        default:
937        {
938          if (y == 0)
939            for (i=0; i < (ssize_t) length; i++)
940              previous_pixels[i]=(~pixels[i]);
941          packets=PCLDeltaCompressImage(length,previous_pixels,pixels,
942            compress_pixels);
943          (void) FormatLocaleString(buffer,MaxTextExtent,"\033*b%.20gW",
944            (double) packets);
945          (void) WriteBlobString(image,buffer);
946          (void) WriteBlob(image,packets,compress_pixels);
947          (void) CopyMagickMemory(previous_pixels,pixels,length*
948            sizeof(*pixels));
949          break;
950        }
951      }
952    }
953    (void) WriteBlobString(image,"\033*rB");  /* end graphics */
954    switch (image->compression)
955    {
956      case NoCompression:
957        break;
958      case RLECompression:
959      {
960        compress_pixels=(unsigned char *) RelinquishMagickMemory(
961          compress_pixels);
962        break;
963      }
964      default:
965      {
966        previous_pixels=(unsigned char *) RelinquishMagickMemory(
967          previous_pixels);
968        compress_pixels=(unsigned char *) RelinquishMagickMemory(
969          compress_pixels);
970        break;
971      }
972    }
973    pixels=(unsigned char *) RelinquishMagickMemory(pixels);
974    if (GetNextImageInList(image) == (Image *) NULL)
975      break;
976    image=SyncNextImageInList(image);
977    status=SetImageProgress(image,SaveImagesTag,scene++,
978      GetImageListLength(image));
979    if (status == MagickFalse)
980      break;
981  } while (image_info->adjoin != MagickFalse);
982  (void) WriteBlobString(image,"\033E");
983  (void) CloseBlob(image);
984  return(MagickTrue);
985}
Note: See TracBrowser for help on using the repository browser.