/src/imagemagick/coders/sun.c
Line | Count | Source |
1 | | /* |
2 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
3 | | % % |
4 | | % % |
5 | | % % |
6 | | % SSSSS U U N N % |
7 | | % SS U U NN N % |
8 | | % SSS U U N N N % |
9 | | % SS U U N NN % |
10 | | % SSSSS UUU N N % |
11 | | % % |
12 | | % % |
13 | | % Read/Write Sun Rasterfile Image Format % |
14 | | % % |
15 | | % Software Design % |
16 | | % Cristy % |
17 | | % July 1992 % |
18 | | % % |
19 | | % % |
20 | | % Copyright @ 1999 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 | | % https://imagemagick.org/license/ % |
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/colormap.h" |
50 | | #include "MagickCore/colormap-private.h" |
51 | | #include "MagickCore/colorspace.h" |
52 | | #include "MagickCore/colorspace-private.h" |
53 | | #include "MagickCore/exception.h" |
54 | | #include "MagickCore/exception-private.h" |
55 | | #include "MagickCore/image.h" |
56 | | #include "MagickCore/image-private.h" |
57 | | #include "MagickCore/list.h" |
58 | | #include "MagickCore/magick.h" |
59 | | #include "MagickCore/memory_.h" |
60 | | #include "MagickCore/monitor.h" |
61 | | #include "MagickCore/monitor-private.h" |
62 | | #include "MagickCore/pixel-accessor.h" |
63 | | #include "MagickCore/quantum-private.h" |
64 | | #include "MagickCore/static.h" |
65 | | #include "MagickCore/string_.h" |
66 | | #include "MagickCore/module.h" |
67 | | |
68 | | /* |
69 | | Forward declarations. |
70 | | */ |
71 | | static MagickBooleanType |
72 | | WriteSUNImage(const ImageInfo *,Image *,ExceptionInfo *); |
73 | | |
74 | | /* |
75 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
76 | | % % |
77 | | % % |
78 | | % % |
79 | | % I s S U N % |
80 | | % % |
81 | | % % |
82 | | % % |
83 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
84 | | % |
85 | | % IsSUN() returns MagickTrue if the image format type, identified by the |
86 | | % magick string, is SUN. |
87 | | % |
88 | | % The format of the IsSUN method is: |
89 | | % |
90 | | % MagickBooleanType IsSUN(const unsigned char *magick,const size_t length) |
91 | | % |
92 | | % A description of each parameter follows: |
93 | | % |
94 | | % o magick: compare image format pattern against these bytes. |
95 | | % |
96 | | % o length: Specifies the length of the magick string. |
97 | | % |
98 | | */ |
99 | | static MagickBooleanType IsSUN(const unsigned char *magick,const size_t length) |
100 | 0 | { |
101 | 0 | if (length < 4) |
102 | 0 | return(MagickFalse); |
103 | 0 | if (memcmp(magick,"\131\246\152\225",4) == 0) |
104 | 0 | return(MagickTrue); |
105 | 0 | return(MagickFalse); |
106 | 0 | } |
107 | | |
108 | | /* |
109 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
110 | | % % |
111 | | % % |
112 | | % % |
113 | | % D e c o d e I m a g e % |
114 | | % % |
115 | | % % |
116 | | % % |
117 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
118 | | % |
119 | | % DecodeImage unpacks the packed image pixels into runlength-encoded pixel |
120 | | % packets. |
121 | | % |
122 | | % The format of the DecodeImage method is: |
123 | | % |
124 | | % MagickBooleanType DecodeImage(const unsigned char *compressed_pixels, |
125 | | % const size_t length,unsigned char *pixels) |
126 | | % |
127 | | % A description of each parameter follows: |
128 | | % |
129 | | % o compressed_pixels: The address of a byte (8 bits) array of compressed |
130 | | % pixel data. |
131 | | % |
132 | | % o length: An integer value that is the total number of bytes of the |
133 | | % source image (as just read by ReadBlob) |
134 | | % |
135 | | % o pixels: The address of a byte (8 bits) array of pixel data created by |
136 | | % the uncompression process. The number of bytes in this array |
137 | | % must be at least equal to the number columns times the number of rows |
138 | | % of the source pixels. |
139 | | % |
140 | | */ |
141 | | static MagickBooleanType DecodeImage(const unsigned char *compressed_pixels, |
142 | | const size_t length,unsigned char *pixels,size_t extent) |
143 | 763 | { |
144 | 763 | const unsigned char |
145 | 763 | *p; |
146 | | |
147 | 763 | unsigned char |
148 | 763 | *q; |
149 | | |
150 | 763 | ssize_t |
151 | 763 | count; |
152 | | |
153 | 763 | unsigned char |
154 | 763 | byte; |
155 | | |
156 | 763 | if (IsEventLogging() != MagickFalse) |
157 | 0 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); |
158 | 763 | assert(compressed_pixels != (unsigned char *) NULL); |
159 | 763 | assert(pixels != (unsigned char *) NULL); |
160 | 763 | p=compressed_pixels; |
161 | 763 | q=pixels; |
162 | 40.0k | while (((size_t) (p-compressed_pixels) < length) && |
163 | 39.5k | ((size_t) (q-pixels) < extent)) |
164 | 39.3k | { |
165 | 39.3k | byte=(*p++); |
166 | 39.3k | if (byte != 128U) |
167 | 32.7k | *q++=byte; |
168 | 6.59k | else |
169 | 6.59k | { |
170 | | /* |
171 | | Runlength-encoded packet: <count><byte>. |
172 | | */ |
173 | 6.59k | if (((size_t) (p-compressed_pixels) >= length)) |
174 | 3 | break; |
175 | 6.59k | count=(*p++); |
176 | 6.59k | if (count > 0) |
177 | 5.71k | { |
178 | 5.71k | if (((size_t) (p-compressed_pixels) >= length)) |
179 | 2 | break; |
180 | 5.71k | byte=(*p++); |
181 | 5.71k | } |
182 | 727k | while ((count >= 0) && ((size_t) (q-pixels) < extent)) |
183 | 720k | { |
184 | 720k | *q++=byte; |
185 | 720k | count--; |
186 | 720k | } |
187 | 6.59k | } |
188 | 39.3k | } |
189 | 763 | return(((size_t) (q-pixels) == extent) ? MagickTrue : MagickFalse); |
190 | 763 | } |
191 | | |
192 | | /* |
193 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
194 | | % % |
195 | | % % |
196 | | % % |
197 | | % R e a d S U N I m a g e % |
198 | | % % |
199 | | % % |
200 | | % % |
201 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
202 | | % |
203 | | % ReadSUNImage() reads a SUN image file and returns it. It allocates |
204 | | % the memory necessary for the new Image structure and returns a pointer to |
205 | | % the new image. |
206 | | % |
207 | | % The format of the ReadSUNImage method is: |
208 | | % |
209 | | % Image *ReadSUNImage(const ImageInfo *image_info,ExceptionInfo *exception) |
210 | | % |
211 | | % A description of each parameter follows: |
212 | | % |
213 | | % o image_info: the image info. |
214 | | % |
215 | | % o exception: return any errors or warnings in this structure. |
216 | | % |
217 | | */ |
218 | | static Image *ReadSUNImage(const ImageInfo *image_info,ExceptionInfo *exception) |
219 | 1.58k | { |
220 | 3.61k | #define RMT_EQUAL_RGB 1 |
221 | 8.40k | #define RMT_NONE 0 |
222 | 1.58k | #define RMT_RAW 2 |
223 | 22.1k | #define RT_STANDARD 1 |
224 | 7.50k | #define RT_ENCODED 2 |
225 | 1.58k | #define RT_FORMAT_RGB 3 |
226 | | |
227 | 1.58k | typedef struct _SUNInfo |
228 | 1.58k | { |
229 | 1.58k | unsigned int |
230 | 1.58k | magic, |
231 | 1.58k | width, |
232 | 1.58k | height, |
233 | 1.58k | depth, |
234 | 1.58k | length, |
235 | 1.58k | type, |
236 | 1.58k | maptype, |
237 | 1.58k | maplength; |
238 | 1.58k | } SUNInfo; |
239 | | |
240 | 1.58k | Image |
241 | 1.58k | *image; |
242 | | |
243 | 1.58k | int |
244 | 1.58k | bit; |
245 | | |
246 | 1.58k | MagickBooleanType |
247 | 1.58k | status; |
248 | | |
249 | 1.58k | MagickSizeType |
250 | 1.58k | number_pixels; |
251 | | |
252 | 1.58k | Quantum |
253 | 1.58k | *q; |
254 | | |
255 | 1.58k | ssize_t |
256 | 1.58k | i, |
257 | 1.58k | x; |
258 | | |
259 | 1.58k | unsigned char |
260 | 1.58k | *p; |
261 | | |
262 | 1.58k | size_t |
263 | 1.58k | bytes_per_line, |
264 | 1.58k | extent, |
265 | 1.58k | height, |
266 | 1.58k | pixels_length, |
267 | 1.58k | quantum; |
268 | | |
269 | 1.58k | ssize_t |
270 | 1.58k | count, |
271 | 1.58k | y; |
272 | | |
273 | 1.58k | SUNInfo |
274 | 1.58k | sun_info; |
275 | | |
276 | 1.58k | unsigned char |
277 | 1.58k | *sun_data, |
278 | 1.58k | *sun_pixels; |
279 | | |
280 | | /* |
281 | | Open image file. |
282 | | */ |
283 | 1.58k | assert(image_info != (const ImageInfo *) NULL); |
284 | 1.58k | assert(image_info->signature == MagickCoreSignature); |
285 | 1.58k | assert(exception != (ExceptionInfo *) NULL); |
286 | 1.58k | assert(exception->signature == MagickCoreSignature); |
287 | 1.58k | if (IsEventLogging() != MagickFalse) |
288 | 0 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", |
289 | 0 | image_info->filename); |
290 | 1.58k | image=AcquireImage(image_info,exception); |
291 | 1.58k | status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); |
292 | 1.58k | if (status == MagickFalse) |
293 | 0 | { |
294 | 0 | image=DestroyImageList(image); |
295 | 0 | return((Image *) NULL); |
296 | 0 | } |
297 | | /* |
298 | | Read SUN raster header. |
299 | | */ |
300 | 1.58k | (void) memset(&sun_info,0,sizeof(sun_info)); |
301 | 1.58k | sun_info.magic=ReadBlobMSBLong(image); |
302 | 1.58k | do |
303 | 2.84k | { |
304 | | /* |
305 | | Verify SUN identifier. |
306 | | */ |
307 | 2.84k | if (sun_info.magic != 0x59a66a95) |
308 | 2.79k | ThrowReaderException(CorruptImageError,"ImproperImageHeader"); |
309 | 2.79k | sun_info.width=ReadBlobMSBLong(image); |
310 | 2.79k | sun_info.height=ReadBlobMSBLong(image); |
311 | 2.79k | sun_info.depth=ReadBlobMSBLong(image); |
312 | 2.79k | sun_info.length=ReadBlobMSBLong(image); |
313 | 2.79k | sun_info.type=ReadBlobMSBLong(image); |
314 | 2.79k | sun_info.maptype=ReadBlobMSBLong(image); |
315 | 2.79k | sun_info.maplength=ReadBlobMSBLong(image); |
316 | 2.79k | if (EOFBlob(image) != MagickFalse) |
317 | 2.72k | ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile"); |
318 | 2.72k | if (sun_info.maplength > GetBlobSize(image)) |
319 | 2.68k | ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile"); |
320 | 2.68k | if (HeapOverflowSanityCheckGetSize(sun_info.width,sun_info.height,&extent) != MagickFalse) |
321 | 2.67k | ThrowReaderException(CorruptImageError,"ImproperImageHeader"); |
322 | 2.67k | if ((sun_info.type != RT_STANDARD) && (sun_info.type != RT_ENCODED) && |
323 | 269 | (sun_info.type != RT_FORMAT_RGB)) |
324 | 2.57k | ThrowReaderException(CorruptImageError,"ImproperImageHeader"); |
325 | 2.57k | if ((sun_info.maptype == RMT_NONE) && (sun_info.maplength != 0)) |
326 | 2.56k | ThrowReaderException(CorruptImageError,"ImproperImageHeader"); |
327 | 2.56k | if ((sun_info.depth != 1) && (sun_info.depth != 8) && |
328 | 472 | (sun_info.depth != 24) && (sun_info.depth != 32)) |
329 | 2.48k | ThrowReaderException(CorruptImageError,"ImproperImageHeader"); |
330 | 2.48k | if ((sun_info.maptype != RMT_NONE) && (sun_info.maptype != RMT_EQUAL_RGB) && |
331 | 811 | (sun_info.maptype != RMT_RAW)) |
332 | 2.42k | ThrowReaderException(CoderError,"ColormapTypeNotSupported"); |
333 | 2.42k | image->columns=sun_info.width; |
334 | 2.42k | image->rows=sun_info.height; |
335 | 2.42k | image->depth=sun_info.depth <= 8 ? sun_info.depth : |
336 | 2.42k | MAGICKCORE_QUANTUM_DEPTH; |
337 | 2.42k | if (sun_info.depth < 24) |
338 | 2.04k | { |
339 | 2.04k | size_t |
340 | 2.04k | one; |
341 | | |
342 | 2.04k | image->colors=sun_info.maplength; |
343 | 2.04k | one=1; |
344 | 2.04k | if (sun_info.maptype == RMT_NONE) |
345 | 929 | image->colors=one << sun_info.depth; |
346 | 2.04k | if (sun_info.maptype == RMT_EQUAL_RGB) |
347 | 376 | image->colors=sun_info.maplength/3; |
348 | 2.04k | if (image->colors == 0) |
349 | 2.04k | ThrowReaderException(CorruptImageError,"ImproperImageHeader"); |
350 | 2.04k | if (AcquireImageColormap(image,image->colors,exception) == MagickFalse) |
351 | 2.04k | ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); |
352 | 2.04k | } |
353 | 2.42k | switch (sun_info.maptype) |
354 | 2.42k | { |
355 | 1.29k | case RMT_NONE: |
356 | 1.29k | break; |
357 | 377 | case RMT_EQUAL_RGB: |
358 | 377 | { |
359 | 377 | unsigned char |
360 | 377 | *sun_colormap; |
361 | | |
362 | | /* |
363 | | Read SUN raster colormap. |
364 | | */ |
365 | 377 | sun_colormap=(unsigned char *) AcquireQuantumMemory(image->colors, |
366 | 377 | sizeof(*sun_colormap)); |
367 | 377 | if (sun_colormap == (unsigned char *) NULL) |
368 | 373 | ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); |
369 | 373 | count=ReadBlob(image,image->colors,sun_colormap); |
370 | 373 | if (count != (ssize_t) image->colors) |
371 | 15 | { |
372 | 15 | sun_colormap=(unsigned char *) RelinquishMagickMemory(sun_colormap); |
373 | 15 | ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile"); |
374 | 0 | } |
375 | 12.3k | for (i=0; i < (ssize_t) image->colors; i++) |
376 | 12.0k | image->colormap[i].red=(MagickRealType) ScaleCharToQuantum( |
377 | 12.0k | sun_colormap[i]); |
378 | 358 | count=ReadBlob(image,image->colors,sun_colormap); |
379 | 358 | if (count != (ssize_t) image->colors) |
380 | 21 | { |
381 | 21 | sun_colormap=(unsigned char *) RelinquishMagickMemory(sun_colormap); |
382 | 21 | ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile"); |
383 | 0 | } |
384 | 11.8k | for (i=0; i < (ssize_t) image->colors; i++) |
385 | 11.5k | image->colormap[i].green=(MagickRealType) ScaleCharToQuantum( |
386 | 11.5k | sun_colormap[i]); |
387 | 337 | count=ReadBlob(image,image->colors,sun_colormap); |
388 | 337 | if (count != (ssize_t) image->colors) |
389 | 29 | { |
390 | 29 | sun_colormap=(unsigned char *) RelinquishMagickMemory(sun_colormap); |
391 | 29 | ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile"); |
392 | 0 | } |
393 | 9.19k | for (i=0; i < (ssize_t) image->colors; i++) |
394 | 8.88k | image->colormap[i].blue=(MagickRealType) ScaleCharToQuantum( |
395 | 8.88k | sun_colormap[i]); |
396 | 308 | sun_colormap=(unsigned char *) RelinquishMagickMemory(sun_colormap); |
397 | 308 | break; |
398 | 337 | } |
399 | 749 | case RMT_RAW: |
400 | 749 | { |
401 | 749 | unsigned char |
402 | 749 | *sun_colormap; |
403 | | |
404 | | /* |
405 | | Read SUN raster colormap. |
406 | | */ |
407 | 749 | sun_colormap=(unsigned char *) AcquireQuantumMemory(sun_info.maplength, |
408 | 749 | sizeof(*sun_colormap)); |
409 | 749 | if (sun_colormap == (unsigned char *) NULL) |
410 | 747 | ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); |
411 | 747 | count=ReadBlob(image,sun_info.maplength,sun_colormap); |
412 | 747 | sun_colormap=(unsigned char *) RelinquishMagickMemory(sun_colormap); |
413 | 747 | if (count != (ssize_t) sun_info.maplength) |
414 | 705 | ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile"); |
415 | 705 | break; |
416 | 747 | } |
417 | 0 | default: |
418 | 0 | ThrowReaderException(CoderError,"ColormapTypeNotSupported"); |
419 | 2.42k | } |
420 | 2.31k | image->alpha_trait=sun_info.depth == 32 ? BlendPixelTrait : |
421 | 2.31k | UndefinedPixelTrait; |
422 | 2.31k | image->columns=sun_info.width; |
423 | 2.31k | image->rows=sun_info.height; |
424 | 2.31k | if (image_info->ping != MagickFalse) |
425 | 6 | { |
426 | 6 | (void) CloseBlob(image); |
427 | 6 | return(GetFirstImageInList(image)); |
428 | 6 | } |
429 | 2.30k | status=SetImageExtent(image,image->columns,image->rows,exception); |
430 | 2.30k | if (status == MagickFalse) |
431 | 129 | return(DestroyImageList(image)); |
432 | 2.17k | if (sun_info.length == 0) |
433 | 2.17k | ThrowReaderException(ResourceLimitError,"ImproperImageHeader"); |
434 | 2.17k | number_pixels=(MagickSizeType) (image->columns*image->rows); |
435 | 2.17k | if ((sun_info.type != RT_ENCODED) && |
436 | 1.38k | ((number_pixels*sun_info.depth) > (8UL*sun_info.length))) |
437 | 2.13k | ThrowReaderException(CorruptImageError,"ImproperImageHeader"); |
438 | 2.13k | if (HeapOverflowSanityCheckGetSize(sun_info.width,sun_info.depth,&bytes_per_line) != MagickFalse) |
439 | 2.13k | ThrowReaderException(CorruptImageError,"ImproperImageHeader"); |
440 | 2.13k | if (sun_info.length > GetBlobSize(image)) |
441 | 2.07k | ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile"); |
442 | 2.07k | sun_data=(unsigned char *) AcquireQuantumMemory(sun_info.length, |
443 | 2.07k | sizeof(*sun_data)); |
444 | 2.07k | if (sun_data == (unsigned char *) NULL) |
445 | 2.07k | ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); |
446 | 2.07k | (void) memset(sun_data,0,sun_info.length*sizeof(*sun_data)); |
447 | 2.07k | count=(ssize_t) ReadBlob(image,sun_info.length,sun_data); |
448 | 2.07k | if ((sun_info.type != RT_ENCODED) && (count != (ssize_t) sun_info.length)) |
449 | 29 | { |
450 | 29 | sun_data=(unsigned char *) RelinquishMagickMemory(sun_data); |
451 | 29 | ThrowReaderException(CorruptImageError,"UnableToReadImageData"); |
452 | 0 | } |
453 | 2.04k | height=sun_info.height; |
454 | 2.04k | if ((height == 0) || (sun_info.width == 0) || (sun_info.depth == 0) || |
455 | 2.04k | ((bytes_per_line/sun_info.depth) != sun_info.width)) |
456 | 0 | { |
457 | 0 | sun_data=(unsigned char *) RelinquishMagickMemory(sun_data); |
458 | 0 | ThrowReaderException(ResourceLimitError,"ImproperImageHeader"); |
459 | 0 | } |
460 | 2.04k | quantum=sun_info.depth == 1 ? 15 : 7; |
461 | 2.04k | bytes_per_line+=quantum; |
462 | 2.04k | bytes_per_line<<=1; |
463 | 2.04k | if ((bytes_per_line >> 1) != ((size_t) sun_info.width*sun_info.depth+quantum)) |
464 | 0 | { |
465 | 0 | sun_data=(unsigned char *) RelinquishMagickMemory(sun_data); |
466 | 0 | ThrowReaderException(ResourceLimitError,"ImproperImageHeader"); |
467 | 0 | } |
468 | 2.04k | bytes_per_line>>=4; |
469 | 2.04k | if (HeapOverflowSanityCheckGetSize(height,bytes_per_line,&pixels_length) != MagickFalse) |
470 | 0 | { |
471 | 0 | sun_data=(unsigned char *) RelinquishMagickMemory(sun_data); |
472 | 0 | ThrowReaderException(ResourceLimitError,"ImproperImageHeader"); |
473 | 0 | } |
474 | 2.04k | if (image->rows > (MAGICK_SIZE_MAX-pixels_length)) |
475 | 0 | { |
476 | 0 | sun_data=(unsigned char *) RelinquishMagickMemory(sun_data); |
477 | 0 | ThrowReaderException(ResourceLimitError,"ImproperImageHeader"); |
478 | 0 | } |
479 | 2.04k | sun_pixels=(unsigned char *) AcquireQuantumMemory(pixels_length+image->rows, |
480 | 2.04k | sizeof(*sun_pixels)); |
481 | 2.04k | if (sun_pixels == (unsigned char *) NULL) |
482 | 0 | { |
483 | 0 | sun_data=(unsigned char *) RelinquishMagickMemory(sun_data); |
484 | 0 | ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); |
485 | 0 | } |
486 | 2.04k | (void) memset(sun_pixels,0,(pixels_length+image->rows)*sizeof(*sun_pixels)); |
487 | 2.04k | if (sun_info.type == RT_ENCODED) |
488 | 763 | { |
489 | 763 | status=DecodeImage(sun_data,sun_info.length,sun_pixels,pixels_length); |
490 | 763 | if (status == MagickFalse) |
491 | 97 | { |
492 | 97 | sun_data=(unsigned char *) RelinquishMagickMemory(sun_data); |
493 | 97 | sun_pixels=(unsigned char *) RelinquishMagickMemory(sun_pixels); |
494 | 97 | ThrowReaderException(CorruptImageError,"UnableToReadImageData"); |
495 | 0 | } |
496 | 763 | } |
497 | 1.28k | else |
498 | 1.28k | { |
499 | 1.28k | if (sun_info.length > (pixels_length+image->rows)) |
500 | 2 | { |
501 | 2 | sun_data=(unsigned char *) RelinquishMagickMemory(sun_data); |
502 | 2 | sun_pixels=(unsigned char *) RelinquishMagickMemory(sun_pixels); |
503 | 2 | ThrowReaderException(ResourceLimitError,"ImproperImageHeader"); |
504 | 0 | } |
505 | 1.27k | (void) memcpy(sun_pixels,sun_data,sun_info.length); |
506 | 1.27k | } |
507 | 1.94k | sun_data=(unsigned char *) RelinquishMagickMemory(sun_data); |
508 | | /* |
509 | | Convert SUN raster image to pixel packets. |
510 | | */ |
511 | 1.94k | p=sun_pixels; |
512 | 1.94k | if (sun_info.depth == 1) |
513 | 21.6k | for (y=0; y < (ssize_t) image->rows; y++) |
514 | 20.4k | { |
515 | 20.4k | q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); |
516 | 20.4k | if (q == (Quantum *) NULL) |
517 | 0 | break; |
518 | 612k | for (x=0; x < ((ssize_t) image->columns-7); x+=8) |
519 | 591k | { |
520 | 5.32M | for (bit=7; bit >= 0; bit--) |
521 | 4.73M | { |
522 | 4.73M | SetPixelIndex(image,(Quantum) ((*p) & (0x01 << bit) ? 0x00 : 0x01), |
523 | 4.73M | q); |
524 | 4.73M | q+=(ptrdiff_t) GetPixelChannels(image); |
525 | 4.73M | } |
526 | 591k | p++; |
527 | 591k | } |
528 | 20.4k | if ((image->columns % 8) != 0) |
529 | 18.3k | { |
530 | 57.6k | for (bit=7; bit >= (int) (8-(image->columns % 8)); bit--) |
531 | 39.3k | { |
532 | 39.3k | SetPixelIndex(image,(Quantum) ((*p) & (0x01 << bit) ? 0x00 : |
533 | 39.3k | 0x01),q); |
534 | 39.3k | q+=(ptrdiff_t) GetPixelChannels(image); |
535 | 39.3k | } |
536 | 18.3k | p++; |
537 | 18.3k | } |
538 | 20.4k | if ((((image->columns/8)+(image->columns % 8 ? 1 : 0)) % 2) != 0) |
539 | 17.1k | p++; |
540 | 20.4k | if (SyncAuthenticPixels(image,exception) == MagickFalse) |
541 | 0 | break; |
542 | 20.4k | if (image->previous == (Image *) NULL) |
543 | 19.1k | { |
544 | 19.1k | status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, |
545 | 19.1k | image->rows); |
546 | 19.1k | if (status == MagickFalse) |
547 | 0 | break; |
548 | 19.1k | } |
549 | 20.4k | } |
550 | 805 | else |
551 | 805 | if (image->storage_class == PseudoClass) |
552 | 551 | { |
553 | 27.6k | for (y=0; y < (ssize_t) image->rows; y++) |
554 | 27.1k | { |
555 | 27.1k | q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); |
556 | 27.1k | if (q == (Quantum *) NULL) |
557 | 0 | break; |
558 | 66.7k | for (x=0; x < (ssize_t) image->columns; x++) |
559 | 39.6k | { |
560 | 39.6k | SetPixelIndex(image,(Quantum) |
561 | 39.6k | ConstrainColormapIndex(image,*p,exception),q); |
562 | 39.6k | p++; |
563 | 39.6k | q+=(ptrdiff_t) GetPixelChannels(image); |
564 | 39.6k | } |
565 | 27.1k | if ((image->columns % 2) != 0) |
566 | 26.1k | p++; |
567 | 27.1k | if (SyncAuthenticPixels(image,exception) == MagickFalse) |
568 | 0 | break; |
569 | 27.1k | if (image->previous == (Image *) NULL) |
570 | 26.5k | { |
571 | 26.5k | status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, |
572 | 26.5k | image->rows); |
573 | 26.5k | if (status == MagickFalse) |
574 | 0 | break; |
575 | 26.5k | } |
576 | 27.1k | } |
577 | 551 | } |
578 | 254 | else |
579 | 254 | { |
580 | 254 | size_t |
581 | 254 | bytes_per_pixel; |
582 | | |
583 | 254 | bytes_per_pixel=3; |
584 | 254 | if (image->alpha_trait != UndefinedPixelTrait) |
585 | 126 | bytes_per_pixel++; |
586 | 254 | if (bytes_per_line == 0) |
587 | 0 | bytes_per_line=bytes_per_pixel*image->columns; |
588 | 12.5k | for (y=0; y < (ssize_t) image->rows; y++) |
589 | 12.2k | { |
590 | 12.2k | q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); |
591 | 12.2k | if (q == (Quantum *) NULL) |
592 | 0 | break; |
593 | 31.7k | for (x=0; x < (ssize_t) image->columns; x++) |
594 | 19.4k | { |
595 | 19.4k | if (image->alpha_trait != UndefinedPixelTrait) |
596 | 3.17k | SetPixelAlpha(image,ScaleCharToQuantum(*p++),q); |
597 | 19.4k | if (sun_info.type == RT_STANDARD) |
598 | 198 | { |
599 | 198 | SetPixelBlue(image,ScaleCharToQuantum(*p++),q); |
600 | 198 | SetPixelGreen(image,ScaleCharToQuantum(*p++),q); |
601 | 198 | SetPixelRed(image,ScaleCharToQuantum(*p++),q); |
602 | 198 | } |
603 | 19.2k | else |
604 | 19.2k | { |
605 | 19.2k | SetPixelRed(image,ScaleCharToQuantum(*p++),q); |
606 | 19.2k | SetPixelGreen(image,ScaleCharToQuantum(*p++),q); |
607 | 19.2k | SetPixelBlue(image,ScaleCharToQuantum(*p++),q); |
608 | 19.2k | } |
609 | 19.4k | if (image->colors != 0) |
610 | 0 | { |
611 | 0 | SetPixelRed(image,ClampToQuantum(image->colormap[(ssize_t) |
612 | 0 | GetPixelRed(image,q)].red),q); |
613 | 0 | SetPixelGreen(image,ClampToQuantum(image->colormap[(ssize_t) |
614 | 0 | GetPixelGreen(image,q)].green),q); |
615 | 0 | SetPixelBlue(image,ClampToQuantum(image->colormap[(ssize_t) |
616 | 0 | GetPixelBlue(image,q)].blue),q); |
617 | 0 | } |
618 | 19.4k | q+=(ptrdiff_t) GetPixelChannels(image); |
619 | 19.4k | } |
620 | 12.2k | if (((bytes_per_pixel*image->columns) % 2) != 0) |
621 | 8.51k | p++; |
622 | 12.2k | if (SyncAuthenticPixels(image,exception) == MagickFalse) |
623 | 0 | break; |
624 | 12.2k | if (image->previous == (Image *) NULL) |
625 | 10.7k | { |
626 | 10.7k | status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, |
627 | 10.7k | image->rows); |
628 | 10.7k | if (status == MagickFalse) |
629 | 0 | break; |
630 | 10.7k | } |
631 | 12.2k | } |
632 | 254 | } |
633 | 1.94k | if (image->storage_class == PseudoClass) |
634 | 1.69k | (void) SyncImage(image,exception); |
635 | 1.94k | sun_pixels=(unsigned char *) RelinquishMagickMemory(sun_pixels); |
636 | 1.94k | if (EOFBlob(image) != MagickFalse) |
637 | 213 | { |
638 | 213 | ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", |
639 | 213 | image->filename); |
640 | 213 | break; |
641 | 213 | } |
642 | | /* |
643 | | Proceed to next image. |
644 | | */ |
645 | 1.73k | if (image_info->number_scenes != 0) |
646 | 0 | if (image->scene >= (image_info->scene+image_info->number_scenes-1)) |
647 | 0 | break; |
648 | 1.73k | sun_info.magic=ReadBlobMSBLong(image); |
649 | 1.73k | if (sun_info.magic == 0x59a66a95) |
650 | 1.26k | { |
651 | | /* |
652 | | Allocate next image structure. |
653 | | */ |
654 | 1.26k | AcquireNextImage(image_info,image,exception); |
655 | 1.26k | if (GetNextImageInList(image) == (Image *) NULL) |
656 | 0 | { |
657 | 0 | status=MagickFalse; |
658 | 0 | break; |
659 | 0 | } |
660 | 1.26k | image=SyncNextImageInList(image); |
661 | 1.26k | status=SetImageProgress(image,LoadImagesTag,TellBlob(image), |
662 | 1.26k | GetBlobSize(image)); |
663 | 1.26k | if (status == MagickFalse) |
664 | 0 | break; |
665 | 1.26k | } |
666 | 1.73k | } while (sun_info.magic == 0x59a66a95); |
667 | 681 | if (CloseBlob(image) == MagickFalse) |
668 | 0 | status=MagickFalse; |
669 | 681 | if (status == MagickFalse) |
670 | 0 | return(DestroyImageList(image)); |
671 | 681 | return(GetFirstImageInList(image)); |
672 | 681 | } |
673 | | |
674 | | /* |
675 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
676 | | % % |
677 | | % % |
678 | | % % |
679 | | % R e g i s t e r S U N I m a g e % |
680 | | % % |
681 | | % % |
682 | | % % |
683 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
684 | | % |
685 | | % RegisterSUNImage() adds attributes for the SUN image format to |
686 | | % the list of supported formats. The attributes include the image format |
687 | | % tag, a method to read and/or write the format, whether the format |
688 | | % supports the saving of more than one frame to the same file or blob, |
689 | | % whether the format supports native in-memory I/O, and a brief |
690 | | % description of the format. |
691 | | % |
692 | | % The format of the RegisterSUNImage method is: |
693 | | % |
694 | | % size_t RegisterSUNImage(void) |
695 | | % |
696 | | */ |
697 | | ModuleExport size_t RegisterSUNImage(void) |
698 | 11 | { |
699 | 11 | MagickInfo |
700 | 11 | *entry; |
701 | | |
702 | 11 | entry=AcquireMagickInfo("SUN","RAS","SUN Rasterfile"); |
703 | 11 | entry->decoder=(DecodeImageHandler *) ReadSUNImage; |
704 | 11 | entry->encoder=(EncodeImageHandler *) WriteSUNImage; |
705 | 11 | entry->magick=(IsImageFormatHandler *) IsSUN; |
706 | 11 | entry->flags|=CoderDecoderSeekableStreamFlag; |
707 | 11 | (void) RegisterMagickInfo(entry); |
708 | 11 | entry=AcquireMagickInfo("SUN","SUN","SUN Rasterfile"); |
709 | 11 | entry->decoder=(DecodeImageHandler *) ReadSUNImage; |
710 | 11 | entry->encoder=(EncodeImageHandler *) WriteSUNImage; |
711 | 11 | entry->flags|=CoderDecoderSeekableStreamFlag; |
712 | 11 | (void) RegisterMagickInfo(entry); |
713 | 11 | return(MagickImageCoderSignature); |
714 | 11 | } |
715 | | |
716 | | /* |
717 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
718 | | % % |
719 | | % % |
720 | | % % |
721 | | % U n r e g i s t e r S U N I m a g e % |
722 | | % % |
723 | | % % |
724 | | % % |
725 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
726 | | % |
727 | | % UnregisterSUNImage() removes format registrations made by the |
728 | | % SUN module from the list of supported formats. |
729 | | % |
730 | | % The format of the UnregisterSUNImage method is: |
731 | | % |
732 | | % UnregisterSUNImage(void) |
733 | | % |
734 | | */ |
735 | | ModuleExport void UnregisterSUNImage(void) |
736 | 0 | { |
737 | 0 | (void) UnregisterMagickInfo("RAS"); |
738 | 0 | (void) UnregisterMagickInfo("SUN"); |
739 | 0 | } |
740 | | |
741 | | /* |
742 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
743 | | % % |
744 | | % % |
745 | | % % |
746 | | % W r i t e S U N I m a g e % |
747 | | % % |
748 | | % % |
749 | | % % |
750 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
751 | | % |
752 | | % WriteSUNImage() writes an image in the SUN rasterfile format. |
753 | | % |
754 | | % The format of the WriteSUNImage method is: |
755 | | % |
756 | | % MagickBooleanType WriteSUNImage(const ImageInfo *image_info, |
757 | | % Image *image,ExceptionInfo *exception) |
758 | | % |
759 | | % A description of each parameter follows. |
760 | | % |
761 | | % o image_info: the image info. |
762 | | % |
763 | | % o image: The image. |
764 | | % |
765 | | % o exception: return any errors or warnings in this structure. |
766 | | % |
767 | | */ |
768 | | static MagickBooleanType WriteSUNImage(const ImageInfo *image_info,Image *image, |
769 | | ExceptionInfo *exception) |
770 | 414 | { |
771 | 414 | #define RMT_EQUAL_RGB 1 |
772 | 414 | #define RMT_NONE 0 |
773 | 414 | #define RMT_RAW 2 |
774 | 414 | #define RT_STANDARD 1 |
775 | 414 | #define RT_FORMAT_RGB 3 |
776 | | |
777 | 414 | typedef struct _SUNInfo |
778 | 414 | { |
779 | 414 | unsigned int |
780 | 414 | magic, |
781 | 414 | width, |
782 | 414 | height, |
783 | 414 | depth, |
784 | 414 | length, |
785 | 414 | type, |
786 | 414 | maptype, |
787 | 414 | maplength; |
788 | 414 | } SUNInfo; |
789 | | |
790 | 414 | const Quantum |
791 | 414 | *p; |
792 | | |
793 | 414 | MagickBooleanType |
794 | 414 | status; |
795 | | |
796 | 414 | MagickOffsetType |
797 | 414 | scene; |
798 | | |
799 | 414 | MagickSizeType |
800 | 414 | number_pixels; |
801 | | |
802 | 414 | size_t |
803 | 414 | number_scenes; |
804 | | |
805 | 414 | ssize_t |
806 | 414 | i, |
807 | 414 | x, |
808 | 414 | y; |
809 | | |
810 | 414 | SUNInfo |
811 | 414 | sun_info; |
812 | | |
813 | | /* |
814 | | Open output image file. |
815 | | */ |
816 | 414 | assert(image_info != (const ImageInfo *) NULL); |
817 | 414 | assert(image_info->signature == MagickCoreSignature); |
818 | 414 | assert(image != (Image *) NULL); |
819 | 414 | assert(image->signature == MagickCoreSignature); |
820 | 414 | assert(exception != (ExceptionInfo *) NULL); |
821 | 414 | assert(exception->signature == MagickCoreSignature); |
822 | 414 | if (IsEventLogging() != MagickFalse) |
823 | 0 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); |
824 | 414 | status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); |
825 | 414 | if (status == MagickFalse) |
826 | 0 | return(status); |
827 | 414 | scene=0; |
828 | 414 | number_scenes=GetImageListLength(image); |
829 | 414 | do |
830 | 414 | { |
831 | | /* |
832 | | Initialize SUN raster file header. |
833 | | */ |
834 | 414 | if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse) |
835 | 0 | (void) TransformImageColorspace(image,sRGBColorspace,exception); |
836 | 414 | sun_info.magic=0x59a66a95; |
837 | 414 | if ((image->columns != (unsigned int) image->columns) || |
838 | 414 | (image->rows != (unsigned int) image->rows)) |
839 | 414 | ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit"); |
840 | 414 | sun_info.width=(unsigned int) image->columns; |
841 | 414 | sun_info.height=(unsigned int) image->rows; |
842 | 414 | sun_info.type=(unsigned int) |
843 | 414 | (image->storage_class == DirectClass ? RT_FORMAT_RGB : RT_STANDARD); |
844 | 414 | sun_info.maptype=RMT_NONE; |
845 | 414 | sun_info.maplength=0; |
846 | 414 | number_pixels=(MagickSizeType) image->columns*image->rows; |
847 | 414 | if ((HeapOverflowSanityCheck(image->columns,image->rows) != MagickFalse) || |
848 | 414 | (number_pixels > (MAGICK_SSIZE_MAX/4))) |
849 | 414 | ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); |
850 | 414 | if (image->storage_class == DirectClass) |
851 | 67 | { |
852 | | /* |
853 | | Full color SUN raster. |
854 | | */ |
855 | 67 | sun_info.depth=(unsigned int) image->alpha_trait != |
856 | 67 | UndefinedPixelTrait ? 32U : 24U; |
857 | 67 | sun_info.length=(unsigned int) ((image->alpha_trait != |
858 | 67 | UndefinedPixelTrait ? 4 : 3)*number_pixels); |
859 | 67 | sun_info.length+=sun_info.length & 0x01 ? (unsigned int) image->rows : |
860 | 67 | 0; |
861 | 67 | } |
862 | 347 | else |
863 | 347 | if (SetImageMonochrome(image,exception) != MagickFalse) |
864 | 228 | { |
865 | | /* |
866 | | Monochrome SUN raster. |
867 | | */ |
868 | 228 | sun_info.depth=1; |
869 | 228 | sun_info.length=(unsigned int) (((image->columns+7) >> 3)* |
870 | 228 | image->rows); |
871 | 228 | sun_info.length+=(unsigned int) (((image->columns/8)+(image->columns % |
872 | 228 | 8 ? 1 : 0)) % 2 ? image->rows : 0); |
873 | 228 | } |
874 | 119 | else |
875 | 119 | { |
876 | | /* |
877 | | Colormapped SUN raster. |
878 | | */ |
879 | 119 | sun_info.depth=8; |
880 | 119 | sun_info.length=(unsigned int) number_pixels; |
881 | 119 | sun_info.length+=(unsigned int) (image->columns & 0x01 ? image->rows : |
882 | 119 | 0); |
883 | 119 | sun_info.maptype=RMT_EQUAL_RGB; |
884 | 119 | sun_info.maplength=(unsigned int) (3*image->colors); |
885 | 119 | } |
886 | | /* |
887 | | Write SUN header. |
888 | | */ |
889 | 414 | (void) WriteBlobMSBLong(image,sun_info.magic); |
890 | 414 | (void) WriteBlobMSBLong(image,sun_info.width); |
891 | 414 | (void) WriteBlobMSBLong(image,sun_info.height); |
892 | 414 | (void) WriteBlobMSBLong(image,sun_info.depth); |
893 | 414 | (void) WriteBlobMSBLong(image,sun_info.length); |
894 | 414 | (void) WriteBlobMSBLong(image,sun_info.type); |
895 | 414 | (void) WriteBlobMSBLong(image,sun_info.maptype); |
896 | 414 | (void) WriteBlobMSBLong(image,sun_info.maplength); |
897 | | /* |
898 | | Convert MIFF to SUN raster pixels. |
899 | | */ |
900 | 414 | x=0; |
901 | 414 | y=0; |
902 | 414 | if (image->storage_class == DirectClass) |
903 | 67 | { |
904 | 67 | unsigned char |
905 | 67 | *q; |
906 | | |
907 | 67 | size_t |
908 | 67 | bytes_per_pixel, |
909 | 67 | length; |
910 | | |
911 | 67 | unsigned char |
912 | 67 | *pixels; |
913 | | |
914 | | /* |
915 | | Allocate memory for pixels. |
916 | | */ |
917 | 67 | bytes_per_pixel=3; |
918 | 67 | if (image->alpha_trait != UndefinedPixelTrait) |
919 | 33 | bytes_per_pixel++; |
920 | 67 | length=image->columns; |
921 | 67 | pixels=(unsigned char *) AcquireQuantumMemory(length,4*sizeof(*pixels)); |
922 | 67 | if (pixels == (unsigned char *) NULL) |
923 | 67 | ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); |
924 | | /* |
925 | | Convert DirectClass packet to SUN RGB pixel. |
926 | | */ |
927 | 9.25k | for (y=0; y < (ssize_t) image->rows; y++) |
928 | 9.19k | { |
929 | 9.19k | p=GetVirtualPixels(image,0,y,image->columns,1,exception); |
930 | 9.19k | if (p == (const Quantum *) NULL) |
931 | 0 | break; |
932 | 9.19k | q=pixels; |
933 | 24.0k | for (x=0; x < (ssize_t) image->columns; x++) |
934 | 14.8k | { |
935 | 14.8k | if (image->alpha_trait != UndefinedPixelTrait) |
936 | 1.33k | *q++=ScaleQuantumToChar(GetPixelAlpha(image,p)); |
937 | 14.8k | *q++=ScaleQuantumToChar(GetPixelRed(image,p)); |
938 | 14.8k | *q++=ScaleQuantumToChar(GetPixelGreen(image,p)); |
939 | 14.8k | *q++=ScaleQuantumToChar(GetPixelBlue(image,p)); |
940 | 14.8k | p+=(ptrdiff_t) GetPixelChannels(image); |
941 | 14.8k | } |
942 | 9.19k | if (((bytes_per_pixel*image->columns) & 0x01) != 0) |
943 | 7.20k | *q++='\0'; /* pad scanline */ |
944 | 9.19k | (void) WriteBlob(image,(size_t) (q-pixels),pixels); |
945 | 9.19k | if (image->previous == (Image *) NULL) |
946 | 9.19k | { |
947 | 9.19k | status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, |
948 | 9.19k | image->rows); |
949 | 9.19k | if (status == MagickFalse) |
950 | 0 | break; |
951 | 9.19k | } |
952 | 9.19k | } |
953 | 67 | pixels=(unsigned char *) RelinquishMagickMemory(pixels); |
954 | 67 | } |
955 | 347 | else |
956 | 347 | if (SetImageMonochrome(image,exception) != MagickFalse) |
957 | 228 | { |
958 | 228 | unsigned char |
959 | 228 | bit, |
960 | 228 | byte; |
961 | | |
962 | | /* |
963 | | Convert PseudoClass image to a SUN monochrome image. |
964 | | */ |
965 | 228 | (void) SetImageType(image,BilevelType,exception); |
966 | 16.8k | for (y=0; y < (ssize_t) image->rows; y++) |
967 | 16.5k | { |
968 | 16.5k | p=GetVirtualPixels(image,0,y,image->columns,1,exception); |
969 | 16.5k | if (p == (const Quantum *) NULL) |
970 | 0 | break; |
971 | 16.5k | bit=0; |
972 | 16.5k | byte=0; |
973 | 2.15M | for (x=0; x < (ssize_t) image->columns; x++) |
974 | 2.13M | { |
975 | 2.13M | byte<<=1; |
976 | 2.13M | if (GetPixelLuma(image,p) < ((double) QuantumRange/2.0)) |
977 | 473k | byte|=0x01; |
978 | 2.13M | bit++; |
979 | 2.13M | if (bit == 8) |
980 | 263k | { |
981 | 263k | (void) WriteBlobByte(image,byte); |
982 | 263k | bit=0; |
983 | 263k | byte=0; |
984 | 263k | } |
985 | 2.13M | p+=(ptrdiff_t) GetPixelChannels(image); |
986 | 2.13M | } |
987 | 16.5k | if (bit != 0) |
988 | 15.2k | (void) WriteBlobByte(image,(unsigned char) (byte << (8-bit))); |
989 | 16.5k | if ((((image->columns/8)+ |
990 | 16.5k | (image->columns % 8 ? 1 : 0)) % 2) != 0) |
991 | 14.4k | (void) WriteBlobByte(image,0); /* pad scanline */ |
992 | 16.5k | if (image->previous == (Image *) NULL) |
993 | 16.5k | { |
994 | 16.5k | status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, |
995 | 16.5k | image->rows); |
996 | 16.5k | if (status == MagickFalse) |
997 | 0 | break; |
998 | 16.5k | } |
999 | 16.5k | } |
1000 | 228 | } |
1001 | 119 | else |
1002 | 119 | { |
1003 | | /* |
1004 | | Dump colormap to file. |
1005 | | */ |
1006 | 22.3k | for (i=0; i < (ssize_t) image->colors; i++) |
1007 | 22.1k | (void) WriteBlobByte(image,ScaleQuantumToChar( |
1008 | 22.1k | ClampToQuantum(image->colormap[i].red))); |
1009 | 22.3k | for (i=0; i < (ssize_t) image->colors; i++) |
1010 | 22.1k | (void) WriteBlobByte(image,ScaleQuantumToChar( |
1011 | 22.1k | ClampToQuantum(image->colormap[i].green))); |
1012 | 22.3k | for (i=0; i < (ssize_t) image->colors; i++) |
1013 | 22.1k | (void) WriteBlobByte(image,ScaleQuantumToChar( |
1014 | 22.1k | ClampToQuantum(image->colormap[i].blue))); |
1015 | | /* |
1016 | | Convert PseudoClass packet to SUN colormapped pixel. |
1017 | | */ |
1018 | 10.8k | for (y=0; y < (ssize_t) image->rows; y++) |
1019 | 10.7k | { |
1020 | 10.7k | p=GetVirtualPixels(image,0,y,image->columns,1,exception); |
1021 | 10.7k | if (p == (const Quantum *) NULL) |
1022 | 0 | break; |
1023 | 1.62M | for (x=0; x < (ssize_t) image->columns; x++) |
1024 | 1.61M | { |
1025 | 1.61M | (void) WriteBlobByte(image,(unsigned char) |
1026 | 1.61M | GetPixelIndex(image,p)); |
1027 | 1.61M | p+=(ptrdiff_t) GetPixelChannels(image); |
1028 | 1.61M | } |
1029 | 10.7k | if (image->columns & 0x01) |
1030 | 9.31k | (void) WriteBlobByte(image,0); /* pad scanline */ |
1031 | 10.7k | if (image->previous == (Image *) NULL) |
1032 | 10.7k | { |
1033 | 10.7k | status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, |
1034 | 10.7k | image->rows); |
1035 | 10.7k | if (status == MagickFalse) |
1036 | 0 | break; |
1037 | 10.7k | } |
1038 | 10.7k | } |
1039 | 119 | } |
1040 | 414 | if (GetNextImageInList(image) == (Image *) NULL) |
1041 | 414 | break; |
1042 | 0 | image=SyncNextImageInList(image); |
1043 | 0 | status=SetImageProgress(image,SaveImagesTag,scene++,number_scenes); |
1044 | 0 | if (status == MagickFalse) |
1045 | 0 | break; |
1046 | 0 | } while (image_info->adjoin != MagickFalse); |
1047 | 414 | if (CloseBlob(image) == MagickFalse) |
1048 | 0 | status=MagickFalse; |
1049 | 414 | return(status); |
1050 | 414 | } |