/src/imagemagick/coders/ps3.c
Line | Count | Source |
1 | | /* |
2 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
3 | | % % |
4 | | % % |
5 | | % % |
6 | | % PPPP SSSSS 33333 % |
7 | | % P P SS 33 % |
8 | | % PPPP SSS 333 % |
9 | | % P SS 33 % |
10 | | % P SSSSS 33333 % |
11 | | % % |
12 | | % % |
13 | | % Write Postscript Level III Format % |
14 | | % % |
15 | | % Software Design % |
16 | | % Cristy % |
17 | | % Lars Ruben Skyum % |
18 | | % July 1992 % |
19 | | % % |
20 | | % % |
21 | | % Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization % |
22 | | % dedicated to making software imaging solutions freely available. % |
23 | | % % |
24 | | % You may not use this file except in compliance with the License. You may % |
25 | | % obtain a copy of the License at % |
26 | | % % |
27 | | % https://imagemagick.org/license/ % |
28 | | % % |
29 | | % Unless required by applicable law or agreed to in writing, software % |
30 | | % distributed under the License is distributed on an "AS IS" BASIS, % |
31 | | % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % |
32 | | % See the License for the specific language governing permissions and % |
33 | | % limitations under the License. % |
34 | | % % |
35 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
36 | | % |
37 | | % |
38 | | */ |
39 | | |
40 | | /* |
41 | | Include declarations. |
42 | | */ |
43 | | #include "MagickCore/studio.h" |
44 | | #include "MagickCore/artifact.h" |
45 | | #include "MagickCore/attribute.h" |
46 | | #include "MagickCore/blob.h" |
47 | | #include "MagickCore/blob-private.h" |
48 | | #include "MagickCore/cache.h" |
49 | | #include "MagickCore/channel.h" |
50 | | #include "MagickCore/color.h" |
51 | | #include "MagickCore/color-private.h" |
52 | | #include "MagickCore/colorspace-private.h" |
53 | | #include "MagickCore/compress.h" |
54 | | #include "MagickCore/constitute.h" |
55 | | #include "MagickCore/draw.h" |
56 | | #include "MagickCore/exception.h" |
57 | | #include "MagickCore/exception-private.h" |
58 | | #include "MagickCore/geometry.h" |
59 | | #include "MagickCore/image.h" |
60 | | #include "MagickCore/image-private.h" |
61 | | #include "MagickCore/list.h" |
62 | | #include "MagickCore/magick.h" |
63 | | #include "MagickCore/memory_.h" |
64 | | #include "MagickCore/module.h" |
65 | | #include "MagickCore/monitor.h" |
66 | | #include "MagickCore/monitor-private.h" |
67 | | #include "MagickCore/option.h" |
68 | | #include "MagickCore/pixel-accessor.h" |
69 | | #include "MagickCore/property.h" |
70 | | #include "MagickCore/quantum-private.h" |
71 | | #include "MagickCore/resource_.h" |
72 | | #include "MagickCore/static.h" |
73 | | #include "MagickCore/string_.h" |
74 | | #include "MagickCore/module.h" |
75 | | #include "MagickCore/timer-private.h" |
76 | | #include "MagickCore/token.h" |
77 | | #include "MagickCore/utility.h" |
78 | | #include "coders/coders-private.h" |
79 | | |
80 | | /* |
81 | | Define declarations. |
82 | | */ |
83 | 0 | #define PS3_NoCompression "0" |
84 | 0 | #define PS3_FaxCompression "1" |
85 | 0 | #define PS3_JPEGCompression "2" |
86 | 0 | #define PS3_LZWCompression "3" |
87 | 0 | #define PS3_RLECompression "4" |
88 | 0 | #define PS3_ZipCompression "5" |
89 | | |
90 | 0 | #define PS3_RGBColorspace "0" |
91 | 0 | #define PS3_CMYKColorspace "1" |
92 | | |
93 | 0 | #define PS3_DirectClass "0" |
94 | 0 | #define PS3_PseudoClass "1" |
95 | | |
96 | | #if defined(MAGICKCORE_TIFF_DELEGATE) |
97 | 0 | #define CCITTParam "-1" |
98 | | #else |
99 | | #define CCITTParam "0" |
100 | | #endif |
101 | | |
102 | | /* |
103 | | Forward declarations. |
104 | | */ |
105 | | static MagickBooleanType |
106 | | WritePS3Image(const ImageInfo *,Image *,ExceptionInfo *); |
107 | | |
108 | | /* |
109 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
110 | | % % |
111 | | % % |
112 | | % % |
113 | | % R e g i s t e r P S 3 I m a g e % |
114 | | % % |
115 | | % % |
116 | | % % |
117 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
118 | | % |
119 | | % RegisterPS3Image() adds properties for the PS3 image format to the list of |
120 | | % supported formats. The properties include the image format tag, a method to |
121 | | % read and/or write the format, whether the format supports the saving of more |
122 | | % than one frame to the same file or blob, whether the format supports native |
123 | | % in-memory I/O, and a brief description of the format. |
124 | | % |
125 | | % The format of the RegisterPS3Image method is: |
126 | | % |
127 | | % size_t RegisterPS3Image(void) |
128 | | % |
129 | | */ |
130 | | ModuleExport size_t RegisterPS3Image(void) |
131 | 7 | { |
132 | 7 | MagickInfo |
133 | 7 | *entry; |
134 | | |
135 | 7 | entry=AcquireMagickInfo("PS3","EPS3","Level III Encapsulated PostScript"); |
136 | 7 | entry->encoder=(EncodeImageHandler *) WritePS3Image; |
137 | 7 | entry->mime_type=ConstantString("application/postscript"); |
138 | 7 | entry->flags|=CoderEncoderSeekableStreamFlag; |
139 | 7 | entry->flags^=CoderBlobSupportFlag; |
140 | 7 | (void) RegisterMagickInfo(entry); |
141 | 7 | entry=AcquireMagickInfo("PS3","PS3","Level III PostScript"); |
142 | 7 | entry->encoder=(EncodeImageHandler *) WritePS3Image; |
143 | 7 | entry->mime_type=ConstantString("application/postscript"); |
144 | 7 | entry->flags|=CoderEncoderSeekableStreamFlag; |
145 | 7 | entry->flags^=CoderBlobSupportFlag; |
146 | 7 | (void) RegisterMagickInfo(entry); |
147 | 7 | return(MagickImageCoderSignature); |
148 | 7 | } |
149 | | |
150 | | /* |
151 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
152 | | % % |
153 | | % % |
154 | | % % |
155 | | % U n r e g i s t e r P S 3 I m a g e % |
156 | | % % |
157 | | % % |
158 | | % % |
159 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
160 | | % |
161 | | % UnregisterPS3Image() removes format registrations made by the PS3 module |
162 | | % from the list of supported formats. |
163 | | % |
164 | | % The format of the UnregisterPS3Image method is: |
165 | | % |
166 | | % UnregisterPS3Image(void) |
167 | | % |
168 | | */ |
169 | | ModuleExport void UnregisterPS3Image(void) |
170 | 0 | { |
171 | 0 | (void) UnregisterMagickInfo("EPS3"); |
172 | 0 | (void) UnregisterMagickInfo("PS3"); |
173 | 0 | } |
174 | | |
175 | | /* |
176 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
177 | | % % |
178 | | % % |
179 | | % % |
180 | | % W r i t e P S 3 I m a g e % |
181 | | % % |
182 | | % % |
183 | | % % |
184 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
185 | | % |
186 | | % WritePS3Image() translates an image to encapsulated Postscript Level III |
187 | | % for printing. If the supplied geometry is null, the image is centered on |
188 | | % the Postscript page. Otherwise, the image is positioned as specified by the |
189 | | % geometry. |
190 | | % |
191 | | % The format of the WritePS3Image method is: |
192 | | % |
193 | | % MagickBooleanType WritePS3Image(const ImageInfo *image_info, |
194 | | % Image *image,ExceptionInfo *exception) |
195 | | % |
196 | | % A description of each parameter follows: |
197 | | % |
198 | | % o image_info: Specifies a pointer to a ImageInfo structure. |
199 | | % |
200 | | % o image: the image. |
201 | | % |
202 | | % o exception: return any errors or warnings in this structure. |
203 | | % |
204 | | */ |
205 | | |
206 | | static inline void FilenameToTitle(const char *filename,char *title, |
207 | | const size_t extent) |
208 | 0 | { |
209 | 0 | int |
210 | 0 | depth = 0; |
211 | |
|
212 | 0 | ssize_t |
213 | 0 | i, |
214 | 0 | offset = 0; |
215 | |
|
216 | 0 | if (extent == 0) |
217 | 0 | return; |
218 | 0 | for (i=0; (filename[i] != '\0') && ((offset+1) < (ssize_t) extent); i++) |
219 | 0 | { |
220 | 0 | unsigned char |
221 | 0 | c = filename[i]; |
222 | | |
223 | | /* |
224 | | Only allow printable ASCII. |
225 | | */ |
226 | 0 | if ((c < 32) || (c > 126)) |
227 | 0 | { |
228 | 0 | title[offset++]='_'; |
229 | 0 | continue; |
230 | 0 | } |
231 | | /* |
232 | | Percent signs break DSC parsing. |
233 | | */ |
234 | 0 | if (c == '%') |
235 | 0 | { |
236 | 0 | title[offset++]='_'; |
237 | 0 | continue; |
238 | 0 | } |
239 | | /* |
240 | | Parentheses must remain balanced. |
241 | | */ |
242 | 0 | if (c == '(') |
243 | 0 | { |
244 | 0 | depth++; |
245 | 0 | title[offset++] = '('; |
246 | 0 | continue; |
247 | 0 | } |
248 | 0 | if (c == ')') |
249 | 0 | { |
250 | 0 | if (depth <= 0) |
251 | 0 | title[offset++]='_'; |
252 | 0 | else |
253 | 0 | { |
254 | 0 | depth--; |
255 | 0 | title[offset++]=')'; |
256 | 0 | } |
257 | 0 | continue; |
258 | 0 | } |
259 | | /* |
260 | | Everything else is allowed. |
261 | | */ |
262 | 0 | title[offset++]=c; |
263 | 0 | } |
264 | | /* |
265 | | If parentheses remain unbalanced, close them. |
266 | | */ |
267 | 0 | while ((depth > 0) && ((offset+1) < (ssize_t) extent)) { |
268 | 0 | title[offset++]=')'; |
269 | 0 | depth--; |
270 | 0 | } |
271 | 0 | title[offset]='\0'; |
272 | | /* |
273 | | Ensure non-empty result. |
274 | | */ |
275 | 0 | if (offset == 0) |
276 | 0 | { |
277 | 0 | (void) CopyMagickString(title,"Untitled",extent-1); |
278 | 0 | title[extent-1]='\0'; |
279 | 0 | } |
280 | 0 | } |
281 | | |
282 | | static MagickBooleanType Huffman2DEncodeImage(const ImageInfo *image_info, |
283 | | Image *image,Image *inject_image,ExceptionInfo *exception) |
284 | 0 | { |
285 | 0 | Image |
286 | 0 | *group4_image; |
287 | |
|
288 | 0 | ImageInfo |
289 | 0 | *write_info; |
290 | |
|
291 | 0 | MagickBooleanType |
292 | 0 | status; |
293 | |
|
294 | 0 | size_t |
295 | 0 | length; |
296 | |
|
297 | 0 | unsigned char |
298 | 0 | *group4; |
299 | |
|
300 | 0 | group4_image=CloneImage(inject_image,0,0,MagickTrue,exception); |
301 | 0 | if (group4_image == (Image *) NULL) |
302 | 0 | return(MagickFalse); |
303 | 0 | status=MagickTrue; |
304 | 0 | write_info=CloneImageInfo(image_info); |
305 | 0 | (void) CopyMagickString(write_info->filename,"GROUP4:",MagickPathExtent); |
306 | 0 | (void) CopyMagickString(write_info->magick,"GROUP4",MagickPathExtent); |
307 | 0 | group4=(unsigned char *) ImageToBlob(write_info,group4_image,&length, |
308 | 0 | exception); |
309 | 0 | group4_image=DestroyImage(group4_image); |
310 | 0 | write_info=DestroyImageInfo(write_info); |
311 | 0 | if (group4 == (unsigned char *) NULL) |
312 | 0 | return(MagickFalse); |
313 | 0 | if (WriteBlob(image,length,group4) != (ssize_t) length) |
314 | 0 | status=MagickFalse; |
315 | 0 | group4=(unsigned char *) RelinquishMagickMemory(group4); |
316 | 0 | return(status); |
317 | 0 | } |
318 | | |
319 | | static MagickBooleanType SerializeImage(const ImageInfo *image_info, |
320 | | Image *image,MemoryInfo **pixel_info,size_t *length,ExceptionInfo *exception) |
321 | 0 | { |
322 | 0 | MagickBooleanType |
323 | 0 | status; |
324 | |
|
325 | 0 | const Quantum |
326 | 0 | *p; |
327 | |
|
328 | 0 | size_t |
329 | 0 | channels, |
330 | 0 | extent; |
331 | |
|
332 | 0 | ssize_t |
333 | 0 | x, |
334 | 0 | y; |
335 | |
|
336 | 0 | unsigned char |
337 | 0 | *q; |
338 | |
|
339 | 0 | assert(image != (Image *) NULL); |
340 | 0 | assert(image->signature == MagickCoreSignature); |
341 | 0 | if (IsEventLogging() != MagickFalse) |
342 | 0 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); |
343 | 0 | status=MagickTrue; |
344 | 0 | channels=(image->colorspace == CMYKColorspace ? 4 : 3); |
345 | 0 | if (HeapOverflowSanityCheckGetSize(channels,(size_t) image->columns,&extent) != MagickFalse) |
346 | 0 | ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); |
347 | 0 | if (HeapOverflowSanityCheckGetSize(extent,image->rows,length) != MagickFalse) |
348 | 0 | ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); |
349 | 0 | *pixel_info=AcquireVirtualMemory(*length,sizeof(*q)); |
350 | 0 | if (*pixel_info == (MemoryInfo *) NULL) |
351 | 0 | ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); |
352 | 0 | q=(unsigned char *) GetVirtualMemoryBlob(*pixel_info); |
353 | 0 | (void) memset(q,0,*length*sizeof(*q)); |
354 | 0 | for (y=0; y < (ssize_t) image->rows; y++) |
355 | 0 | { |
356 | 0 | p=GetVirtualPixels(image,0,y,image->columns,1,exception); |
357 | 0 | if (p == (const Quantum *) NULL) |
358 | 0 | break; |
359 | 0 | if (image->colorspace != CMYKColorspace) |
360 | 0 | for (x=0; x < (ssize_t) image->columns; x++) |
361 | 0 | { |
362 | 0 | *q++=ScaleQuantumToChar(GetPixelRed(image,p)); |
363 | 0 | *q++=ScaleQuantumToChar(GetPixelGreen(image,p)); |
364 | 0 | *q++=ScaleQuantumToChar(GetPixelBlue(image,p)); |
365 | 0 | p+=(ptrdiff_t) GetPixelChannels(image); |
366 | 0 | } |
367 | 0 | else |
368 | 0 | for (x=0; x < (ssize_t) image->columns; x++) |
369 | 0 | { |
370 | 0 | *q++=ScaleQuantumToChar(GetPixelRed(image,p)); |
371 | 0 | *q++=ScaleQuantumToChar(GetPixelGreen(image,p)); |
372 | 0 | *q++=ScaleQuantumToChar(GetPixelBlue(image,p)); |
373 | 0 | *q++=ScaleQuantumToChar(GetPixelBlack(image,p)); |
374 | 0 | p+=(ptrdiff_t) GetPixelChannels(image); |
375 | 0 | } |
376 | 0 | if (image->previous == (Image *) NULL) |
377 | 0 | { |
378 | 0 | status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, |
379 | 0 | image->rows); |
380 | 0 | if (status == MagickFalse) |
381 | 0 | break; |
382 | 0 | } |
383 | 0 | } |
384 | 0 | if (status == MagickFalse) |
385 | 0 | *pixel_info=RelinquishVirtualMemory(*pixel_info); |
386 | 0 | return(status); |
387 | 0 | } |
388 | | |
389 | | static MagickBooleanType SerializeImageChannel(const ImageInfo *image_info, |
390 | | Image *image,MemoryInfo **pixel_info,size_t *length,ExceptionInfo *exception) |
391 | 0 | { |
392 | 0 | MagickBooleanType |
393 | 0 | status; |
394 | |
|
395 | 0 | const Quantum |
396 | 0 | *p; |
397 | |
|
398 | 0 | ssize_t |
399 | 0 | x; |
400 | |
|
401 | 0 | unsigned char |
402 | 0 | *q; |
403 | |
|
404 | 0 | size_t |
405 | 0 | pack, |
406 | 0 | padded_columns; |
407 | |
|
408 | 0 | ssize_t |
409 | 0 | y; |
410 | |
|
411 | 0 | unsigned char |
412 | 0 | code, |
413 | 0 | bit; |
414 | |
|
415 | 0 | assert(image != (Image *) NULL); |
416 | 0 | assert(image->signature == MagickCoreSignature); |
417 | 0 | if (IsEventLogging() != MagickFalse) |
418 | 0 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); |
419 | 0 | status=MagickTrue; |
420 | 0 | pack=SetImageMonochrome(image,exception) == MagickFalse ? 1UL : 8UL; |
421 | 0 | padded_columns=((image->columns+pack-1)/pack)*pack; |
422 | 0 | *length=(size_t) padded_columns*image->rows/pack; |
423 | 0 | *pixel_info=AcquireVirtualMemory(*length,sizeof(*q)); |
424 | 0 | if (*pixel_info == (MemoryInfo *) NULL) |
425 | 0 | ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); |
426 | 0 | q=(unsigned char *) GetVirtualMemoryBlob(*pixel_info); |
427 | 0 | for (y=0; y < (ssize_t) image->rows; y++) |
428 | 0 | { |
429 | 0 | p=GetVirtualPixels(image,0,y,image->columns,1,exception); |
430 | 0 | if (p == (const Quantum *) NULL) |
431 | 0 | break; |
432 | 0 | if (pack == 1) |
433 | 0 | for (x=0; x < (ssize_t) image->columns; x++) |
434 | 0 | { |
435 | 0 | *q++=ScaleQuantumToChar(ClampToQuantum(GetPixelLuma(image,p))); |
436 | 0 | p+=(ptrdiff_t) GetPixelChannels(image); |
437 | 0 | } |
438 | 0 | else |
439 | 0 | { |
440 | 0 | code='\0'; |
441 | 0 | for (x=0; x < (ssize_t) padded_columns; x++) |
442 | 0 | { |
443 | 0 | bit=(unsigned char) 0x00; |
444 | 0 | if (x < (ssize_t) image->columns) |
445 | 0 | bit=(unsigned char) (GetPixelLuma(image,p) == (double) |
446 | 0 | TransparentAlpha ? 0x01 : 0x00); |
447 | 0 | code=(code << 1)+bit; |
448 | 0 | if (((x+1) % (ssize_t) pack) == 0) |
449 | 0 | { |
450 | 0 | *q++=code; |
451 | 0 | code='\0'; |
452 | 0 | } |
453 | 0 | p+=(ptrdiff_t) GetPixelChannels(image); |
454 | 0 | } |
455 | 0 | } |
456 | 0 | status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, |
457 | 0 | image->rows); |
458 | 0 | if (status == MagickFalse) |
459 | 0 | break; |
460 | 0 | } |
461 | 0 | if (status == MagickFalse) |
462 | 0 | *pixel_info=RelinquishVirtualMemory(*pixel_info); |
463 | 0 | return(status); |
464 | 0 | } |
465 | | |
466 | | static MagickBooleanType SerializeImageIndexes(const ImageInfo *image_info, |
467 | | Image *image,MemoryInfo **pixel_info,size_t *length,ExceptionInfo *exception) |
468 | 0 | { |
469 | 0 | MagickBooleanType |
470 | 0 | status; |
471 | |
|
472 | 0 | const Quantum |
473 | 0 | *p; |
474 | |
|
475 | 0 | ssize_t |
476 | 0 | x; |
477 | |
|
478 | 0 | unsigned char |
479 | 0 | *q; |
480 | |
|
481 | 0 | ssize_t |
482 | 0 | y; |
483 | |
|
484 | 0 | assert(image != (Image *) NULL); |
485 | 0 | assert(image->signature == MagickCoreSignature); |
486 | 0 | if (IsEventLogging() != MagickFalse) |
487 | 0 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); |
488 | 0 | status=MagickTrue; |
489 | 0 | *length=(size_t) image->columns*image->rows; |
490 | 0 | *pixel_info=AcquireVirtualMemory(*length,sizeof(*q)); |
491 | 0 | if (*pixel_info == (MemoryInfo *) NULL) |
492 | 0 | ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); |
493 | 0 | q=(unsigned char *) GetVirtualMemoryBlob(*pixel_info); |
494 | 0 | for (y=0; y < (ssize_t) image->rows; y++) |
495 | 0 | { |
496 | 0 | p=GetVirtualPixels(image,0,y,image->columns,1,exception); |
497 | 0 | if (p == (const Quantum *) NULL) |
498 | 0 | break; |
499 | 0 | for (x=0; x < (ssize_t) image->columns; x++) |
500 | 0 | { |
501 | 0 | *q++=(unsigned char) ((ssize_t) GetPixelIndex(image,p)); |
502 | 0 | p+=(ptrdiff_t) GetPixelChannels(image); |
503 | 0 | } |
504 | 0 | if (image->previous == (Image *) NULL) |
505 | 0 | { |
506 | 0 | status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, |
507 | 0 | image->rows); |
508 | 0 | if (status == MagickFalse) |
509 | 0 | break; |
510 | 0 | } |
511 | 0 | } |
512 | 0 | if (status == MagickFalse) |
513 | 0 | *pixel_info=RelinquishVirtualMemory(*pixel_info); |
514 | 0 | return(status); |
515 | 0 | } |
516 | | |
517 | | static MagickBooleanType WritePS3MaskImage(const ImageInfo *image_info, |
518 | | Image *image,const CompressionType compression,ExceptionInfo *exception) |
519 | 0 | { |
520 | 0 | char |
521 | 0 | buffer[MagickPathExtent]; |
522 | |
|
523 | 0 | Image |
524 | 0 | *mask_image; |
525 | |
|
526 | 0 | MagickBooleanType |
527 | 0 | status; |
528 | |
|
529 | 0 | MagickOffsetType |
530 | 0 | offset, |
531 | 0 | start, |
532 | 0 | stop; |
533 | |
|
534 | 0 | MemoryInfo |
535 | 0 | *pixel_info; |
536 | |
|
537 | 0 | ssize_t |
538 | 0 | i; |
539 | |
|
540 | 0 | size_t |
541 | 0 | length; |
542 | |
|
543 | 0 | unsigned char |
544 | 0 | *pixels; |
545 | |
|
546 | 0 | assert(image_info != (ImageInfo *) NULL); |
547 | 0 | assert(image_info->signature == MagickCoreSignature); |
548 | 0 | assert(image != (Image *) NULL); |
549 | 0 | assert(image->signature == MagickCoreSignature); |
550 | 0 | assert(image->alpha_trait != UndefinedPixelTrait); |
551 | 0 | if (IsEventLogging() != MagickFalse) |
552 | 0 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); |
553 | 0 | status=MagickTrue; |
554 | | /* |
555 | | Note BeginData DSC comment for update later. |
556 | | */ |
557 | 0 | start=TellBlob(image); |
558 | 0 | if (start < 0) |
559 | 0 | ThrowWriterException(CorruptImageError,"ImproperImageHeader"); |
560 | 0 | (void) FormatLocaleString(buffer,MagickPathExtent, |
561 | 0 | "%%%%BeginData:%13ld %s Bytes\n",0L,compression == NoCompression ? |
562 | 0 | "ASCII" : "BINARY"); |
563 | 0 | (void) WriteBlobString(image,buffer); |
564 | 0 | stop=TellBlob(image); |
565 | 0 | if (stop < 0) |
566 | 0 | ThrowWriterException(CorruptImageError,"ImproperImageHeader"); |
567 | | /* |
568 | | Only lossless compressions for the mask. |
569 | | */ |
570 | 0 | switch (compression) |
571 | 0 | { |
572 | 0 | case NoCompression: |
573 | 0 | default: |
574 | 0 | { |
575 | 0 | (void) FormatLocaleString(buffer,MagickPathExtent, |
576 | 0 | "currentfile %.20g %.20g " PS3_NoCompression |
577 | 0 | " ByteStreamDecodeFilter\n",(double) image->columns,(double) |
578 | 0 | image->rows); |
579 | 0 | break; |
580 | 0 | } |
581 | 0 | case FaxCompression: |
582 | 0 | case Group4Compression: |
583 | 0 | { |
584 | 0 | (void) FormatLocaleString(buffer,MagickPathExtent, |
585 | 0 | "currentfile %.20g %.20g " PS3_FaxCompression |
586 | 0 | " ByteStreamDecodeFilter\n",(double) image->columns,(double) |
587 | 0 | image->rows); |
588 | 0 | break; |
589 | 0 | } |
590 | 0 | case LZWCompression: |
591 | 0 | { |
592 | 0 | (void) FormatLocaleString(buffer,MagickPathExtent, |
593 | 0 | "currentfile %.20g %.20g " PS3_LZWCompression |
594 | 0 | " ByteStreamDecodeFilter\n",(double) image->columns,(double) |
595 | 0 | image->rows); |
596 | 0 | break; |
597 | 0 | } |
598 | 0 | case RLECompression: |
599 | 0 | { |
600 | 0 | (void) FormatLocaleString(buffer,MagickPathExtent, |
601 | 0 | "currentfile %.20g %.20g " PS3_RLECompression |
602 | 0 | " ByteStreamDecodeFilter\n",(double) image->columns,(double) |
603 | 0 | image->rows); |
604 | 0 | break; |
605 | 0 | } |
606 | 0 | case ZipCompression: |
607 | 0 | { |
608 | 0 | (void) FormatLocaleString(buffer,MagickPathExtent, |
609 | 0 | "currentfile %.20g %.20g " PS3_ZipCompression |
610 | 0 | " ByteStreamDecodeFilter\n",(double) image->columns,(double) |
611 | 0 | image->rows); |
612 | 0 | break; |
613 | 0 | } |
614 | 0 | } |
615 | 0 | (void) WriteBlobString(image,buffer); |
616 | 0 | (void) WriteBlobString(image,"/ReusableStreamDecode filter\n"); |
617 | 0 | mask_image=SeparateImage(image,AlphaChannel,exception); |
618 | 0 | if (mask_image == (Image *) NULL) |
619 | 0 | ThrowWriterException(CoderError,exception->reason); |
620 | 0 | (void) SetImageType(mask_image,BilevelType,exception); |
621 | 0 | (void) SetImageType(mask_image,PaletteType,exception); |
622 | 0 | mask_image->alpha_trait=UndefinedPixelTrait; |
623 | 0 | pixels=(unsigned char *) NULL; |
624 | 0 | length=0; |
625 | 0 | switch (compression) |
626 | 0 | { |
627 | 0 | case NoCompression: |
628 | 0 | default: |
629 | 0 | { |
630 | 0 | status=SerializeImageChannel(image_info,mask_image,&pixel_info,&length, |
631 | 0 | exception); |
632 | 0 | if (status == MagickFalse) |
633 | 0 | break; |
634 | 0 | Ascii85Initialize(image); |
635 | 0 | pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); |
636 | 0 | for (i=0; i < (ssize_t) length; i++) |
637 | 0 | Ascii85Encode(image,pixels[i]); |
638 | 0 | Ascii85Flush(image); |
639 | 0 | pixel_info=RelinquishVirtualMemory(pixel_info); |
640 | 0 | break; |
641 | 0 | } |
642 | 0 | case FaxCompression: |
643 | 0 | case Group4Compression: |
644 | 0 | { |
645 | 0 | if ((compression == FaxCompression) || |
646 | 0 | (LocaleCompare(CCITTParam,"0") == 0)) |
647 | 0 | status=HuffmanEncodeImage(image_info,image,mask_image,exception); |
648 | 0 | else |
649 | 0 | status=Huffman2DEncodeImage(image_info,image,mask_image,exception); |
650 | 0 | break; |
651 | 0 | } |
652 | 0 | case LZWCompression: |
653 | 0 | { |
654 | 0 | status=SerializeImageChannel(image_info,mask_image,&pixel_info,&length, |
655 | 0 | exception); |
656 | 0 | if (status == MagickFalse) |
657 | 0 | break; |
658 | 0 | pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); |
659 | 0 | status=LZWEncodeImage(image,length,pixels,exception); |
660 | 0 | pixel_info=RelinquishVirtualMemory(pixel_info); |
661 | 0 | break; |
662 | 0 | } |
663 | 0 | case RLECompression: |
664 | 0 | { |
665 | 0 | status=SerializeImageChannel(image_info,mask_image,&pixel_info,&length, |
666 | 0 | exception); |
667 | 0 | if (status == MagickFalse) |
668 | 0 | break; |
669 | 0 | pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); |
670 | 0 | status=PackbitsEncodeImage(image,length,pixels,exception); |
671 | 0 | pixel_info=RelinquishVirtualMemory(pixel_info); |
672 | 0 | break; |
673 | 0 | } |
674 | 0 | case ZipCompression: |
675 | 0 | { |
676 | 0 | status=SerializeImageChannel(image_info,mask_image,&pixel_info,&length, |
677 | 0 | exception); |
678 | 0 | if (status == MagickFalse) |
679 | 0 | break; |
680 | 0 | pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); |
681 | 0 | status=ZLIBEncodeImage(image,length,pixels,exception); |
682 | 0 | pixel_info=RelinquishVirtualMemory(pixel_info); |
683 | 0 | break; |
684 | 0 | } |
685 | 0 | } |
686 | 0 | mask_image=DestroyImage(mask_image); |
687 | 0 | (void) WriteBlobByte(image,'\n'); |
688 | 0 | length=(size_t) (TellBlob(image)-stop); |
689 | 0 | stop=TellBlob(image); |
690 | 0 | if (stop < 0) |
691 | 0 | ThrowWriterException(CorruptImageError,"ImproperImageHeader"); |
692 | 0 | offset=SeekBlob(image,start,SEEK_SET); |
693 | 0 | if (offset < 0) |
694 | 0 | ThrowWriterException(CorruptImageError,"ImproperImageHeader"); |
695 | 0 | (void) FormatLocaleString(buffer,MagickPathExtent, |
696 | 0 | "%%%%BeginData:%13ld %s Bytes\n",(long) length, |
697 | 0 | compression == NoCompression ? "ASCII" : "BINARY"); |
698 | 0 | (void) WriteBlobString(image,buffer); |
699 | 0 | offset=SeekBlob(image,stop,SEEK_SET); |
700 | 0 | if (offset < 0) |
701 | 0 | ThrowWriterException(CorruptImageError,"ImproperImageHeader"); |
702 | 0 | (void) WriteBlobString(image,"%%EndData\n"); |
703 | 0 | (void) WriteBlobString(image, "/mask_stream exch def\n"); |
704 | 0 | return(status); |
705 | 0 | } |
706 | | |
707 | | static MagickBooleanType WritePS3Image(const ImageInfo *image_info,Image *image, |
708 | | ExceptionInfo *exception) |
709 | 0 | { |
710 | 0 | static const char |
711 | 0 | PostscriptProlog[] = |
712 | 0 | "/ByteStreamDecodeFilter\n" |
713 | 0 | "{\n" |
714 | 0 | " /z exch def\n" |
715 | 0 | " /r exch def\n" |
716 | 0 | " /c exch def\n" |
717 | 0 | " z " PS3_NoCompression " eq { /ASCII85Decode filter } if\n" |
718 | 0 | " z " PS3_FaxCompression " eq\n" |
719 | 0 | " {\n" |
720 | 0 | " <<\n" |
721 | 0 | " /K " CCITTParam "\n" |
722 | 0 | " /Columns c\n" |
723 | 0 | " /Rows r\n" |
724 | 0 | " >>\n" |
725 | 0 | " /CCITTFaxDecode filter\n" |
726 | 0 | " } if\n" |
727 | 0 | " z " PS3_JPEGCompression " eq { /DCTDecode filter } if\n" |
728 | 0 | " z " PS3_LZWCompression " eq { /LZWDecode filter } if\n" |
729 | 0 | " z " PS3_RLECompression " eq { /RunLengthDecode filter } if\n" |
730 | 0 | " z " PS3_ZipCompression " eq { /FlateDecode filter } if\n" |
731 | 0 | "} bind def\n" |
732 | 0 | "\n" |
733 | 0 | "/DirectClassImageDict\n" |
734 | 0 | "{\n" |
735 | 0 | " colorspace " PS3_RGBColorspace " eq\n" |
736 | 0 | " {\n" |
737 | 0 | " /DeviceRGB setcolorspace\n" |
738 | 0 | " <<\n" |
739 | 0 | " /ImageType 1\n" |
740 | 0 | " /Width columns\n" |
741 | 0 | " /Height rows\n" |
742 | 0 | " /BitsPerComponent 8\n" |
743 | 0 | " /DataSource pixel_stream\n" |
744 | 0 | " /MultipleDataSources false\n" |
745 | 0 | " /ImageMatrix [columns 0 0 rows neg 0 rows]\n" |
746 | 0 | " /Decode [0 1 0 1 0 1]\n" |
747 | 0 | " >>\n" |
748 | 0 | " }\n" |
749 | 0 | " {\n" |
750 | 0 | " /DeviceCMYK setcolorspace\n" |
751 | 0 | " <<\n" |
752 | 0 | " /ImageType 1\n" |
753 | 0 | " /Width columns\n" |
754 | 0 | " /Height rows\n" |
755 | 0 | " /BitsPerComponent 8\n" |
756 | 0 | " /DataSource pixel_stream\n" |
757 | 0 | " /MultipleDataSources false\n" |
758 | 0 | " /ImageMatrix [columns 0 0 rows neg 0 rows]\n" |
759 | 0 | " /Decode\n" |
760 | 0 | " compression " PS3_JPEGCompression " eq\n" |
761 | 0 | " { [1 0 1 0 1 0 1 0] }\n" |
762 | 0 | " { [0 1 0 1 0 1 0 1] }\n" |
763 | 0 | " ifelse\n" |
764 | 0 | " >>\n" |
765 | 0 | " }\n" |
766 | 0 | " ifelse\n" |
767 | 0 | "} bind def\n" |
768 | 0 | "\n" |
769 | 0 | "/PseudoClassImageDict\n" |
770 | 0 | "{\n" |
771 | 0 | " % Colors in colormap image.\n" |
772 | 0 | " currentfile buffer readline pop\n" |
773 | 0 | " token pop /colors exch def pop\n" |
774 | 0 | " colors 0 eq\n" |
775 | 0 | " {\n" |
776 | 0 | " % Depth of grayscale image.\n" |
777 | 0 | " currentfile buffer readline pop\n" |
778 | 0 | " token pop /bits exch def pop\n" |
779 | 0 | " /DeviceGray setcolorspace\n" |
780 | 0 | " <<\n" |
781 | 0 | " /ImageType 1\n" |
782 | 0 | " /Width columns\n" |
783 | 0 | " /Height rows\n" |
784 | 0 | " /BitsPerComponent bits\n" |
785 | 0 | " /Decode [0 1]\n" |
786 | 0 | " /ImageMatrix [columns 0 0 rows neg 0 rows]\n" |
787 | 0 | " /DataSource pixel_stream\n" |
788 | 0 | " >>\n" |
789 | 0 | " }\n" |
790 | 0 | " {\n" |
791 | 0 | " % RGB colormap.\n" |
792 | 0 | " /colormap colors 3 mul string def\n" |
793 | 0 | " compression " PS3_NoCompression " eq\n" |
794 | 0 | " { currentfile /ASCII85Decode filter colormap readstring pop pop }\n" |
795 | 0 | " { currentfile colormap readstring pop pop }\n" |
796 | 0 | " ifelse\n" |
797 | 0 | " [ /Indexed /DeviceRGB colors 1 sub colormap ] setcolorspace\n" |
798 | 0 | " <<\n" |
799 | 0 | " /ImageType 1\n" |
800 | 0 | " /Width columns\n" |
801 | 0 | " /Height rows\n" |
802 | 0 | " /BitsPerComponent 8\n" |
803 | 0 | " /Decode [0 255]\n" |
804 | 0 | " /ImageMatrix [columns 0 0 rows neg 0 rows]\n" |
805 | 0 | " /DataSource pixel_stream\n" |
806 | 0 | " >>\n" |
807 | 0 | " }\n" |
808 | 0 | " ifelse\n" |
809 | 0 | "} bind def\n" |
810 | 0 | "\n" |
811 | 0 | "/NonMaskedImageDict\n" |
812 | 0 | "{\n" |
813 | 0 | " class " PS3_PseudoClass " eq\n" |
814 | 0 | " { PseudoClassImageDict }\n" |
815 | 0 | " { DirectClassImageDict }\n" |
816 | 0 | " ifelse\n" |
817 | 0 | "} bind def\n" |
818 | 0 | "\n" |
819 | 0 | "/MaskedImageDict\n" |
820 | 0 | "{\n" |
821 | 0 | " <<\n" |
822 | 0 | " /ImageType 3\n" |
823 | 0 | " /InterleaveType 3\n" |
824 | 0 | " /DataDict NonMaskedImageDict\n" |
825 | 0 | " /MaskDict\n" |
826 | 0 | " <<\n" |
827 | 0 | " /ImageType 1\n" |
828 | 0 | " /Width columns\n" |
829 | 0 | " /Height rows\n" |
830 | 0 | " /BitsPerComponent 1\n" |
831 | 0 | " /DataSource mask_stream\n" |
832 | 0 | " /MultipleDataSources false\n" |
833 | 0 | " /ImageMatrix [ columns 0 0 rows neg 0 rows]\n" |
834 | 0 | " /Decode [ 0 1 ]\n" |
835 | 0 | " >>\n" |
836 | 0 | " >>\n" |
837 | 0 | "} bind def\n" |
838 | 0 | "\n" |
839 | 0 | "/ClipImage\n" |
840 | 0 | "{} def\n" |
841 | 0 | "\n" |
842 | 0 | "/DisplayImage\n" |
843 | 0 | "{\n" |
844 | 0 | " gsave\n" |
845 | 0 | " /buffer 512 string def\n" |
846 | 0 | " % Translation.\n" |
847 | 0 | " currentfile buffer readline pop\n" |
848 | 0 | " token pop /x exch def\n" |
849 | 0 | " token pop /y exch def pop\n" |
850 | 0 | " x y translate\n" |
851 | 0 | " % Image size and font size.\n" |
852 | 0 | " currentfile buffer readline pop\n" |
853 | 0 | " token pop /x exch def\n" |
854 | 0 | " token pop /y exch def pop\n" |
855 | 0 | " currentfile buffer readline pop\n" |
856 | 0 | " token pop /pointsize exch def pop\n"; |
857 | 0 | static const char |
858 | 0 | PostscriptEpilog[] = |
859 | 0 | " x y scale\n" |
860 | 0 | " % Clipping path.\n" |
861 | 0 | " currentfile buffer readline pop\n" |
862 | 0 | " token pop /clipped exch def pop\n" |
863 | 0 | " % Showpage.\n" |
864 | 0 | " currentfile buffer readline pop\n" |
865 | 0 | " token pop /sp exch def pop\n" |
866 | 0 | " % Image pixel size.\n" |
867 | 0 | " currentfile buffer readline pop\n" |
868 | 0 | " token pop /columns exch def\n" |
869 | 0 | " token pop /rows exch def pop\n" |
870 | 0 | " % Colorspace (RGB/CMYK).\n" |
871 | 0 | " currentfile buffer readline pop\n" |
872 | 0 | " token pop /colorspace exch def pop\n" |
873 | 0 | " % Transparency.\n" |
874 | 0 | " currentfile buffer readline pop\n" |
875 | 0 | " token pop /alpha exch def pop\n" |
876 | 0 | " % Stencil mask?\n" |
877 | 0 | " currentfile buffer readline pop\n" |
878 | 0 | " token pop /stencil exch def pop\n" |
879 | 0 | " % Image class (direct/pseudo).\n" |
880 | 0 | " currentfile buffer readline pop\n" |
881 | 0 | " token pop /class exch def pop\n" |
882 | 0 | " % Compression type.\n" |
883 | 0 | " currentfile buffer readline pop\n" |
884 | 0 | " token pop /compression exch def pop\n" |
885 | 0 | " % Clip and render.\n" |
886 | 0 | " /pixel_stream currentfile columns rows compression ByteStreamDecodeFilter def\n" |
887 | 0 | " clipped { ClipImage } if\n" |
888 | 0 | " alpha stencil not and\n" |
889 | 0 | " { MaskedImageDict mask_stream resetfile }\n" |
890 | 0 | " { NonMaskedImageDict }\n" |
891 | 0 | " ifelse\n" |
892 | 0 | " stencil { 0 setgray imagemask } { image } ifelse\n" |
893 | 0 | " grestore\n" |
894 | 0 | " sp { showpage } if\n" |
895 | 0 | "} bind def\n"; |
896 | |
|
897 | 0 | char |
898 | 0 | buffer[MagickPathExtent], |
899 | 0 | date[MagickTimeExtent], |
900 | 0 | **labels, |
901 | 0 | page_geometry[MagickPathExtent]; |
902 | |
|
903 | 0 | CompressionType |
904 | 0 | compression; |
905 | |
|
906 | 0 | const char |
907 | 0 | *option, |
908 | 0 | *value; |
909 | |
|
910 | 0 | double |
911 | 0 | pointsize; |
912 | |
|
913 | 0 | GeometryInfo |
914 | 0 | geometry_info; |
915 | |
|
916 | 0 | MagickBooleanType |
917 | 0 | status; |
918 | |
|
919 | 0 | MagickOffsetType |
920 | 0 | offset, |
921 | 0 | scene, |
922 | 0 | start, |
923 | 0 | stop; |
924 | |
|
925 | 0 | MagickStatusType |
926 | 0 | flags; |
927 | |
|
928 | 0 | MemoryInfo |
929 | 0 | *pixel_info; |
930 | |
|
931 | 0 | PointInfo |
932 | 0 | delta, |
933 | 0 | resolution, |
934 | 0 | scale; |
935 | |
|
936 | 0 | RectangleInfo |
937 | 0 | geometry, |
938 | 0 | media_info, |
939 | 0 | page_info; |
940 | |
|
941 | 0 | SegmentInfo |
942 | 0 | bounds; |
943 | |
|
944 | 0 | size_t |
945 | 0 | length, |
946 | 0 | number_scenes, |
947 | 0 | page, |
948 | 0 | pixel, |
949 | 0 | text_size; |
950 | |
|
951 | 0 | ssize_t |
952 | 0 | i, |
953 | 0 | j; |
954 | |
|
955 | 0 | time_t |
956 | 0 | timer; |
957 | |
|
958 | 0 | unsigned char |
959 | 0 | *pixels; |
960 | | |
961 | | /* |
962 | | Open output image file. |
963 | | */ |
964 | 0 | assert(image_info != (const ImageInfo *) NULL); |
965 | 0 | assert(image_info->signature == MagickCoreSignature); |
966 | 0 | assert(image != (Image *) NULL); |
967 | 0 | assert(image->signature == MagickCoreSignature); |
968 | 0 | assert(exception != (ExceptionInfo *) NULL); |
969 | 0 | assert(exception->signature == MagickCoreSignature); |
970 | 0 | if (IsEventLogging() != MagickFalse) |
971 | 0 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); |
972 | 0 | status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); |
973 | 0 | if (status == MagickFalse) |
974 | 0 | return(MagickFalse); |
975 | 0 | compression=image->compression; |
976 | 0 | if (image_info->compression != UndefinedCompression) |
977 | 0 | compression=image_info->compression; |
978 | 0 | switch (compression) |
979 | 0 | { |
980 | 0 | case FaxCompression: |
981 | 0 | case Group4Compression: |
982 | 0 | { |
983 | 0 | if ((SetImageMonochrome(image,exception) == MagickFalse) || |
984 | 0 | (image->alpha_trait != UndefinedPixelTrait)) |
985 | 0 | compression=RLECompression; |
986 | 0 | break; |
987 | 0 | } |
988 | | #if !defined(MAGICKCORE_JPEG_DELEGATE) |
989 | | case JPEGCompression: |
990 | | { |
991 | | compression=RLECompression; |
992 | | (void) ThrowMagickException(exception,GetMagickModule(), |
993 | | MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (JPEG)", |
994 | | image->filename); |
995 | | break; |
996 | | } |
997 | | #endif |
998 | | #if !defined(MAGICKCORE_ZLIB_DELEGATE) |
999 | | case ZipCompression: |
1000 | | { |
1001 | | compression=RLECompression; |
1002 | | (void) ThrowMagickException(exception,GetMagickModule(), |
1003 | | MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (ZLIB)", |
1004 | | image->filename); |
1005 | | break; |
1006 | | } |
1007 | | #endif |
1008 | 0 | default: |
1009 | 0 | break; |
1010 | 0 | } |
1011 | 0 | (void) memset(&bounds,0,sizeof(bounds)); |
1012 | 0 | page=0; |
1013 | 0 | scene=0; |
1014 | 0 | number_scenes=GetImageListLength(image); |
1015 | 0 | do |
1016 | 0 | { |
1017 | 0 | MagickBooleanType |
1018 | 0 | is_gray; |
1019 | | |
1020 | | /* |
1021 | | Scale relative to dots-per-inch. |
1022 | | */ |
1023 | 0 | delta.x=DefaultResolution; |
1024 | 0 | delta.y=DefaultResolution; |
1025 | 0 | resolution.x=image->resolution.x; |
1026 | 0 | resolution.y=image->resolution.y; |
1027 | 0 | if ((resolution.x == 0.0) || (resolution.y == 0.0)) |
1028 | 0 | { |
1029 | 0 | flags=ParseGeometry(PSDensityGeometry,&geometry_info); |
1030 | 0 | if ((flags & RhoValue) != 0) |
1031 | 0 | resolution.x=geometry_info.rho; |
1032 | 0 | resolution.y=resolution.x; |
1033 | 0 | if ((flags & SigmaValue) != 0) |
1034 | 0 | resolution.y=geometry_info.sigma; |
1035 | 0 | } |
1036 | 0 | if (image_info->density != (char *) NULL) |
1037 | 0 | { |
1038 | 0 | flags=ParseGeometry(image_info->density,&geometry_info); |
1039 | 0 | if ((flags & RhoValue) != 0) |
1040 | 0 | resolution.x=geometry_info.rho; |
1041 | 0 | resolution.y=resolution.x; |
1042 | 0 | if ((flags & SigmaValue) != 0) |
1043 | 0 | resolution.y=geometry_info.sigma; |
1044 | 0 | } |
1045 | 0 | if (image->units == PixelsPerCentimeterResolution) |
1046 | 0 | { |
1047 | 0 | resolution.x=(100.0*2.54*resolution.x+0.5)/100.0; |
1048 | 0 | resolution.y=(100.0*2.54*resolution.y+0.5)/100.0; |
1049 | 0 | } |
1050 | 0 | SetGeometry(image,&geometry); |
1051 | 0 | (void) FormatLocaleString(page_geometry,MagickPathExtent,"%.20gx%.20g", |
1052 | 0 | (double) image->columns,(double) image->rows); |
1053 | 0 | if (image_info->page != (char *) NULL) |
1054 | 0 | (void) CopyMagickString(page_geometry,image_info->page,MagickPathExtent); |
1055 | 0 | else |
1056 | 0 | if ((image->page.width != 0) && (image->page.height != 0)) |
1057 | 0 | (void) FormatLocaleString(page_geometry,MagickPathExtent, |
1058 | 0 | "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,(double) |
1059 | 0 | image->page.height,(double) image->page.x,(double) image->page.y); |
1060 | 0 | else |
1061 | 0 | if ((image->gravity != UndefinedGravity) && |
1062 | 0 | (LocaleCompare(image_info->magick,"PS") == 0)) |
1063 | 0 | (void) CopyMagickString(page_geometry,PSPageGeometry, |
1064 | 0 | MagickPathExtent); |
1065 | 0 | (void) ConcatenateMagickString(page_geometry,">",MagickPathExtent); |
1066 | 0 | (void) ParseMetaGeometry(page_geometry,&geometry.x,&geometry.y, |
1067 | 0 | &geometry.width,&geometry.height); |
1068 | 0 | scale.x=MagickSafeReciprocal(resolution.x)*geometry.width*delta.x; |
1069 | 0 | geometry.width=CastDoubleToSizeT(scale.x+0.5); |
1070 | 0 | scale.y=MagickSafeReciprocal(resolution.y)*geometry.height*delta.y; |
1071 | 0 | geometry.height=CastDoubleToSizeT(scale.y+0.5); |
1072 | 0 | (void) ParseAbsoluteGeometry(page_geometry,&media_info); |
1073 | 0 | (void) ParseGravityGeometry(image,page_geometry,&page_info,exception); |
1074 | 0 | if (image->gravity != UndefinedGravity) |
1075 | 0 | { |
1076 | 0 | geometry.x=(-page_info.x); |
1077 | 0 | geometry.y=(ssize_t) media_info.height+page_info.y-(ssize_t) |
1078 | 0 | image->rows; |
1079 | 0 | } |
1080 | 0 | pointsize=12.0; |
1081 | 0 | if (image_info->pointsize != 0.0) |
1082 | 0 | pointsize=image_info->pointsize; |
1083 | 0 | text_size=0; |
1084 | 0 | value=GetImageProperty(image,"label",exception); |
1085 | 0 | if (value != (const char *) NULL) |
1086 | 0 | text_size=(size_t) (MultilineCensus(value)*pointsize+12); |
1087 | 0 | page++; |
1088 | 0 | is_gray=IdentifyImageCoderGray(image,exception); |
1089 | 0 | if (page == 1) |
1090 | 0 | { |
1091 | 0 | char |
1092 | 0 | title[MagickPathExtent]; |
1093 | | |
1094 | | /* |
1095 | | Postscript header on the first page. |
1096 | | */ |
1097 | 0 | if (LocaleCompare(image_info->magick,"PS3") == 0) |
1098 | 0 | (void) CopyMagickString(buffer,"%!PS-Adobe-3.0\n",MagickPathExtent); |
1099 | 0 | else |
1100 | 0 | (void) CopyMagickString(buffer,"%!PS-Adobe-3.0 EPSF-3.0\n", |
1101 | 0 | MagickPathExtent); |
1102 | 0 | (void) WriteBlobString(image,buffer); |
1103 | 0 | (void) FormatLocaleString(buffer,MagickPathExtent, |
1104 | 0 | "%%%%Creator: ImageMagick %s\n",MagickLibVersionText); |
1105 | 0 | (void) WriteBlobString(image,buffer); |
1106 | 0 | FilenameToTitle(image->filename,title,MagickPathExtent); |
1107 | 0 | (void) FormatLocaleString(buffer,MagickPathExtent,"%%%%Title: %s\n", |
1108 | 0 | title); |
1109 | 0 | (void) WriteBlobString(image,buffer); |
1110 | 0 | timer=GetMagickTime(); |
1111 | 0 | (void) FormatMagickTime(timer,sizeof(date),date); |
1112 | 0 | (void) FormatLocaleString(buffer,MagickPathExtent, |
1113 | 0 | "%%%%CreationDate: %s\n",date); |
1114 | 0 | (void) WriteBlobString(image,buffer); |
1115 | 0 | bounds.x1=(double) geometry.x; |
1116 | 0 | bounds.y1=(double) geometry.y; |
1117 | 0 | bounds.x2=(double) geometry.x+scale.x; |
1118 | 0 | bounds.y2=(double) geometry.y+scale.y+text_size; |
1119 | 0 | if ((image_info->adjoin != MagickFalse) && |
1120 | 0 | (GetNextImageInList(image) != (Image *) NULL)) |
1121 | 0 | { |
1122 | 0 | (void) WriteBlobString(image,"%%BoundingBox: (atend)\n"); |
1123 | 0 | (void) WriteBlobString(image,"%%HiResBoundingBox: (atend)\n"); |
1124 | 0 | } |
1125 | 0 | else |
1126 | 0 | { |
1127 | 0 | (void) FormatLocaleString(buffer,MagickPathExtent, |
1128 | 0 | "%%%%BoundingBox: %g %g %g %g\n",ceil(bounds.x1-0.5), |
1129 | 0 | ceil(bounds.y1-0.5),floor(bounds.x2+0.5),floor(bounds.y2+0.5)); |
1130 | 0 | (void) WriteBlobString(image,buffer); |
1131 | 0 | (void) FormatLocaleString(buffer,MagickPathExtent, |
1132 | 0 | "%%%%HiResBoundingBox: %g %g %g %g\n",bounds.x1, |
1133 | 0 | bounds.y1,bounds.x2,bounds.y2); |
1134 | 0 | (void) WriteBlobString(image,buffer); |
1135 | 0 | if (image->colorspace == CMYKColorspace) |
1136 | 0 | (void) WriteBlobString(image, |
1137 | 0 | "%%DocumentProcessColors: Cyan Magenta Yellow Black\n"); |
1138 | 0 | else |
1139 | 0 | if (is_gray != MagickFalse) |
1140 | 0 | (void) WriteBlobString(image, |
1141 | 0 | "%%DocumentProcessColors: Black\n"); |
1142 | 0 | } |
1143 | | /* |
1144 | | Font resources |
1145 | | */ |
1146 | 0 | value=GetImageProperty(image,"label",exception); |
1147 | 0 | if (value != (const char *) NULL) |
1148 | 0 | (void) WriteBlobString(image, |
1149 | 0 | "%%DocumentNeededResources: font Helvetica\n"); |
1150 | 0 | (void) WriteBlobString(image,"%%LanguageLevel: 3\n"); |
1151 | | /* |
1152 | | Pages, orientation and order. |
1153 | | */ |
1154 | 0 | if (LocaleCompare(image_info->magick,"PS3") != 0) |
1155 | 0 | (void) WriteBlobString(image,"%%Pages: 1\n"); |
1156 | 0 | else |
1157 | 0 | { |
1158 | 0 | (void) WriteBlobString(image,"%%Orientation: Portrait\n"); |
1159 | 0 | (void) WriteBlobString(image,"%%PageOrder: Ascend\n"); |
1160 | 0 | if (image_info->adjoin == MagickFalse) |
1161 | 0 | (void) CopyMagickString(buffer,"%%Pages: 1\n",MagickPathExtent); |
1162 | 0 | else |
1163 | 0 | (void) FormatLocaleString(buffer,MagickPathExtent, |
1164 | 0 | "%%%%Pages: %.20g\n",(double) number_scenes); |
1165 | 0 | (void) WriteBlobString(image,buffer); |
1166 | 0 | } |
1167 | 0 | if (image->colorspace == CMYKColorspace) |
1168 | 0 | (void) WriteBlobString(image, |
1169 | 0 | "%%DocumentProcessColors: Cyan Magenta Yellow Black\n"); |
1170 | 0 | (void) WriteBlobString(image,"%%EndComments\n"); |
1171 | | /* |
1172 | | The static postscript procedures prolog. |
1173 | | */ |
1174 | 0 | (void) WriteBlobString(image,"%%BeginProlog\n"); |
1175 | 0 | (void) WriteBlob(image,sizeof(PostscriptProlog)-1,PostscriptProlog); |
1176 | | /* |
1177 | | One label line for each line in label string. |
1178 | | */ |
1179 | 0 | value=GetImageProperty(image,"label",exception); |
1180 | 0 | if (value != (const char *) NULL) |
1181 | 0 | { |
1182 | 0 | (void) WriteBlobString(image,"\n %% Labels.\n /Helvetica " |
1183 | 0 | " findfont pointsize scalefont setfont\n"); |
1184 | 0 | for (i=(ssize_t) MultilineCensus(value)-1; i >= 0; i--) |
1185 | 0 | { |
1186 | 0 | (void) WriteBlobString(image, |
1187 | 0 | " currentfile buffer readline pop token pop\n"); |
1188 | 0 | (void) FormatLocaleString(buffer,MagickPathExtent, |
1189 | 0 | " 0 y %g add moveto show pop\n",i*pointsize+12); |
1190 | 0 | (void) WriteBlobString(image,buffer); |
1191 | 0 | } |
1192 | 0 | } |
1193 | | /* |
1194 | | The static postscript procedures epilog. |
1195 | | */ |
1196 | 0 | (void) WriteBlob(image,sizeof(PostscriptEpilog)-1,PostscriptEpilog); |
1197 | 0 | (void) WriteBlobString(image,"%%EndProlog\n"); |
1198 | 0 | } |
1199 | 0 | (void) FormatLocaleString(buffer,MagickPathExtent,"%%%%Page: 1 %.20g\n", |
1200 | 0 | (double) page); |
1201 | 0 | (void) WriteBlobString(image,buffer); |
1202 | | /* |
1203 | | Page bounding box. |
1204 | | */ |
1205 | 0 | (void) FormatLocaleString(buffer,MagickPathExtent, |
1206 | 0 | "%%%%PageBoundingBox: %.20g %.20g %.20g %.20g\n",(double) geometry.x, |
1207 | 0 | (double) geometry.y,geometry.x+(double) geometry.width,geometry.y+ |
1208 | 0 | (double) (geometry.height+text_size)); |
1209 | 0 | (void) WriteBlobString(image,buffer); |
1210 | | /* |
1211 | | Page process colors if not RGB. |
1212 | | */ |
1213 | 0 | if (image->colorspace == CMYKColorspace) |
1214 | 0 | (void) WriteBlobString(image, |
1215 | 0 | "%%PageProcessColors: Cyan Magenta Yellow Black\n"); |
1216 | 0 | else |
1217 | 0 | if (is_gray != MagickFalse) |
1218 | 0 | (void) WriteBlobString(image,"%%PageProcessColors: Black\n"); |
1219 | | /* |
1220 | | Adjust document bounding box to bound page bounding box. |
1221 | | */ |
1222 | 0 | if ((double) geometry.x < bounds.x1) |
1223 | 0 | bounds.x1=(double) geometry.x; |
1224 | 0 | if ((double) geometry.y < bounds.y1) |
1225 | 0 | bounds.y1=(double) geometry.y; |
1226 | 0 | if ((double) (geometry.x+scale.x) > bounds.x2) |
1227 | 0 | bounds.x2=(double) geometry.x+scale.x; |
1228 | 0 | if ((double) (geometry.y+scale.y+text_size) > bounds.y2) |
1229 | 0 | bounds.y2=(double) geometry.y+scale.y+text_size; |
1230 | | /* |
1231 | | Page font resource if there's a label. |
1232 | | */ |
1233 | 0 | value=GetImageProperty(image,"label",exception); |
1234 | 0 | if (value != (const char *) NULL) |
1235 | 0 | (void) WriteBlobString(image,"%%PageResources: font Helvetica\n"); |
1236 | | /* |
1237 | | PS clipping path from Photoshop clipping path. |
1238 | | */ |
1239 | 0 | if (((image->channels & WriteMaskChannel) != 0) || |
1240 | 0 | (LocaleNCompare("8BIM:",image->magick_filename,5) != 0)) |
1241 | 0 | (void) WriteBlobString(image,"/ClipImage {} def\n"); |
1242 | 0 | else |
1243 | 0 | { |
1244 | 0 | value=GetImageProperty(image,image->magick_filename,exception); |
1245 | 0 | if (value == (const char *) NULL) |
1246 | 0 | return(MagickFalse); |
1247 | 0 | (void) WriteBlobString(image,value); |
1248 | 0 | (void) WriteBlobByte(image,'\n'); |
1249 | 0 | } |
1250 | | /* |
1251 | | Push a dictionary for our own def's if this an EPS. |
1252 | | */ |
1253 | 0 | if (LocaleCompare(image_info->magick,"PS3") != 0) |
1254 | 0 | (void) WriteBlobString(image,"userdict begin\n"); |
1255 | | /* |
1256 | | Image mask. |
1257 | | */ |
1258 | 0 | if ((image->alpha_trait != UndefinedPixelTrait) && |
1259 | 0 | (WritePS3MaskImage(image_info,image,compression,exception) == MagickFalse)) |
1260 | 0 | { |
1261 | 0 | (void) CloseBlob(image); |
1262 | 0 | return(MagickFalse); |
1263 | 0 | } |
1264 | | /* |
1265 | | Remember position of BeginData comment so we can update it. |
1266 | | */ |
1267 | 0 | start=TellBlob(image); |
1268 | 0 | if (start < 0) |
1269 | 0 | ThrowWriterException(CorruptImageError,"ImproperImageHeader"); |
1270 | 0 | (void) FormatLocaleString(buffer,MagickPathExtent, |
1271 | 0 | "%%%%BeginData:%13ld %s Bytes\n",0L, |
1272 | 0 | compression == NoCompression ? "ASCII" : "BINARY"); |
1273 | 0 | (void) WriteBlobString(image,buffer); |
1274 | 0 | stop=TellBlob(image); |
1275 | 0 | if (stop < 0) |
1276 | 0 | ThrowWriterException(CorruptImageError,"ImproperImageHeader"); |
1277 | 0 | (void) WriteBlobString(image,"DisplayImage\n"); |
1278 | | /* |
1279 | | Translate, scale, and font point size. |
1280 | | */ |
1281 | 0 | (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g %.20g\n%g %g\n%g\n", |
1282 | 0 | (double) geometry.x,(double) geometry.y,scale.x,scale.y,pointsize); |
1283 | 0 | (void) WriteBlobString(image,buffer); |
1284 | | /* |
1285 | | Output labels. |
1286 | | */ |
1287 | 0 | labels=(char **) NULL; |
1288 | 0 | value=GetImageProperty(image,"label",exception); |
1289 | 0 | if (value != (const char *) NULL) |
1290 | 0 | labels=StringToList(value); |
1291 | 0 | if (labels != (char **) NULL) |
1292 | 0 | { |
1293 | 0 | for (i=0; labels[i] != (char *) NULL; i++) |
1294 | 0 | { |
1295 | 0 | if (compression != NoCompression) |
1296 | 0 | { |
1297 | 0 | for (j=0; labels[i][j] != '\0'; j++) |
1298 | 0 | (void) WriteBlobByte(image,(unsigned char) labels[i][j]); |
1299 | 0 | (void) WriteBlobByte(image,'\n'); |
1300 | 0 | } |
1301 | 0 | else |
1302 | 0 | { |
1303 | 0 | (void) WriteBlobString(image,"<~"); |
1304 | 0 | Ascii85Initialize(image); |
1305 | 0 | for (j=0; labels[i][j] != '\0'; j++) |
1306 | 0 | Ascii85Encode(image,(unsigned char) labels[i][j]); |
1307 | 0 | Ascii85Flush(image); |
1308 | 0 | } |
1309 | 0 | labels[i]=DestroyString(labels[i]); |
1310 | 0 | } |
1311 | 0 | labels=(char **) RelinquishMagickMemory(labels); |
1312 | 0 | } |
1313 | | /* |
1314 | | Photoshop clipping path active? |
1315 | | */ |
1316 | 0 | if (((image->channels & WriteMaskChannel) != 0) && |
1317 | 0 | (LocaleNCompare("8BIM:",image->magick_filename,5) == 0)) |
1318 | 0 | (void) WriteBlobString(image,"true\n"); |
1319 | 0 | else |
1320 | 0 | (void) WriteBlobString(image,"false\n"); |
1321 | | /* |
1322 | | Showpage for non-EPS. |
1323 | | */ |
1324 | 0 | (void) WriteBlobString(image, LocaleCompare(image_info->magick,"PS3") == 0 ? |
1325 | 0 | "true\n" : "false\n"); |
1326 | | /* |
1327 | | Image columns, rows, and color space. |
1328 | | */ |
1329 | 0 | (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g %.20g\n%s\n", |
1330 | 0 | (double) image->columns,(double) image->rows,image->colorspace == |
1331 | 0 | CMYKColorspace ? PS3_CMYKColorspace : PS3_RGBColorspace); |
1332 | 0 | (void) WriteBlobString(image,buffer); |
1333 | | /* |
1334 | | Masked image? |
1335 | | */ |
1336 | 0 | (void) WriteBlobString(image,image->alpha_trait != UndefinedPixelTrait ? |
1337 | 0 | "true\n" : "false\n"); |
1338 | | /* |
1339 | | Render with imagemask operator? |
1340 | | */ |
1341 | 0 | option=GetImageOption(image_info,"ps3:imagemask"); |
1342 | 0 | (void) WriteBlobString(image,((option != (const char *) NULL) && |
1343 | 0 | (SetImageMonochrome(image,exception) != MagickFalse)) ? |
1344 | 0 | "true\n" : "false\n"); |
1345 | | /* |
1346 | | Output pixel data. |
1347 | | */ |
1348 | 0 | pixels=(unsigned char *) NULL; |
1349 | 0 | length=0; |
1350 | 0 | if ((image_info->type != TrueColorType) && |
1351 | 0 | (image_info->type != TrueColorAlphaType) && |
1352 | 0 | (image_info->type != ColorSeparationType) && |
1353 | 0 | (image_info->type != ColorSeparationAlphaType) && |
1354 | 0 | (image->colorspace != CMYKColorspace) && |
1355 | 0 | (is_gray != MagickFalse)) |
1356 | 0 | { |
1357 | | /* |
1358 | | Gray images. |
1359 | | */ |
1360 | 0 | (void) WriteBlobString(image,PS3_PseudoClass"\n"); |
1361 | 0 | switch (compression) |
1362 | 0 | { |
1363 | 0 | case NoCompression: |
1364 | 0 | default: |
1365 | 0 | { |
1366 | 0 | (void) WriteBlobString(image,PS3_NoCompression"\n"); |
1367 | 0 | break; |
1368 | 0 | } |
1369 | 0 | case FaxCompression: |
1370 | 0 | case Group4Compression: |
1371 | 0 | { |
1372 | 0 | (void) WriteBlobString(image,PS3_FaxCompression"\n"); |
1373 | 0 | break; |
1374 | 0 | } |
1375 | 0 | case JPEGCompression: |
1376 | 0 | { |
1377 | 0 | (void) WriteBlobString(image,PS3_JPEGCompression"\n"); |
1378 | 0 | break; |
1379 | 0 | } |
1380 | 0 | case LZWCompression: |
1381 | 0 | { |
1382 | 0 | (void) WriteBlobString(image,PS3_LZWCompression"\n"); |
1383 | 0 | break; |
1384 | 0 | } |
1385 | 0 | case RLECompression: |
1386 | 0 | { |
1387 | 0 | (void) WriteBlobString(image,PS3_RLECompression"\n"); |
1388 | 0 | break; |
1389 | 0 | } |
1390 | 0 | case ZipCompression: |
1391 | 0 | { |
1392 | 0 | (void) WriteBlobString(image,PS3_ZipCompression"\n"); |
1393 | 0 | break; |
1394 | 0 | } |
1395 | 0 | } |
1396 | | /* |
1397 | | Number of colors -- 0 for single component non-color mapped data. |
1398 | | */ |
1399 | 0 | (void) WriteBlobString(image,"0\n"); |
1400 | | /* |
1401 | | 1 bit or 8 bit components? |
1402 | | */ |
1403 | 0 | (void) FormatLocaleString(buffer,MagickPathExtent,"%d\n", |
1404 | 0 | SetImageMonochrome(image,exception) != MagickFalse ? 1 : 8); |
1405 | 0 | (void) WriteBlobString(image,buffer); |
1406 | | /* |
1407 | | Image data. |
1408 | | */ |
1409 | 0 | if (compression == JPEGCompression) |
1410 | 0 | status=InjectImageBlob(image_info,image,image,"jpeg",exception); |
1411 | 0 | else |
1412 | 0 | if ((compression == FaxCompression) || |
1413 | 0 | (compression == Group4Compression)) |
1414 | 0 | { |
1415 | 0 | if (LocaleCompare(CCITTParam,"0") == 0) |
1416 | 0 | status=HuffmanEncodeImage(image_info,image,image,exception); |
1417 | 0 | else |
1418 | 0 | status=Huffman2DEncodeImage(image_info,image,image,exception); |
1419 | 0 | } |
1420 | 0 | else |
1421 | 0 | { |
1422 | 0 | status=SerializeImageChannel(image_info,image,&pixel_info,&length, |
1423 | 0 | exception); |
1424 | 0 | if (status == MagickFalse) |
1425 | 0 | { |
1426 | 0 | (void) CloseBlob(image); |
1427 | 0 | return(MagickFalse); |
1428 | 0 | } |
1429 | 0 | pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); |
1430 | 0 | switch (compression) |
1431 | 0 | { |
1432 | 0 | case NoCompression: |
1433 | 0 | default: |
1434 | 0 | { |
1435 | 0 | Ascii85Initialize(image); |
1436 | 0 | for (i=0; i < (ssize_t) length; i++) |
1437 | 0 | Ascii85Encode(image,pixels[i]); |
1438 | 0 | Ascii85Flush(image); |
1439 | 0 | status=MagickTrue; |
1440 | 0 | break; |
1441 | 0 | } |
1442 | 0 | case LZWCompression: |
1443 | 0 | { |
1444 | 0 | status=LZWEncodeImage(image,length,pixels,exception); |
1445 | 0 | break; |
1446 | 0 | } |
1447 | 0 | case RLECompression: |
1448 | 0 | { |
1449 | 0 | status=PackbitsEncodeImage(image,length,pixels,exception); |
1450 | 0 | break; |
1451 | 0 | } |
1452 | 0 | case ZipCompression: |
1453 | 0 | { |
1454 | 0 | status=ZLIBEncodeImage(image,length,pixels,exception); |
1455 | 0 | break; |
1456 | 0 | } |
1457 | 0 | } |
1458 | 0 | pixel_info=RelinquishVirtualMemory(pixel_info); |
1459 | 0 | } |
1460 | 0 | } |
1461 | 0 | else |
1462 | 0 | if ((image->storage_class == DirectClass) || (image->colors > 256) || |
1463 | 0 | (compression == JPEGCompression)) |
1464 | 0 | { |
1465 | | /* |
1466 | | Truecolor image. |
1467 | | */ |
1468 | 0 | (void) WriteBlobString(image,PS3_DirectClass"\n"); |
1469 | 0 | switch (compression) |
1470 | 0 | { |
1471 | 0 | case NoCompression: |
1472 | 0 | default: |
1473 | 0 | { |
1474 | 0 | (void) WriteBlobString(image,PS3_NoCompression"\n"); |
1475 | 0 | break; |
1476 | 0 | } |
1477 | 0 | case RLECompression: |
1478 | 0 | { |
1479 | 0 | (void) WriteBlobString(image,PS3_RLECompression"\n"); |
1480 | 0 | break; |
1481 | 0 | } |
1482 | 0 | case JPEGCompression: |
1483 | 0 | { |
1484 | 0 | (void) WriteBlobString(image,PS3_JPEGCompression"\n"); |
1485 | 0 | break; |
1486 | 0 | } |
1487 | 0 | case LZWCompression: |
1488 | 0 | { |
1489 | 0 | (void) WriteBlobString(image,PS3_LZWCompression"\n"); |
1490 | 0 | break; |
1491 | 0 | } |
1492 | 0 | case ZipCompression: |
1493 | 0 | { |
1494 | 0 | (void) WriteBlobString(image,PS3_ZipCompression"\n"); |
1495 | 0 | break; |
1496 | 0 | } |
1497 | 0 | } |
1498 | | /* |
1499 | | Image data. |
1500 | | */ |
1501 | 0 | if (compression == JPEGCompression) |
1502 | 0 | status=InjectImageBlob(image_info,image,image,"jpeg",exception); |
1503 | 0 | else |
1504 | 0 | { |
1505 | | /* |
1506 | | Stream based compressions. |
1507 | | */ |
1508 | 0 | status=SerializeImage(image_info,image,&pixel_info,&length, |
1509 | 0 | exception); |
1510 | 0 | if (status == MagickFalse) |
1511 | 0 | { |
1512 | 0 | (void) CloseBlob(image); |
1513 | 0 | return(MagickFalse); |
1514 | 0 | } |
1515 | 0 | pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); |
1516 | 0 | switch (compression) |
1517 | 0 | { |
1518 | 0 | case NoCompression: |
1519 | 0 | default: |
1520 | 0 | { |
1521 | 0 | Ascii85Initialize(image); |
1522 | 0 | for (i=0; i < (ssize_t) length; i++) |
1523 | 0 | Ascii85Encode(image,pixels[i]); |
1524 | 0 | Ascii85Flush(image); |
1525 | 0 | status=MagickTrue; |
1526 | 0 | break; |
1527 | 0 | } |
1528 | 0 | case RLECompression: |
1529 | 0 | { |
1530 | 0 | status=PackbitsEncodeImage(image,length,pixels,exception); |
1531 | 0 | break; |
1532 | 0 | } |
1533 | 0 | case LZWCompression: |
1534 | 0 | { |
1535 | 0 | status=LZWEncodeImage(image,length,pixels,exception); |
1536 | 0 | break; |
1537 | 0 | } |
1538 | 0 | case ZipCompression: |
1539 | 0 | { |
1540 | 0 | status=ZLIBEncodeImage(image,length,pixels,exception); |
1541 | 0 | break; |
1542 | 0 | } |
1543 | 0 | } |
1544 | 0 | pixel_info=RelinquishVirtualMemory(pixel_info); |
1545 | 0 | } |
1546 | 0 | } |
1547 | 0 | else |
1548 | 0 | { |
1549 | | /* |
1550 | | Colormapped images. |
1551 | | */ |
1552 | 0 | (void) WriteBlobString(image,PS3_PseudoClass"\n"); |
1553 | 0 | switch (compression) |
1554 | 0 | { |
1555 | 0 | case NoCompression: |
1556 | 0 | default: |
1557 | 0 | { |
1558 | 0 | (void) WriteBlobString(image,PS3_NoCompression"\n"); |
1559 | 0 | break; |
1560 | 0 | } |
1561 | 0 | case RLECompression: |
1562 | 0 | { |
1563 | 0 | (void) WriteBlobString(image,PS3_RLECompression"\n"); |
1564 | 0 | break; |
1565 | 0 | } |
1566 | 0 | case LZWCompression: |
1567 | 0 | { |
1568 | 0 | (void) WriteBlobString(image,PS3_LZWCompression"\n"); |
1569 | 0 | break; |
1570 | 0 | } |
1571 | 0 | case ZipCompression: |
1572 | 0 | { |
1573 | 0 | (void) WriteBlobString(image,PS3_ZipCompression"\n"); |
1574 | 0 | break; |
1575 | 0 | } |
1576 | 0 | } |
1577 | | /* |
1578 | | Number of colors in color map. |
1579 | | */ |
1580 | 0 | (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n", |
1581 | 0 | (double) image->colors); |
1582 | 0 | (void) WriteBlobString(image,buffer); |
1583 | | /* |
1584 | | Color map - uncompressed. |
1585 | | */ |
1586 | 0 | if ((compression != NoCompression) && |
1587 | 0 | (compression != UndefinedCompression)) |
1588 | 0 | { |
1589 | 0 | for (i=0; i < (ssize_t) image->colors; i++) |
1590 | 0 | { |
1591 | 0 | pixel=ScaleQuantumToChar((Quantum) image->colormap[i].red); |
1592 | 0 | (void) WriteBlobByte(image,(unsigned char) pixel); |
1593 | 0 | pixel=ScaleQuantumToChar((Quantum) image->colormap[i].green); |
1594 | 0 | (void) WriteBlobByte(image,(unsigned char) pixel); |
1595 | 0 | pixel=ScaleQuantumToChar((Quantum) image->colormap[i].blue); |
1596 | 0 | (void) WriteBlobByte(image,(unsigned char) pixel); |
1597 | 0 | } |
1598 | 0 | } |
1599 | 0 | else |
1600 | 0 | { |
1601 | 0 | Ascii85Initialize(image); |
1602 | 0 | for (i=0; i < (ssize_t) image->colors; i++) |
1603 | 0 | { |
1604 | 0 | pixel=ScaleQuantumToChar((Quantum) image->colormap[i].red); |
1605 | 0 | Ascii85Encode(image,(unsigned char) pixel); |
1606 | 0 | pixel=ScaleQuantumToChar((Quantum) image->colormap[i].green); |
1607 | 0 | Ascii85Encode(image,(unsigned char) pixel); |
1608 | 0 | pixel=ScaleQuantumToChar((Quantum) image->colormap[i].blue); |
1609 | 0 | Ascii85Encode(image,(unsigned char) pixel); |
1610 | 0 | } |
1611 | 0 | Ascii85Flush(image); |
1612 | 0 | } |
1613 | 0 | status=SerializeImageIndexes(image_info,image,&pixel_info,&length, |
1614 | 0 | exception); |
1615 | 0 | if (status == MagickFalse) |
1616 | 0 | { |
1617 | 0 | (void) CloseBlob(image); |
1618 | 0 | return(MagickFalse); |
1619 | 0 | } |
1620 | 0 | pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); |
1621 | 0 | switch (compression) |
1622 | 0 | { |
1623 | 0 | case NoCompression: |
1624 | 0 | default: |
1625 | 0 | { |
1626 | 0 | Ascii85Initialize(image); |
1627 | 0 | for (i=0; i < (ssize_t) length; i++) |
1628 | 0 | Ascii85Encode(image,pixels[i]); |
1629 | 0 | Ascii85Flush(image); |
1630 | 0 | status=MagickTrue; |
1631 | 0 | break; |
1632 | 0 | } |
1633 | 0 | case RLECompression: |
1634 | 0 | { |
1635 | 0 | status=PackbitsEncodeImage(image,length,pixels,exception); |
1636 | 0 | break; |
1637 | 0 | } |
1638 | 0 | case LZWCompression: |
1639 | 0 | { |
1640 | 0 | status=LZWEncodeImage(image,length,pixels,exception); |
1641 | 0 | break; |
1642 | 0 | } |
1643 | 0 | case ZipCompression: |
1644 | 0 | { |
1645 | 0 | status=ZLIBEncodeImage(image,length,pixels,exception); |
1646 | 0 | break; |
1647 | 0 | } |
1648 | 0 | } |
1649 | 0 | pixel_info=RelinquishVirtualMemory(pixel_info); |
1650 | 0 | } |
1651 | 0 | (void) WriteBlobByte(image,'\n'); |
1652 | 0 | if (status == MagickFalse) |
1653 | 0 | { |
1654 | 0 | (void) CloseBlob(image); |
1655 | 0 | return(MagickFalse); |
1656 | 0 | } |
1657 | | /* |
1658 | | Update BeginData now that we know the data size. |
1659 | | */ |
1660 | 0 | length=(size_t) (TellBlob(image)-stop); |
1661 | 0 | stop=TellBlob(image); |
1662 | 0 | if (stop < 0) |
1663 | 0 | ThrowWriterException(CorruptImageError,"ImproperImageHeader"); |
1664 | 0 | offset=SeekBlob(image,start,SEEK_SET); |
1665 | 0 | if (offset < 0) |
1666 | 0 | ThrowWriterException(CorruptImageError,"ImproperImageHeader"); |
1667 | 0 | (void) FormatLocaleString(buffer,MagickPathExtent, |
1668 | 0 | "%%%%BeginData:%13ld %s Bytes\n",(long) length, |
1669 | 0 | compression == NoCompression ? "ASCII" : "BINARY"); |
1670 | 0 | (void) WriteBlobString(image,buffer); |
1671 | 0 | offset=SeekBlob(image,stop,SEEK_SET); |
1672 | 0 | (void) WriteBlobString(image,"%%EndData\n"); |
1673 | | /* |
1674 | | End private dictionary if this an EPS. |
1675 | | */ |
1676 | 0 | if (LocaleCompare(image_info->magick,"PS3") != 0) |
1677 | 0 | (void) WriteBlobString(image,"end\n"); |
1678 | 0 | (void) WriteBlobString(image,"%%PageTrailer\n"); |
1679 | 0 | if (GetNextImageInList(image) == (Image *) NULL) |
1680 | 0 | break; |
1681 | 0 | image=SyncNextImageInList(image); |
1682 | 0 | status=SetImageProgress(image,SaveImagesTag,scene++,number_scenes); |
1683 | 0 | if (status == MagickFalse) |
1684 | 0 | break; |
1685 | 0 | } while (image_info->adjoin != MagickFalse); |
1686 | 0 | (void) WriteBlobString(image,"%%Trailer\n"); |
1687 | 0 | if (page > 1) |
1688 | 0 | { |
1689 | 0 | (void) FormatLocaleString(buffer,MagickPathExtent, |
1690 | 0 | "%%%%BoundingBox: %g %g %g %g\n",ceil(bounds.x1-0.5), |
1691 | 0 | ceil(bounds.y1-0.5),floor(bounds.x2+0.5),floor(bounds.y2+0.5)); |
1692 | 0 | (void) WriteBlobString(image,buffer); |
1693 | 0 | (void) FormatLocaleString(buffer,MagickPathExtent, |
1694 | 0 | "%%%%HiResBoundingBox: %g %g %g %g\n",bounds.x1,bounds.y1,bounds.x2, |
1695 | 0 | bounds.y2); |
1696 | 0 | (void) WriteBlobString(image,buffer); |
1697 | 0 | } |
1698 | 0 | (void) WriteBlobString(image,"%%EOF\n"); |
1699 | 0 | if (CloseBlob(image) == MagickFalse) |
1700 | 0 | status=MagickFalse; |
1701 | 0 | return(status); |
1702 | 0 | } |