blob: 324d0481e719a9a4020c06e4b8a8dcfb95a17c95 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% RRRR GGGG BBBB %
7% R R G B B %
8% RRRR G GG BBBB %
9% R R G G B B %
10% R R GGG BBBB %
11% %
12% %
13% Read/Write Raw RGB Image Format %
14% %
15% Software Design %
cristyde984cd2013-12-01 14:49:27 +000016% Cristy %
cristy3ed852e2009-09-05 21:47:34 +000017% July 1992 %
18% %
19% %
Cristyf775a5c2019-11-26 14:27:47 -050020% Copyright 1999-2020 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% 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% %
Cristy83d74de2018-10-13 10:17:25 -040026% https://imagemagick.org/script/license.php %
cristy3ed852e2009-09-05 21:47:34 +000027% %
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*/
cristy4c08aed2011-07-01 19:47:50 +000042#include "MagickCore/studio.h"
43#include "MagickCore/blob.h"
44#include "MagickCore/blob-private.h"
45#include "MagickCore/cache.h"
cristy6a2180c2013-05-27 10:28:36 +000046#include "MagickCore/channel.h"
cristy4c08aed2011-07-01 19:47:50 +000047#include "MagickCore/colorspace.h"
cristy510d06a2011-07-06 23:43:54 +000048#include "MagickCore/colorspace-private.h"
cristy4c08aed2011-07-01 19:47:50 +000049#include "MagickCore/constitute.h"
50#include "MagickCore/exception.h"
51#include "MagickCore/exception-private.h"
52#include "MagickCore/image.h"
53#include "MagickCore/image-private.h"
54#include "MagickCore/list.h"
55#include "MagickCore/magick.h"
56#include "MagickCore/memory_.h"
57#include "MagickCore/monitor.h"
58#include "MagickCore/monitor-private.h"
59#include "MagickCore/pixel-accessor.h"
60#include "MagickCore/quantum-private.h"
61#include "MagickCore/static.h"
62#include "MagickCore/statistic.h"
63#include "MagickCore/string_.h"
64#include "MagickCore/module.h"
65#include "MagickCore/utility.h"
cristy3ed852e2009-09-05 21:47:34 +000066
67/*
68 Forward declarations.
69*/
70static MagickBooleanType
cristy3a37efd2011-08-28 20:31:03 +000071 WriteRGBImage(const ImageInfo *,Image *,ExceptionInfo *);
cristy3ed852e2009-09-05 21:47:34 +000072
73/*
74%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
75% %
76% %
77% %
78% R e a d R G B I m a g e %
79% %
80% %
81% %
82%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
83%
cristy90dbac72010-08-22 15:08:40 +000084% ReadRGBImage() reads an image of raw RGB, RGBA, or RGBO samples and returns
85% it. It allocates the memory necessary for the new Image structure and
86% returns a pointer to the new image.
cristy3ed852e2009-09-05 21:47:34 +000087%
88% The format of the ReadRGBImage method is:
89%
cristy90dbac72010-08-22 15:08:40 +000090% Image *ReadRGBImage(const ImageInfo *image_info,
91% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +000092%
93% A description of each parameter follows:
94%
95% o image_info: the image info.
96%
97% o exception: return any errors or warnings in this structure.
98%
99*/
cristyddacdd12012-05-07 23:08:14 +0000100static Image *ReadRGBImage(const ImageInfo *image_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000101{
Cristy6e32ff12019-10-20 11:10:41 -0400102 const void
103 *stream;
cristybd797f12015-01-24 20:42:32 +0000104
cristy3ed852e2009-09-05 21:47:34 +0000105 Image
106 *canvas_image,
107 *image;
108
cristy3ed852e2009-09-05 21:47:34 +0000109 MagickBooleanType
110 status;
111
112 MagickOffsetType
113 scene;
114
115 QuantumInfo
116 *quantum_info;
117
118 QuantumType
119 quantum_type;
120
cristybb503372010-05-27 20:51:26 +0000121 register ssize_t
cristy90dbac72010-08-22 15:08:40 +0000122 i;
cristy3ed852e2009-09-05 21:47:34 +0000123
cristyc6da28e2011-04-28 01:41:35 +0000124 size_t
125 length;
126
cristy3ed852e2009-09-05 21:47:34 +0000127 ssize_t
cristya38675f2010-08-21 18:35:13 +0000128 count,
129 y;
cristy3ed852e2009-09-05 21:47:34 +0000130
Cristy6e32ff12019-10-20 11:10:41 -0400131 unsigned char
132 *pixels;
133
cristy3ed852e2009-09-05 21:47:34 +0000134 /*
135 Open image file.
136 */
137 assert(image_info != (const ImageInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000138 assert(image_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +0000139 if (image_info->debug != MagickFalse)
140 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
141 image_info->filename);
142 assert(exception != (ExceptionInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000143 assert(exception->signature == MagickCoreSignature);
cristy9950d572011-10-01 18:22:35 +0000144 image=AcquireImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +0000145 if ((image->columns == 0) || (image->rows == 0))
146 ThrowReaderException(OptionError,"MustSpecifyImageSize");
147 if (image_info->interlace != PartitionInterlace)
148 {
149 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
150 if (status == MagickFalse)
151 {
152 image=DestroyImageList(image);
153 return((Image *) NULL);
154 }
Cristyb2d24412018-03-09 19:41:19 -0500155 if (DiscardBlobBytes(image,(MagickSizeType) image->offset) == MagickFalse)
cristyd4297022010-09-16 22:59:09 +0000156 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
157 image->filename);
cristy3ed852e2009-09-05 21:47:34 +0000158 }
159 /*
160 Create virtual canvas to support cropping (i.e. image.rgb[100x100+10+20]).
161 */
162 canvas_image=CloneImage(image,image->extract_info.width,1,MagickFalse,
163 exception);
root7a851d32017-09-28 17:39:04 +0000164 if(canvas_image == (Image *) NULL)
root67c24572017-09-28 16:57:54 +0000165 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristy387430f2012-02-07 13:09:46 +0000166 (void) SetImageVirtualPixelMethod(canvas_image,BlackVirtualPixelMethod,
167 exception);
cristy5f766ef2014-12-14 21:12:47 +0000168 quantum_info=AcquireQuantumInfo(image_info,canvas_image);
cristy3ed852e2009-09-05 21:47:34 +0000169 if (quantum_info == (QuantumInfo *) NULL)
Dirk Lemstradede8402018-03-24 17:51:58 +0100170 {
171 canvas_image=DestroyImage(canvas_image);
172 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
173 }
cristy3ed852e2009-09-05 21:47:34 +0000174 quantum_type=RGBQuantum;
cristy90dbac72010-08-22 15:08:40 +0000175 if (LocaleCompare(image_info->magick,"RGBA") == 0)
cristya38675f2010-08-21 18:35:13 +0000176 {
cristy90dbac72010-08-22 15:08:40 +0000177 quantum_type=RGBAQuantum;
cristy8a46d822012-08-28 23:32:39 +0000178 image->alpha_trait=BlendPixelTrait;
179 canvas_image->alpha_trait=BlendPixelTrait;
cristya38675f2010-08-21 18:35:13 +0000180 }
cristy90dbac72010-08-22 15:08:40 +0000181 if (LocaleCompare(image_info->magick,"RGBO") == 0)
182 {
183 quantum_type=RGBOQuantum;
dirk7000aae2015-02-24 11:56:06 +0000184 image->alpha_trait=BlendPixelTrait;
cristy8a46d822012-08-28 23:32:39 +0000185 canvas_image->alpha_trait=BlendPixelTrait;
cristy90dbac72010-08-22 15:08:40 +0000186 }
Cristy6e32ff12019-10-20 11:10:41 -0400187 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000188 if (image_info->number_scenes != 0)
189 while (image->scene < image_info->scene)
190 {
191 /*
192 Skip to next image.
193 */
194 image->scene++;
195 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
cristybb503372010-05-27 20:51:26 +0000196 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000197 {
Cristy6e32ff12019-10-20 11:10:41 -0400198 stream=ReadBlobStream(image,length,pixels,&count);
cristy3ed852e2009-09-05 21:47:34 +0000199 if (count != (ssize_t) length)
200 break;
201 }
202 }
cristy3ed852e2009-09-05 21:47:34 +0000203 count=0;
204 length=0;
205 scene=0;
Dirk Lemstradede8402018-03-24 17:51:58 +0100206 status=MagickTrue;
Cristy6e32ff12019-10-20 11:10:41 -0400207 stream=NULL;
cristy3ed852e2009-09-05 21:47:34 +0000208 do
209 {
210 /*
211 Read pixels to virtual canvas image then push to image.
212 */
213 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
214 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
215 break;
cristyacabb842014-12-14 23:36:33 +0000216 status=SetImageExtent(image,image->columns,image->rows,exception);
217 if (status == MagickFalse)
Dirk Lemstradede8402018-03-24 17:51:58 +0100218 break;
cristy3ed852e2009-09-05 21:47:34 +0000219 switch (image_info->interlace)
220 {
221 case NoInterlace:
222 default:
223 {
224 /*
225 No interlacing: RGBRGBRGBRGBRGBRGB...
226 */
227 if (scene == 0)
228 {
229 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
Cristy6e32ff12019-10-20 11:10:41 -0400230 stream=ReadBlobStream(image,length,pixels,&count);
cristy3ed852e2009-09-05 21:47:34 +0000231 }
cristybb503372010-05-27 20:51:26 +0000232 for (y=0; y < (ssize_t) image->extract_info.height; y++)
cristy3ed852e2009-09-05 21:47:34 +0000233 {
cristy4c08aed2011-07-01 19:47:50 +0000234 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +0100235 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +0000236
cristy4c08aed2011-07-01 19:47:50 +0000237 register Quantum
dirk05d2ff72015-11-18 23:13:43 +0100238 *magick_restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000239
cristy90dbac72010-08-22 15:08:40 +0000240 register ssize_t
241 x;
242
cristy21da32d2009-09-12 14:56:09 +0000243 if (count != (ssize_t) length)
244 {
Dirk Lemstradede8402018-03-24 17:51:58 +0100245 status=MagickFalse;
cristy21da32d2009-09-12 14:56:09 +0000246 ThrowFileException(exception,CorruptImageError,
247 "UnexpectedEndOfFile",image->filename);
248 break;
249 }
cristy3ed852e2009-09-05 21:47:34 +0000250 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
251 exception);
cristyacd2ed22011-08-30 01:44:23 +0000252 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000253 break;
254 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
Cristy6f84d892019-10-29 21:32:11 -0400255 quantum_info,quantum_type,(unsigned char *) stream,exception);
cristy3ed852e2009-09-05 21:47:34 +0000256 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
257 break;
Cristy747a7342019-06-03 21:01:22 -0400258 if (((y-image->extract_info.y) >= 0) &&
cristybb503372010-05-27 20:51:26 +0000259 ((y-image->extract_info.y) < (ssize_t) image->rows))
cristy3ed852e2009-09-05 21:47:34 +0000260 {
261 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
262 canvas_image->columns,1,exception);
263 q=QueueAuthenticPixels(image,0,y-image->extract_info.y,
264 image->columns,1,exception);
cristyddacdd12012-05-07 23:08:14 +0000265 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
cristy3ed852e2009-09-05 21:47:34 +0000266 break;
cristybb503372010-05-27 20:51:26 +0000267 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000268 {
cristy4c08aed2011-07-01 19:47:50 +0000269 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
270 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
271 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
272 SetPixelAlpha(image,OpaqueAlpha,q);
cristy17f11b02014-12-20 19:37:04 +0000273 if (image->alpha_trait != UndefinedPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +0000274 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
cristyed231572011-07-14 02:18:59 +0000275 p+=GetPixelChannels(canvas_image);
276 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000277 }
278 if (SyncAuthenticPixels(image,exception) == MagickFalse)
279 break;
280 }
281 if (image->previous == (Image *) NULL)
282 {
cristycee97112010-05-28 00:44:52 +0000283 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
284 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000285 if (status == MagickFalse)
286 break;
287 }
Cristy6e32ff12019-10-20 11:10:41 -0400288 stream=ReadBlobStream(image,length,pixels,&count);
cristy3ed852e2009-09-05 21:47:34 +0000289 }
290 break;
291 }
292 case LineInterlace:
293 {
cristy90dbac72010-08-22 15:08:40 +0000294 static QuantumType
295 quantum_types[4] =
296 {
297 RedQuantum,
298 GreenQuantum,
299 BlueQuantum,
300 AlphaQuantum
301 };
302
cristy3ed852e2009-09-05 21:47:34 +0000303 /*
304 Line interlacing: RRR...GGG...BBB...RRR...GGG...BBB...
305 */
cristy90dbac72010-08-22 15:08:40 +0000306 if (LocaleCompare(image_info->magick,"RGBO") == 0)
307 quantum_types[3]=OpacityQuantum;
cristy3ed852e2009-09-05 21:47:34 +0000308 if (scene == 0)
309 {
cristy90dbac72010-08-22 15:08:40 +0000310 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
Cristy6e32ff12019-10-20 11:10:41 -0400311 stream=ReadBlobStream(image,length,pixels,&count);
cristy3ed852e2009-09-05 21:47:34 +0000312 }
cristybb503372010-05-27 20:51:26 +0000313 for (y=0; y < (ssize_t) image->extract_info.height; y++)
cristy3ed852e2009-09-05 21:47:34 +0000314 {
cristy17f11b02014-12-20 19:37:04 +0000315 for (i=0; i < (ssize_t) (image->alpha_trait != UndefinedPixelTrait ? 4 : 3); i++)
cristy3ed852e2009-09-05 21:47:34 +0000316 {
Dirk Lemstradede8402018-03-24 17:51:58 +0100317 register const Quantum
318 *magick_restrict p;
319
320 register Quantum
321 *magick_restrict q;
322
323 register ssize_t
324 x;
325
326 if (count != (ssize_t) length)
327 {
328 status=MagickFalse;
329 ThrowFileException(exception,CorruptImageError,
330 "UnexpectedEndOfFile",image->filename);
331 break;
332 }
cristy90dbac72010-08-22 15:08:40 +0000333 quantum_type=quantum_types[i];
cristy3ed852e2009-09-05 21:47:34 +0000334 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
335 exception);
cristyacd2ed22011-08-30 01:44:23 +0000336 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000337 break;
338 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
Cristy6f84d892019-10-29 21:32:11 -0400339 quantum_info,quantum_type,(unsigned char *) stream,exception);
cristy3ed852e2009-09-05 21:47:34 +0000340 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
341 break;
Cristy747a7342019-06-03 21:01:22 -0400342 if (((y-image->extract_info.y) >= 0) &&
cristybb503372010-05-27 20:51:26 +0000343 ((y-image->extract_info.y) < (ssize_t) image->rows))
cristy3ed852e2009-09-05 21:47:34 +0000344 {
345 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,
346 0,canvas_image->columns,1,exception);
347 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
348 image->columns,1,exception);
cristyddacdd12012-05-07 23:08:14 +0000349 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
cristy3ed852e2009-09-05 21:47:34 +0000350 break;
cristy90dbac72010-08-22 15:08:40 +0000351 for (x=0; x < (ssize_t) image->columns; x++)
352 {
353 switch (quantum_type)
cristy3ed852e2009-09-05 21:47:34 +0000354 {
cristy90dbac72010-08-22 15:08:40 +0000355 case RedQuantum:
356 {
cristy4c08aed2011-07-01 19:47:50 +0000357 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
cristy90dbac72010-08-22 15:08:40 +0000358 break;
359 }
360 case GreenQuantum:
361 {
cristy4c08aed2011-07-01 19:47:50 +0000362 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
cristy90dbac72010-08-22 15:08:40 +0000363 break;
364 }
365 case BlueQuantum:
366 {
cristy4c08aed2011-07-01 19:47:50 +0000367 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
cristy90dbac72010-08-22 15:08:40 +0000368 break;
369 }
370 case OpacityQuantum:
371 {
Cristyc7737122018-03-09 20:01:16 -0500372 SetPixelOpacity(image,GetPixelOpacity(canvas_image,p),q);
cristy90dbac72010-08-22 15:08:40 +0000373 break;
374 }
375 case AlphaQuantum:
376 {
cristy4c08aed2011-07-01 19:47:50 +0000377 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
cristy90dbac72010-08-22 15:08:40 +0000378 break;
379 }
380 default:
381 break;
cristy3ed852e2009-09-05 21:47:34 +0000382 }
cristyed231572011-07-14 02:18:59 +0000383 p+=GetPixelChannels(canvas_image);
384 q+=GetPixelChannels(image);
cristy90dbac72010-08-22 15:08:40 +0000385 }
cristy3ed852e2009-09-05 21:47:34 +0000386 if (SyncAuthenticPixels(image,exception) == MagickFalse)
387 break;
388 }
Cristy6e32ff12019-10-20 11:10:41 -0400389 stream=ReadBlobStream(image,length,pixels,&count);
cristy3ed852e2009-09-05 21:47:34 +0000390 }
391 if (image->previous == (Image *) NULL)
392 {
cristycee97112010-05-28 00:44:52 +0000393 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
394 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000395 if (status == MagickFalse)
396 break;
397 }
398 }
399 break;
400 }
401 case PlaneInterlace:
402 {
403 /*
404 Plane interlacing: RRRRRR...GGGGGG...BBBBBB...
405 */
406 if (scene == 0)
407 {
cristy90dbac72010-08-22 15:08:40 +0000408 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
Cristy6e32ff12019-10-20 11:10:41 -0400409 stream=ReadBlobStream(image,length,pixels,&count);
cristy3ed852e2009-09-05 21:47:34 +0000410 }
cristy90dbac72010-08-22 15:08:40 +0000411 for (y=0; y < (ssize_t) image->extract_info.height; y++)
cristy3ed852e2009-09-05 21:47:34 +0000412 {
cristy4c08aed2011-07-01 19:47:50 +0000413 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +0100414 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +0000415
cristy4c08aed2011-07-01 19:47:50 +0000416 register Quantum
dirk05d2ff72015-11-18 23:13:43 +0100417 *magick_restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000418
cristy90dbac72010-08-22 15:08:40 +0000419 register ssize_t
420 x;
cristy3ed852e2009-09-05 21:47:34 +0000421
cristy90dbac72010-08-22 15:08:40 +0000422 if (count != (ssize_t) length)
cristy3ed852e2009-09-05 21:47:34 +0000423 {
Dirk Lemstradede8402018-03-24 17:51:58 +0100424 status=MagickFalse;
cristy90dbac72010-08-22 15:08:40 +0000425 ThrowFileException(exception,CorruptImageError,
426 "UnexpectedEndOfFile",image->filename);
427 break;
428 }
429 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
430 exception);
cristyacd2ed22011-08-30 01:44:23 +0000431 if (q == (Quantum *) NULL)
cristy90dbac72010-08-22 15:08:40 +0000432 break;
433 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
Cristy6f84d892019-10-29 21:32:11 -0400434 quantum_info,RedQuantum,(unsigned char *) stream,exception);
cristy90dbac72010-08-22 15:08:40 +0000435 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
436 break;
Cristy747a7342019-06-03 21:01:22 -0400437 if (((y-image->extract_info.y) >= 0) &&
cristy90dbac72010-08-22 15:08:40 +0000438 ((y-image->extract_info.y) < (ssize_t) image->rows))
439 {
440 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
441 canvas_image->columns,1,exception);
442 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
443 image->columns,1,exception);
cristyddacdd12012-05-07 23:08:14 +0000444 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
cristy90dbac72010-08-22 15:08:40 +0000445 break;
446 for (x=0; x < (ssize_t) image->columns; x++)
447 {
cristy4c08aed2011-07-01 19:47:50 +0000448 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
cristyed231572011-07-14 02:18:59 +0000449 p+=GetPixelChannels(canvas_image);
450 q+=GetPixelChannels(image);
cristy90dbac72010-08-22 15:08:40 +0000451 }
452 if (SyncAuthenticPixels(image,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000453 break;
454 }
Cristy6e32ff12019-10-20 11:10:41 -0400455 stream=ReadBlobStream(image,length,pixels,&count);
cristy3ed852e2009-09-05 21:47:34 +0000456 }
457 if (image->previous == (Image *) NULL)
458 {
cristy90dbac72010-08-22 15:08:40 +0000459 status=SetImageProgress(image,LoadImageTag,1,6);
460 if (status == MagickFalse)
461 break;
462 }
463 for (y=0; y < (ssize_t) image->extract_info.height; y++)
464 {
cristy4c08aed2011-07-01 19:47:50 +0000465 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +0100466 *magick_restrict p;
cristy90dbac72010-08-22 15:08:40 +0000467
cristy4c08aed2011-07-01 19:47:50 +0000468 register Quantum
dirk05d2ff72015-11-18 23:13:43 +0100469 *magick_restrict q;
cristy90dbac72010-08-22 15:08:40 +0000470
471 register ssize_t
472 x;
473
474 if (count != (ssize_t) length)
475 {
Dirk Lemstradede8402018-03-24 17:51:58 +0100476 status=MagickFalse;
cristy90dbac72010-08-22 15:08:40 +0000477 ThrowFileException(exception,CorruptImageError,
478 "UnexpectedEndOfFile",image->filename);
479 break;
480 }
481 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
482 exception);
cristyacd2ed22011-08-30 01:44:23 +0000483 if (q == (Quantum *) NULL)
cristy90dbac72010-08-22 15:08:40 +0000484 break;
485 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
Cristy6f84d892019-10-29 21:32:11 -0400486 quantum_info,GreenQuantum,(unsigned char *) stream,exception);
cristy90dbac72010-08-22 15:08:40 +0000487 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
488 break;
Cristy747a7342019-06-03 21:01:22 -0400489 if (((y-image->extract_info.y) >= 0) &&
cristy90dbac72010-08-22 15:08:40 +0000490 ((y-image->extract_info.y) < (ssize_t) image->rows))
491 {
492 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
493 canvas_image->columns,1,exception);
494 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
495 image->columns,1,exception);
cristyddacdd12012-05-07 23:08:14 +0000496 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
cristy90dbac72010-08-22 15:08:40 +0000497 break;
498 for (x=0; x < (ssize_t) image->columns; x++)
499 {
cristyf27ee032011-09-29 17:51:41 +0000500 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
cristyed231572011-07-14 02:18:59 +0000501 p+=GetPixelChannels(canvas_image);
502 q+=GetPixelChannels(image);
cristy90dbac72010-08-22 15:08:40 +0000503 }
504 if (SyncAuthenticPixels(image,exception) == MagickFalse)
505 break;
506 }
Cristy6e32ff12019-10-20 11:10:41 -0400507 stream=ReadBlobStream(image,length,pixels,&count);
cristy90dbac72010-08-22 15:08:40 +0000508 }
509 if (image->previous == (Image *) NULL)
510 {
511 status=SetImageProgress(image,LoadImageTag,2,6);
512 if (status == MagickFalse)
513 break;
514 }
515 for (y=0; y < (ssize_t) image->extract_info.height; y++)
516 {
cristy4c08aed2011-07-01 19:47:50 +0000517 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +0100518 *magick_restrict p;
cristy90dbac72010-08-22 15:08:40 +0000519
cristy4c08aed2011-07-01 19:47:50 +0000520 register Quantum
dirk05d2ff72015-11-18 23:13:43 +0100521 *magick_restrict q;
cristy90dbac72010-08-22 15:08:40 +0000522
523 register ssize_t
524 x;
525
526 if (count != (ssize_t) length)
527 {
Dirk Lemstradede8402018-03-24 17:51:58 +0100528 status=MagickFalse;
cristy90dbac72010-08-22 15:08:40 +0000529 ThrowFileException(exception,CorruptImageError,
530 "UnexpectedEndOfFile",image->filename);
531 break;
532 }
533 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
534 exception);
cristyacd2ed22011-08-30 01:44:23 +0000535 if (q == (Quantum *) NULL)
cristy90dbac72010-08-22 15:08:40 +0000536 break;
537 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
Cristy6f84d892019-10-29 21:32:11 -0400538 quantum_info,BlueQuantum,(unsigned char *) stream,exception);
cristy90dbac72010-08-22 15:08:40 +0000539 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
540 break;
Cristy747a7342019-06-03 21:01:22 -0400541 if (((y-image->extract_info.y) >= 0) &&
cristy90dbac72010-08-22 15:08:40 +0000542 ((y-image->extract_info.y) < (ssize_t) image->rows))
543 {
544 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
545 canvas_image->columns,1,exception);
546 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
547 image->columns,1,exception);
cristyddacdd12012-05-07 23:08:14 +0000548 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
cristy90dbac72010-08-22 15:08:40 +0000549 break;
550 for (x=0; x < (ssize_t) image->columns; x++)
551 {
cristyf27ee032011-09-29 17:51:41 +0000552 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
cristyed231572011-07-14 02:18:59 +0000553 p+=GetPixelChannels(canvas_image);
554 q+=GetPixelChannels(image);
cristy90dbac72010-08-22 15:08:40 +0000555 }
556 if (SyncAuthenticPixels(image,exception) == MagickFalse)
557 break;
558 }
Cristy6e32ff12019-10-20 11:10:41 -0400559 stream=ReadBlobStream(image,length,pixels,&count);
cristy90dbac72010-08-22 15:08:40 +0000560 }
561 if (image->previous == (Image *) NULL)
562 {
cristy90dbac72010-08-22 15:08:40 +0000563 status=SetImageProgress(image,LoadImageTag,4,6);
564 if (status == MagickFalse)
565 break;
566 }
cristy17f11b02014-12-20 19:37:04 +0000567 if (image->alpha_trait != UndefinedPixelTrait)
cristy90dbac72010-08-22 15:08:40 +0000568 {
569 for (y=0; y < (ssize_t) image->extract_info.height; y++)
570 {
cristy4c08aed2011-07-01 19:47:50 +0000571 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +0100572 *magick_restrict p;
cristy90dbac72010-08-22 15:08:40 +0000573
cristy4c08aed2011-07-01 19:47:50 +0000574 register Quantum
dirk05d2ff72015-11-18 23:13:43 +0100575 *magick_restrict q;
cristy90dbac72010-08-22 15:08:40 +0000576
577 register ssize_t
578 x;
579
580 if (count != (ssize_t) length)
581 {
Dirk Lemstradede8402018-03-24 17:51:58 +0100582 status=MagickFalse;
cristy90dbac72010-08-22 15:08:40 +0000583 ThrowFileException(exception,CorruptImageError,
584 "UnexpectedEndOfFile",image->filename);
585 break;
586 }
587 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
588 exception);
cristyacd2ed22011-08-30 01:44:23 +0000589 if (q == (Quantum *) NULL)
cristy90dbac72010-08-22 15:08:40 +0000590 break;
591 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
Cristy6f84d892019-10-29 21:32:11 -0400592 quantum_info,AlphaQuantum,(unsigned char *) stream,exception);
cristy90dbac72010-08-22 15:08:40 +0000593 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
594 break;
Cristy747a7342019-06-03 21:01:22 -0400595 if (((y-image->extract_info.y) >= 0) &&
cristy90dbac72010-08-22 15:08:40 +0000596 ((y-image->extract_info.y) < (ssize_t) image->rows))
597 {
598 p=GetVirtualPixels(canvas_image,
599 canvas_image->extract_info.x,0,canvas_image->columns,1,
600 exception);
601 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
602 image->columns,1,exception);
cristyddacdd12012-05-07 23:08:14 +0000603 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
cristy90dbac72010-08-22 15:08:40 +0000604 break;
605 for (x=0; x < (ssize_t) image->columns; x++)
606 {
cristyf27ee032011-09-29 17:51:41 +0000607 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
cristyed231572011-07-14 02:18:59 +0000608 p+=GetPixelChannels(canvas_image);
609 q+=GetPixelChannels(image);
cristy90dbac72010-08-22 15:08:40 +0000610 }
611 if (SyncAuthenticPixels(image,exception) == MagickFalse)
612 break;
613 }
Cristy6e32ff12019-10-20 11:10:41 -0400614 stream=ReadBlobStream(image,length,pixels,&count);
cristy90dbac72010-08-22 15:08:40 +0000615 }
616 if (image->previous == (Image *) NULL)
617 {
618 status=SetImageProgress(image,LoadImageTag,5,6);
619 if (status == MagickFalse)
620 break;
621 }
622 }
623 if (image->previous == (Image *) NULL)
624 {
625 status=SetImageProgress(image,LoadImageTag,6,6);
cristy3ed852e2009-09-05 21:47:34 +0000626 if (status == MagickFalse)
627 break;
628 }
629 break;
630 }
631 case PartitionInterlace:
632 {
633 /*
634 Partition interlacing: RRRRRR..., GGGGGG..., BBBBBB...
635 */
cristy90dbac72010-08-22 15:08:40 +0000636 AppendImageFormat("R",image->filename);
637 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
638 if (status == MagickFalse)
Dirk Lemstradede8402018-03-24 17:51:58 +0100639 break;
Cristyb2d24412018-03-09 19:41:19 -0500640 if (DiscardBlobBytes(image,(MagickSizeType) image->offset) == MagickFalse)
Dirk Lemstradede8402018-03-24 17:51:58 +0100641 {
642 status=MagickFalse;
Cristy6e32ff12019-10-20 11:10:41 -0400643 ThrowFileException(exception,CorruptImageError,
644 "UnexpectedEndOfFile",image->filename);
Dirk Lemstradede8402018-03-24 17:51:58 +0100645 break;
646 }
cristy90dbac72010-08-22 15:08:40 +0000647 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
648 for (i=0; i < (ssize_t) scene; i++)
Dirk Lemstradede8402018-03-24 17:51:58 +0100649 {
cristy90dbac72010-08-22 15:08:40 +0000650 for (y=0; y < (ssize_t) image->extract_info.height; y++)
cristybd797f12015-01-24 20:42:32 +0000651 {
Cristy6e32ff12019-10-20 11:10:41 -0400652 stream=ReadBlobStream(image,length,pixels,&count);
cristybd797f12015-01-24 20:42:32 +0000653 if (count != (ssize_t) length)
Dirk Lemstradede8402018-03-24 17:51:58 +0100654 break;
cristybd797f12015-01-24 20:42:32 +0000655 }
Dirk Lemstradede8402018-03-24 17:51:58 +0100656 if (count != (ssize_t) length)
657 break;
658 }
Cristy6e32ff12019-10-20 11:10:41 -0400659 stream=ReadBlobStream(image,length,pixels,&count);
cristy90dbac72010-08-22 15:08:40 +0000660 for (y=0; y < (ssize_t) image->extract_info.height; y++)
661 {
cristy4c08aed2011-07-01 19:47:50 +0000662 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +0100663 *magick_restrict p;
cristy90dbac72010-08-22 15:08:40 +0000664
cristy4c08aed2011-07-01 19:47:50 +0000665 register Quantum
dirk05d2ff72015-11-18 23:13:43 +0100666 *magick_restrict q;
cristy90dbac72010-08-22 15:08:40 +0000667
668 register ssize_t
669 x;
670
671 if (count != (ssize_t) length)
cristy3ed852e2009-09-05 21:47:34 +0000672 {
Dirk Lemstradede8402018-03-24 17:51:58 +0100673 status=MagickFalse;
cristy90dbac72010-08-22 15:08:40 +0000674 ThrowFileException(exception,CorruptImageError,
675 "UnexpectedEndOfFile",image->filename);
676 break;
677 }
678 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
679 exception);
cristyacd2ed22011-08-30 01:44:23 +0000680 if (q == (Quantum *) NULL)
cristy90dbac72010-08-22 15:08:40 +0000681 break;
682 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
Cristy6f84d892019-10-29 21:32:11 -0400683 quantum_info,RedQuantum,(unsigned char *) stream,exception);
cristy90dbac72010-08-22 15:08:40 +0000684 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
685 break;
Cristy747a7342019-06-03 21:01:22 -0400686 if (((y-image->extract_info.y) >= 0) &&
cristy90dbac72010-08-22 15:08:40 +0000687 ((y-image->extract_info.y) < (ssize_t) image->rows))
688 {
689 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
690 canvas_image->columns,1,exception);
691 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
692 image->columns,1,exception);
cristyddacdd12012-05-07 23:08:14 +0000693 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
cristy90dbac72010-08-22 15:08:40 +0000694 break;
695 for (x=0; x < (ssize_t) image->columns; x++)
696 {
cristy4c08aed2011-07-01 19:47:50 +0000697 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
cristyed231572011-07-14 02:18:59 +0000698 p+=GetPixelChannels(canvas_image);
699 q+=GetPixelChannels(image);
cristy90dbac72010-08-22 15:08:40 +0000700 }
701 if (SyncAuthenticPixels(image,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000702 break;
703 }
Cristy6e32ff12019-10-20 11:10:41 -0400704 stream=ReadBlobStream(image,length,pixels,&count);
cristy3ed852e2009-09-05 21:47:34 +0000705 }
706 if (image->previous == (Image *) NULL)
707 {
cristy90dbac72010-08-22 15:08:40 +0000708 status=SetImageProgress(image,LoadImageTag,1,5);
709 if (status == MagickFalse)
710 break;
711 }
712 (void) CloseBlob(image);
713 AppendImageFormat("G",image->filename);
714 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
715 if (status == MagickFalse)
Dirk Lemstradede8402018-03-24 17:51:58 +0100716 break;
cristy90dbac72010-08-22 15:08:40 +0000717 length=GetQuantumExtent(canvas_image,quantum_info,GreenQuantum);
718 for (i=0; i < (ssize_t) scene; i++)
Dirk Lemstradede8402018-03-24 17:51:58 +0100719 {
cristy90dbac72010-08-22 15:08:40 +0000720 for (y=0; y < (ssize_t) image->extract_info.height; y++)
cristybd797f12015-01-24 20:42:32 +0000721 {
Cristy6e32ff12019-10-20 11:10:41 -0400722 stream=ReadBlobStream(image,length,pixels,&count);
cristybd797f12015-01-24 20:42:32 +0000723 if (count != (ssize_t) length)
Dirk Lemstradede8402018-03-24 17:51:58 +0100724 break;
cristybd797f12015-01-24 20:42:32 +0000725 }
Dirk Lemstradede8402018-03-24 17:51:58 +0100726 if (count != (ssize_t) length)
727 break;
728 }
Cristy6e32ff12019-10-20 11:10:41 -0400729 stream=ReadBlobStream(image,length,pixels,&count);
cristy90dbac72010-08-22 15:08:40 +0000730 for (y=0; y < (ssize_t) image->extract_info.height; y++)
731 {
cristy4c08aed2011-07-01 19:47:50 +0000732 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +0100733 *magick_restrict p;
cristy90dbac72010-08-22 15:08:40 +0000734
cristy4c08aed2011-07-01 19:47:50 +0000735 register Quantum
dirk05d2ff72015-11-18 23:13:43 +0100736 *magick_restrict q;
cristy90dbac72010-08-22 15:08:40 +0000737
738 register ssize_t
739 x;
740
741 if (count != (ssize_t) length)
742 {
Dirk Lemstradede8402018-03-24 17:51:58 +0100743 status=MagickFalse;
cristy90dbac72010-08-22 15:08:40 +0000744 ThrowFileException(exception,CorruptImageError,
745 "UnexpectedEndOfFile",image->filename);
746 break;
747 }
748 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
749 exception);
cristyacd2ed22011-08-30 01:44:23 +0000750 if (q == (Quantum *) NULL)
cristy90dbac72010-08-22 15:08:40 +0000751 break;
752 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
Cristy6f84d892019-10-29 21:32:11 -0400753 quantum_info,GreenQuantum,(unsigned char *) stream,exception);
cristy90dbac72010-08-22 15:08:40 +0000754 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
755 break;
Cristy747a7342019-06-03 21:01:22 -0400756 if (((y-image->extract_info.y) >= 0) &&
cristy90dbac72010-08-22 15:08:40 +0000757 ((y-image->extract_info.y) < (ssize_t) image->rows))
758 {
759 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
760 canvas_image->columns,1,exception);
761 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
762 image->columns,1,exception);
cristyddacdd12012-05-07 23:08:14 +0000763 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
cristy90dbac72010-08-22 15:08:40 +0000764 break;
765 for (x=0; x < (ssize_t) image->columns; x++)
766 {
cristyf27ee032011-09-29 17:51:41 +0000767 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
cristyed231572011-07-14 02:18:59 +0000768 p+=GetPixelChannels(canvas_image);
769 q+=GetPixelChannels(image);
cristy90dbac72010-08-22 15:08:40 +0000770 }
771 if (SyncAuthenticPixels(image,exception) == MagickFalse)
772 break;
773 }
Cristy6e32ff12019-10-20 11:10:41 -0400774 stream=ReadBlobStream(image,length,pixels,&count);
cristy90dbac72010-08-22 15:08:40 +0000775 }
776 if (image->previous == (Image *) NULL)
777 {
778 status=SetImageProgress(image,LoadImageTag,2,5);
779 if (status == MagickFalse)
780 break;
781 }
782 (void) CloseBlob(image);
783 AppendImageFormat("B",image->filename);
784 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
785 if (status == MagickFalse)
Dirk Lemstradede8402018-03-24 17:51:58 +0100786 break;
cristy90dbac72010-08-22 15:08:40 +0000787 length=GetQuantumExtent(canvas_image,quantum_info,BlueQuantum);
788 for (i=0; i < (ssize_t) scene; i++)
Dirk Lemstradede8402018-03-24 17:51:58 +0100789 {
cristy90dbac72010-08-22 15:08:40 +0000790 for (y=0; y < (ssize_t) image->extract_info.height; y++)
Cristy747a7342019-06-03 21:01:22 -0400791 {
Cristy6e32ff12019-10-20 11:10:41 -0400792 stream=ReadBlobStream(image,length,pixels,&count);
cristybd797f12015-01-24 20:42:32 +0000793 if (count != (ssize_t) length)
Dirk Lemstradede8402018-03-24 17:51:58 +0100794 break;
795 }
796 if (count != (ssize_t) length)
797 break;
798 }
Cristy6e32ff12019-10-20 11:10:41 -0400799 stream=ReadBlobStream(image,length,pixels,&count);
cristy90dbac72010-08-22 15:08:40 +0000800 for (y=0; y < (ssize_t) image->extract_info.height; y++)
801 {
cristy4c08aed2011-07-01 19:47:50 +0000802 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +0100803 *magick_restrict p;
cristy90dbac72010-08-22 15:08:40 +0000804
cristy4c08aed2011-07-01 19:47:50 +0000805 register Quantum
dirk05d2ff72015-11-18 23:13:43 +0100806 *magick_restrict q;
cristy90dbac72010-08-22 15:08:40 +0000807
808 register ssize_t
809 x;
810
811 if (count != (ssize_t) length)
812 {
Dirk Lemstradede8402018-03-24 17:51:58 +0100813 status=MagickFalse;
cristy90dbac72010-08-22 15:08:40 +0000814 ThrowFileException(exception,CorruptImageError,
815 "UnexpectedEndOfFile",image->filename);
816 break;
817 }
818 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
819 exception);
cristyacd2ed22011-08-30 01:44:23 +0000820 if (q == (Quantum *) NULL)
cristy90dbac72010-08-22 15:08:40 +0000821 break;
822 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
Cristy6f84d892019-10-29 21:32:11 -0400823 quantum_info,BlueQuantum,(unsigned char *) stream,exception);
cristy90dbac72010-08-22 15:08:40 +0000824 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
825 break;
Cristy747a7342019-06-03 21:01:22 -0400826 if (((y-image->extract_info.y) >= 0) &&
cristy90dbac72010-08-22 15:08:40 +0000827 ((y-image->extract_info.y) < (ssize_t) image->rows))
828 {
829 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
830 canvas_image->columns,1,exception);
831 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
832 image->columns,1,exception);
cristyddacdd12012-05-07 23:08:14 +0000833 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
cristy90dbac72010-08-22 15:08:40 +0000834 break;
835 for (x=0; x < (ssize_t) image->columns; x++)
836 {
cristyf27ee032011-09-29 17:51:41 +0000837 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
cristyed231572011-07-14 02:18:59 +0000838 p+=GetPixelChannels(canvas_image);
839 q+=GetPixelChannels(image);
cristy90dbac72010-08-22 15:08:40 +0000840 }
841 if (SyncAuthenticPixels(image,exception) == MagickFalse)
842 break;
843 }
Cristy6e32ff12019-10-20 11:10:41 -0400844 stream=ReadBlobStream(image,length,pixels,&count);
cristy90dbac72010-08-22 15:08:40 +0000845 }
846 if (image->previous == (Image *) NULL)
847 {
848 status=SetImageProgress(image,LoadImageTag,3,5);
849 if (status == MagickFalse)
850 break;
851 }
cristy17f11b02014-12-20 19:37:04 +0000852 if (image->alpha_trait != UndefinedPixelTrait)
cristy90dbac72010-08-22 15:08:40 +0000853 {
854 (void) CloseBlob(image);
855 AppendImageFormat("A",image->filename);
856 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
857 if (status == MagickFalse)
Dirk Lemstradede8402018-03-24 17:51:58 +0100858 break;
cristy90dbac72010-08-22 15:08:40 +0000859 length=GetQuantumExtent(canvas_image,quantum_info,AlphaQuantum);
860 for (i=0; i < (ssize_t) scene; i++)
Dirk Lemstradede8402018-03-24 17:51:58 +0100861 {
cristy90dbac72010-08-22 15:08:40 +0000862 for (y=0; y < (ssize_t) image->extract_info.height; y++)
cristybd797f12015-01-24 20:42:32 +0000863 {
Cristy6e32ff12019-10-20 11:10:41 -0400864 stream=ReadBlobStream(image,length,pixels,&count);
cristybd797f12015-01-24 20:42:32 +0000865 if (count != (ssize_t) length)
Dirk Lemstradede8402018-03-24 17:51:58 +0100866 break;
cristybd797f12015-01-24 20:42:32 +0000867 }
Dirk Lemstradede8402018-03-24 17:51:58 +0100868 if (count != (ssize_t) length)
869 break;
870 }
Cristy6e32ff12019-10-20 11:10:41 -0400871 stream=ReadBlobStream(image,length,pixels,&count);
cristy90dbac72010-08-22 15:08:40 +0000872 for (y=0; y < (ssize_t) image->extract_info.height; y++)
873 {
cristy4c08aed2011-07-01 19:47:50 +0000874 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +0100875 *magick_restrict p;
cristy90dbac72010-08-22 15:08:40 +0000876
cristy4c08aed2011-07-01 19:47:50 +0000877 register Quantum
dirk05d2ff72015-11-18 23:13:43 +0100878 *magick_restrict q;
cristy90dbac72010-08-22 15:08:40 +0000879
880 register ssize_t
881 x;
882
883 if (count != (ssize_t) length)
884 {
Dirk Lemstradede8402018-03-24 17:51:58 +0100885 status=MagickFalse;
cristy90dbac72010-08-22 15:08:40 +0000886 ThrowFileException(exception,CorruptImageError,
887 "UnexpectedEndOfFile",image->filename);
888 break;
889 }
890 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
891 exception);
cristyacd2ed22011-08-30 01:44:23 +0000892 if (q == (Quantum *) NULL)
cristy90dbac72010-08-22 15:08:40 +0000893 break;
894 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
Cristy6f84d892019-10-29 21:32:11 -0400895 quantum_info,BlueQuantum,(unsigned char *) stream,exception);
cristy90dbac72010-08-22 15:08:40 +0000896 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
897 break;
Cristy747a7342019-06-03 21:01:22 -0400898 if (((y-image->extract_info.y) >= 0) &&
cristy90dbac72010-08-22 15:08:40 +0000899 ((y-image->extract_info.y) < (ssize_t) image->rows))
900 {
901 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,
902 0,canvas_image->columns,1,exception);
903 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
904 image->columns,1,exception);
cristyc6aebff2012-05-07 23:24:35 +0000905 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
cristy90dbac72010-08-22 15:08:40 +0000906 break;
907 for (x=0; x < (ssize_t) image->columns; x++)
908 {
cristyf27ee032011-09-29 17:51:41 +0000909 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
cristyed231572011-07-14 02:18:59 +0000910 p+=GetPixelChannels(canvas_image);
911 q+=GetPixelChannels(image);
cristy90dbac72010-08-22 15:08:40 +0000912 }
913 if (SyncAuthenticPixels(image,exception) == MagickFalse)
914 break;
915 }
Cristy6e32ff12019-10-20 11:10:41 -0400916 stream=ReadBlobStream(image,length,pixels,&count);
cristy90dbac72010-08-22 15:08:40 +0000917 }
918 if (image->previous == (Image *) NULL)
919 {
920 status=SetImageProgress(image,LoadImageTag,4,5);
921 if (status == MagickFalse)
922 break;
923 }
924 }
925 (void) CloseBlob(image);
926 if (image->previous == (Image *) NULL)
927 {
cristy3ed852e2009-09-05 21:47:34 +0000928 status=SetImageProgress(image,LoadImageTag,5,5);
929 if (status == MagickFalse)
930 break;
931 }
932 break;
933 }
934 }
Dirk Lemstradede8402018-03-24 17:51:58 +0100935 if (status == MagickFalse)
936 break;
cristy3ed852e2009-09-05 21:47:34 +0000937 SetQuantumImageType(image,quantum_type);
cristy3ed852e2009-09-05 21:47:34 +0000938 /*
939 Proceed to next image.
940 */
941 if (image_info->number_scenes != 0)
942 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
943 break;
944 if (count == (ssize_t) length)
945 {
946 /*
947 Allocate next image structure.
948 */
cristy9950d572011-10-01 18:22:35 +0000949 AcquireNextImage(image_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000950 if (GetNextImageInList(image) == (Image *) NULL)
951 {
Cristy5ff0db92018-06-20 18:04:36 -0400952 status=MagickFalse;
953 break;
cristy3ed852e2009-09-05 21:47:34 +0000954 }
955 image=SyncNextImageInList(image);
956 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
957 GetBlobSize(image));
958 if (status == MagickFalse)
959 break;
960 }
961 scene++;
962 } while (count == (ssize_t) length);
cristy3ed852e2009-09-05 21:47:34 +0000963 quantum_info=DestroyQuantumInfo(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000964 canvas_image=DestroyImage(canvas_image);
965 (void) CloseBlob(image);
Dirk Lemstradede8402018-03-24 17:51:58 +0100966 if (status == MagickFalse)
Cristy3b48d202018-07-01 17:11:51 -0400967 return(DestroyImageList(image));
cristy3ed852e2009-09-05 21:47:34 +0000968 return(GetFirstImageInList(image));
969}
970
971/*
972%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
973% %
974% %
975% %
Cristy747a7342019-06-03 21:01:22 -0400976% R e a d R G B 5 6 5 I m a g e %
977% %
978% %
979% %
980%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
981%
982% ReadGRAYImage() reads an image of raw RGB 5-6-5 samples and returns it. It
983% allocates the memory necessary for the new Image structure and returns a
984% pointer to the new image.
985%
986% The format of the ReadGRAYImage method is:
987%
988% Image *ReadGRAYImage(const ImageInfo *image_info,
989% ExceptionInfo *exception)
990%
991% A description of each parameter follows:
992%
993% o image_info: the image info.
994%
995% o exception: return any errors or warnings in this structure.
996%
997*/
998static Image *ReadRGB565Image(const ImageInfo *image_info,
999 ExceptionInfo *exception)
1000{
Cristy6e32ff12019-10-20 11:10:41 -04001001 const void
1002 *stream;
Cristy747a7342019-06-03 21:01:22 -04001003
1004 Image
1005 *canvas_image,
1006 *image;
1007
1008 MagickBooleanType
1009 status;
1010
1011 MagickOffsetType
1012 scene;
1013
1014 QuantumInfo
1015 *quantum_info;
1016
1017 QuantumType
1018 quantum_type;
1019
1020 size_t
1021 length;
1022
1023 ssize_t
1024 count,
1025 y;
1026
Cristy6e32ff12019-10-20 11:10:41 -04001027 unsigned char
1028 *pixels;
1029
Cristy747a7342019-06-03 21:01:22 -04001030 /*
1031 Open image file.
1032 */
1033 assert(image_info != (const ImageInfo *) NULL);
1034 assert(image_info->signature == MagickCoreSignature);
1035 if (image_info->debug != MagickFalse)
1036 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1037 image_info->filename);
1038 assert(exception != (ExceptionInfo *) NULL);
1039 assert(exception->signature == MagickCoreSignature);
1040 image=AcquireImage(image_info,exception);
1041 if ((image->columns == 0) || (image->rows == 0))
1042 ThrowReaderException(OptionError,"MustSpecifyImageSize");
1043 image->depth=16;
1044 if (image_info->interlace != PartitionInterlace)
1045 {
1046 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
1047 if (status == MagickFalse)
1048 {
1049 image=DestroyImageList(image);
1050 return((Image *) NULL);
1051 }
1052 if (DiscardBlobBytes(image,(MagickSizeType) image->offset) == MagickFalse)
1053 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
1054 image->filename);
1055 }
1056 /*
1057 Create virtual canvas to support cropping (i.e. image.rgb[100x100+10+20]).
1058 */
1059 canvas_image=CloneImage(image,image->extract_info.width,1,MagickFalse,
1060 exception);
1061 if(canvas_image == (Image *) NULL)
1062 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1063 (void) SetImageVirtualPixelMethod(canvas_image,BlackVirtualPixelMethod,
1064 exception);
1065 quantum_info=AcquireQuantumInfo(image_info,canvas_image);
1066 if (quantum_info == (QuantumInfo *) NULL)
1067 {
1068 canvas_image=DestroyImage(canvas_image);
1069 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1070 }
1071 quantum_type=GrayQuantum;
Cristy6e32ff12019-10-20 11:10:41 -04001072 pixels=GetQuantumPixels(quantum_info);
Cristy747a7342019-06-03 21:01:22 -04001073 if (image_info->number_scenes != 0)
1074 while (image->scene < image_info->scene)
1075 {
1076 /*
1077 Skip to next image.
1078 */
1079 image->scene++;
1080 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
1081 for (y=0; y < (ssize_t) image->rows; y++)
1082 {
Cristy6e32ff12019-10-20 11:10:41 -04001083 stream=ReadBlobStream(image,length,pixels,&count);
Cristy747a7342019-06-03 21:01:22 -04001084 if (count != (ssize_t) length)
1085 break;
1086 }
1087 }
1088 count=0;
1089 length=0;
1090 scene=0;
1091 status=MagickTrue;
Cristy6e32ff12019-10-20 11:10:41 -04001092 stream=NULL;
Cristy747a7342019-06-03 21:01:22 -04001093 do
1094 {
1095 /*
1096 Read pixels to virtual canvas image then push to image.
1097 */
1098 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
1099 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1100 break;
1101 status=SetImageExtent(image,image->columns,image->rows,exception);
1102 if (status == MagickFalse)
1103 break;
1104 /*
1105 No interlacing: GGG...
1106 */
1107 if (scene == 0)
1108 {
1109 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
Cristy6e32ff12019-10-20 11:10:41 -04001110 stream=ReadBlobStream(image,length,pixels,&count);
Cristy747a7342019-06-03 21:01:22 -04001111 }
1112 for (y=0; y < (ssize_t) image->extract_info.height; y++)
1113 {
1114 register const Quantum
1115 *magick_restrict p;
1116
1117 register Quantum
1118 *magick_restrict q;
1119
1120 register ssize_t
1121 x;
1122
1123 if (count != (ssize_t) length)
1124 {
1125 status=MagickFalse;
1126 ThrowFileException(exception,CorruptImageError,
1127 "UnexpectedEndOfFile",image->filename);
1128 break;
1129 }
1130 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,exception);
1131 if (q == (Quantum *) NULL)
1132 break;
1133 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
Cristy6f84d892019-10-29 21:32:11 -04001134 quantum_info,quantum_type,(unsigned char *) stream,exception);
Cristy747a7342019-06-03 21:01:22 -04001135 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
1136 break;
1137 if (((y-image->extract_info.y) >= 0) &&
1138 ((y-image->extract_info.y) < (ssize_t) image->rows))
1139 {
1140 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
1141 canvas_image->columns,1,exception);
1142 q=QueueAuthenticPixels(image,0,y-image->extract_info.y,
1143 image->columns,1,exception);
1144 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
1145 break;
1146 for (x=0; x < (ssize_t) image->columns; x++)
1147 {
1148 unsigned short
1149 pixel;
1150
1151 pixel=(unsigned short) ScaleQuantumToShort(GetPixelGray(
1152 canvas_image,p));
1153 SetPixelRed(image,(Quantum) (((pixel >> 11) & 0x1f) << 11),q);
1154 SetPixelGreen(image,(Quantum) (((pixel >> 5) & 0x3f) << 10),q);
1155 SetPixelBlue(image,(Quantum) ((pixel & 0x1f) << 11),q);
1156 p+=GetPixelChannels(canvas_image);
1157 q+=GetPixelChannels(image);
1158 }
1159 if (SyncAuthenticPixels(image,exception) == MagickFalse)
1160 break;
1161 }
1162 if (image->previous == (Image *) NULL)
1163 {
1164 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
1165 image->rows);
1166 if (status == MagickFalse)
1167 break;
1168 }
Cristy6e32ff12019-10-20 11:10:41 -04001169 stream=ReadBlobStream(image,length,pixels,&count);
Cristy747a7342019-06-03 21:01:22 -04001170 }
1171 if (status == MagickFalse)
1172 break;
1173 SetQuantumImageType(image,quantum_type);
1174 /*
1175 Proceed to next image.
1176 */
1177 if (image_info->number_scenes != 0)
1178 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1179 break;
1180 if (count == (ssize_t) length)
1181 {
1182 /*
1183 Allocate next image structure.
1184 */
1185 AcquireNextImage(image_info,image,exception);
1186 if (GetNextImageInList(image) == (Image *) NULL)
1187 {
1188 status=MagickFalse;
1189 break;
1190 }
1191 image=SyncNextImageInList(image);
1192 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
1193 GetBlobSize(image));
1194 if (status == MagickFalse)
1195 break;
1196 }
1197 scene++;
1198 } while (count == (ssize_t) length);
1199 quantum_info=DestroyQuantumInfo(quantum_info);
1200 canvas_image=DestroyImage(canvas_image);
1201 (void) CloseBlob(image);
1202 if (status == MagickFalse)
1203 return(DestroyImageList(image));
1204 return(GetFirstImageInList(image));
1205}
1206
1207/*
1208%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1209% %
1210% %
1211% %
cristy3ed852e2009-09-05 21:47:34 +00001212% R e g i s t e r R G B I m a g e %
1213% %
1214% %
1215% %
1216%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1217%
cristy90dbac72010-08-22 15:08:40 +00001218% RegisterRGBImage() adds attributes for the RGB image format to
cristy3ed852e2009-09-05 21:47:34 +00001219% the list of supported formats. The attributes include the image format
1220% tag, a method to read and/or write the format, whether the format
1221% supports the saving of more than one frame to the same file or blob,
1222% whether the format supports native in-memory I/O, and a brief
1223% description of the format.
1224%
1225% The format of the RegisterRGBImage method is:
1226%
cristybb503372010-05-27 20:51:26 +00001227% size_t RegisterRGBImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001228%
1229*/
cristybb503372010-05-27 20:51:26 +00001230ModuleExport size_t RegisterRGBImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001231{
1232 MagickInfo
1233 *entry;
1234
dirk06b627a2015-04-06 18:59:17 +00001235 entry=AcquireMagickInfo("RGB","RGB",
1236 "Raw red, green, and blue samples");
cristy3ed852e2009-09-05 21:47:34 +00001237 entry->decoder=(DecodeImageHandler *) ReadRGBImage;
1238 entry->encoder=(EncodeImageHandler *) WriteRGBImage;
dirk08e9a112015-02-22 01:51:41 +00001239 entry->flags|=CoderRawSupportFlag;
1240 entry->flags|=CoderEndianSupportFlag;
cristy3ed852e2009-09-05 21:47:34 +00001241 (void) RegisterMagickInfo(entry);
dirk06b627a2015-04-06 18:59:17 +00001242 entry=AcquireMagickInfo("RGB","RGBA",
1243 "Raw red, green, blue, and alpha samples");
cristy3ed852e2009-09-05 21:47:34 +00001244 entry->decoder=(DecodeImageHandler *) ReadRGBImage;
1245 entry->encoder=(EncodeImageHandler *) WriteRGBImage;
dirk08e9a112015-02-22 01:51:41 +00001246 entry->flags|=CoderRawSupportFlag;
1247 entry->flags|=CoderEndianSupportFlag;
cristy3ed852e2009-09-05 21:47:34 +00001248 (void) RegisterMagickInfo(entry);
dirk06b627a2015-04-06 18:59:17 +00001249 entry=AcquireMagickInfo("RGB","RGBO",
1250 "Raw red, green, blue, and opacity samples");
cristy3ed852e2009-09-05 21:47:34 +00001251 entry->decoder=(DecodeImageHandler *) ReadRGBImage;
1252 entry->encoder=(EncodeImageHandler *) WriteRGBImage;
dirk08e9a112015-02-22 01:51:41 +00001253 entry->flags|=CoderRawSupportFlag;
1254 entry->flags|=CoderEndianSupportFlag;
cristy3ed852e2009-09-05 21:47:34 +00001255 (void) RegisterMagickInfo(entry);
Cristy747a7342019-06-03 21:01:22 -04001256 entry=AcquireMagickInfo("RGB","RGB565",
Dirk Lemstra98bffc22019-06-09 07:23:35 +02001257 "Raw red, green, blue samples in 565 format");
Cristy747a7342019-06-03 21:01:22 -04001258 entry->decoder=(DecodeImageHandler *) ReadRGB565Image;
1259 entry->flags|=CoderRawSupportFlag;
1260 entry->flags|=CoderEndianSupportFlag;
1261 (void) RegisterMagickInfo(entry);
cristy3ed852e2009-09-05 21:47:34 +00001262 return(MagickImageCoderSignature);
1263}
1264
1265/*
1266%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1267% %
1268% %
1269% %
1270% U n r e g i s t e r R G B I m a g e %
1271% %
1272% %
1273% %
1274%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1275%
cristy90dbac72010-08-22 15:08:40 +00001276% UnregisterRGBImage() removes format registrations made by the RGB module
1277% from the list of supported formats.
cristy3ed852e2009-09-05 21:47:34 +00001278%
1279% The format of the UnregisterRGBImage method is:
1280%
1281% UnregisterRGBImage(void)
1282%
1283*/
1284ModuleExport void UnregisterRGBImage(void)
1285{
1286 (void) UnregisterMagickInfo("RGBO");
1287 (void) UnregisterMagickInfo("RGBA");
cristy3ed852e2009-09-05 21:47:34 +00001288 (void) UnregisterMagickInfo("RGB");
1289}
1290
1291/*
1292%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1293% %
1294% %
1295% %
1296% W r i t e R G B I m a g e %
1297% %
1298% %
1299% %
1300%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1301%
cristy90dbac72010-08-22 15:08:40 +00001302% WriteRGBImage() writes an image to a file in the RGB, RGBA, or RGBO
1303% rasterfile format.
cristy3ed852e2009-09-05 21:47:34 +00001304%
1305% The format of the WriteRGBImage method is:
1306%
cristy90dbac72010-08-22 15:08:40 +00001307% MagickBooleanType WriteRGBImage(const ImageInfo *image_info,
cristy3a37efd2011-08-28 20:31:03 +00001308% Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001309%
1310% A description of each parameter follows.
1311%
1312% o image_info: the image info.
1313%
1314% o image: The image.
1315%
cristy3a37efd2011-08-28 20:31:03 +00001316% o exception: return any errors or warnings in this structure.
1317%
cristy3ed852e2009-09-05 21:47:34 +00001318*/
cristyc6aebff2012-05-07 23:24:35 +00001319static MagickBooleanType WriteRGBImage(const ImageInfo *image_info,
1320 Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001321{
cristy3ed852e2009-09-05 21:47:34 +00001322 MagickBooleanType
1323 status;
1324
1325 MagickOffsetType
1326 scene;
1327
1328 QuantumInfo
1329 *quantum_info;
1330
1331 QuantumType
cristy90dbac72010-08-22 15:08:40 +00001332 quantum_type;
cristy3ed852e2009-09-05 21:47:34 +00001333
cristyc6da28e2011-04-28 01:41:35 +00001334 size_t
Cristyc45b2bb2018-04-07 12:32:12 -04001335 imageListLength,
cristyc6da28e2011-04-28 01:41:35 +00001336 length;
1337
cristy3ed852e2009-09-05 21:47:34 +00001338 ssize_t
cristy90dbac72010-08-22 15:08:40 +00001339 count,
1340 y;
cristy3ed852e2009-09-05 21:47:34 +00001341
cristy3ed852e2009-09-05 21:47:34 +00001342 unsigned char
1343 *pixels;
1344
cristy3ed852e2009-09-05 21:47:34 +00001345 /*
1346 Allocate memory for pixels.
1347 */
1348 assert(image_info != (const ImageInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001349 assert(image_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001350 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001351 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001352 if (image->debug != MagickFalse)
1353 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1354 if (image_info->interlace != PartitionInterlace)
1355 {
1356 /*
1357 Open output image file.
1358 */
cristyedf03fa2011-08-30 12:44:39 +00001359 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
cristy3ed852e2009-09-05 21:47:34 +00001360 if (status == MagickFalse)
1361 return(status);
1362 }
1363 quantum_type=RGBQuantum;
cristy90dbac72010-08-22 15:08:40 +00001364 if (LocaleCompare(image_info->magick,"RGBA") == 0)
cristyc6aebff2012-05-07 23:24:35 +00001365 quantum_type=RGBAQuantum;
cristy90dbac72010-08-22 15:08:40 +00001366 if (LocaleCompare(image_info->magick,"RGBO") == 0)
cristyc6aebff2012-05-07 23:24:35 +00001367 quantum_type=RGBOQuantum;
cristy3ed852e2009-09-05 21:47:34 +00001368 scene=0;
Cristyc45b2bb2018-04-07 12:32:12 -04001369 imageListLength=GetImageListLength(image);
cristy3ed852e2009-09-05 21:47:34 +00001370 do
1371 {
1372 /*
1373 Convert MIFF to RGB raster pixels.
1374 */
cristyaf8d3912014-02-21 14:50:33 +00001375 (void) TransformImageColorspace(image,sRGBColorspace,exception);
cristy3ed852e2009-09-05 21:47:34 +00001376 if ((LocaleCompare(image_info->magick,"RGBA") == 0) &&
cristy17f11b02014-12-20 19:37:04 +00001377 (image->alpha_trait == UndefinedPixelTrait))
cristy3a37efd2011-08-28 20:31:03 +00001378 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
cristy5f766ef2014-12-14 21:12:47 +00001379 quantum_info=AcquireQuantumInfo(image_info,image);
cristy3ed852e2009-09-05 21:47:34 +00001380 if (quantum_info == (QuantumInfo *) NULL)
1381 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
cristyb3f97ae2015-05-18 12:29:32 +00001382 pixels=(unsigned char *) GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +00001383 switch (image_info->interlace)
1384 {
1385 case NoInterlace:
1386 default:
1387 {
cristy3ed852e2009-09-05 21:47:34 +00001388 /*
1389 No interlacing: RGBRGBRGBRGBRGBRGB...
1390 */
cristybb503372010-05-27 20:51:26 +00001391 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001392 {
cristy4c08aed2011-07-01 19:47:50 +00001393 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +01001394 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001395
cristy3a37efd2011-08-28 20:31:03 +00001396 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001397 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001398 break;
cristy4c08aed2011-07-01 19:47:50 +00001399 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy3a37efd2011-08-28 20:31:03 +00001400 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001401 count=WriteBlob(image,length,pixels);
1402 if (count != (ssize_t) length)
1403 break;
1404 if (image->previous == (Image *) NULL)
1405 {
cristycee97112010-05-28 00:44:52 +00001406 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1407 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001408 if (status == MagickFalse)
1409 break;
1410 }
1411 }
cristy3ed852e2009-09-05 21:47:34 +00001412 break;
1413 }
1414 case LineInterlace:
1415 {
1416 /*
1417 Line interlacing: RRR...GGG...BBB...RRR...GGG...BBB...
1418 */
cristybb503372010-05-27 20:51:26 +00001419 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001420 {
cristy4c08aed2011-07-01 19:47:50 +00001421 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +01001422 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001423
cristy3a37efd2011-08-28 20:31:03 +00001424 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001425 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001426 break;
cristy4c08aed2011-07-01 19:47:50 +00001427 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy3a37efd2011-08-28 20:31:03 +00001428 RedQuantum,pixels,exception);
cristy90dbac72010-08-22 15:08:40 +00001429 count=WriteBlob(image,length,pixels);
1430 if (count != (ssize_t) length)
1431 break;
cristy4c08aed2011-07-01 19:47:50 +00001432 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy3a37efd2011-08-28 20:31:03 +00001433 GreenQuantum,pixels,exception);
cristy90dbac72010-08-22 15:08:40 +00001434 count=WriteBlob(image,length,pixels);
1435 if (count != (ssize_t) length)
1436 break;
cristy4c08aed2011-07-01 19:47:50 +00001437 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy3a37efd2011-08-28 20:31:03 +00001438 BlueQuantum,pixels,exception);
cristy90dbac72010-08-22 15:08:40 +00001439 count=WriteBlob(image,length,pixels);
1440 if (count != (ssize_t) length)
1441 break;
1442 if (quantum_type == RGBAQuantum)
1443 {
cristy4c08aed2011-07-01 19:47:50 +00001444 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy3a37efd2011-08-28 20:31:03 +00001445 AlphaQuantum,pixels,exception);
cristy90dbac72010-08-22 15:08:40 +00001446 count=WriteBlob(image,length,pixels);
1447 if (count != (ssize_t) length)
1448 break;
1449 }
1450 if (quantum_type == RGBOQuantum)
1451 {
cristy4c08aed2011-07-01 19:47:50 +00001452 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy3a37efd2011-08-28 20:31:03 +00001453 OpacityQuantum,pixels,exception);
cristy90dbac72010-08-22 15:08:40 +00001454 count=WriteBlob(image,length,pixels);
1455 if (count != (ssize_t) length)
1456 break;
1457 }
cristy3ed852e2009-09-05 21:47:34 +00001458 if (image->previous == (Image *) NULL)
1459 {
cristycee97112010-05-28 00:44:52 +00001460 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1461 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001462 if (status == MagickFalse)
1463 break;
1464 }
1465 }
1466 break;
1467 }
1468 case PlaneInterlace:
1469 {
1470 /*
1471 Plane interlacing: RRRRRR...GGGGGG...BBBBBB...
1472 */
cristy90dbac72010-08-22 15:08:40 +00001473 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001474 {
cristy4c08aed2011-07-01 19:47:50 +00001475 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +01001476 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001477
cristy3a37efd2011-08-28 20:31:03 +00001478 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001479 if (p == (const Quantum *) NULL)
cristy90dbac72010-08-22 15:08:40 +00001480 break;
cristy4c08aed2011-07-01 19:47:50 +00001481 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy3a37efd2011-08-28 20:31:03 +00001482 RedQuantum,pixels,exception);
cristy90dbac72010-08-22 15:08:40 +00001483 count=WriteBlob(image,length,pixels);
1484 if (count != (ssize_t) length)
1485 break;
cristy3ed852e2009-09-05 21:47:34 +00001486 }
1487 if (image->previous == (Image *) NULL)
1488 {
cristy90dbac72010-08-22 15:08:40 +00001489 status=SetImageProgress(image,SaveImageTag,1,6);
1490 if (status == MagickFalse)
1491 break;
1492 }
1493 for (y=0; y < (ssize_t) image->rows; y++)
1494 {
cristy4c08aed2011-07-01 19:47:50 +00001495 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +01001496 *magick_restrict p;
cristy90dbac72010-08-22 15:08:40 +00001497
cristy3a37efd2011-08-28 20:31:03 +00001498 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001499 if (p == (const Quantum *) NULL)
cristy90dbac72010-08-22 15:08:40 +00001500 break;
cristy4c08aed2011-07-01 19:47:50 +00001501 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy3a37efd2011-08-28 20:31:03 +00001502 GreenQuantum,pixels,exception);
cristy90dbac72010-08-22 15:08:40 +00001503 count=WriteBlob(image,length,pixels);
1504 if (count != (ssize_t) length)
1505 break;
1506 }
1507 if (image->previous == (Image *) NULL)
1508 {
1509 status=SetImageProgress(image,SaveImageTag,2,6);
1510 if (status == MagickFalse)
1511 break;
1512 }
1513 for (y=0; y < (ssize_t) image->rows; y++)
1514 {
cristy4c08aed2011-07-01 19:47:50 +00001515 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +01001516 *magick_restrict p;
cristy90dbac72010-08-22 15:08:40 +00001517
cristy3a37efd2011-08-28 20:31:03 +00001518 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001519 if (p == (const Quantum *) NULL)
cristy90dbac72010-08-22 15:08:40 +00001520 break;
cristy4c08aed2011-07-01 19:47:50 +00001521 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy3a37efd2011-08-28 20:31:03 +00001522 BlueQuantum,pixels,exception);
cristy90dbac72010-08-22 15:08:40 +00001523 count=WriteBlob(image,length,pixels);
1524 if (count != (ssize_t) length)
1525 break;
1526 }
1527 if (image->previous == (Image *) NULL)
1528 {
1529 status=SetImageProgress(image,SaveImageTag,3,6);
1530 if (status == MagickFalse)
1531 break;
1532 }
1533 if (quantum_type == RGBAQuantum)
1534 {
1535 for (y=0; y < (ssize_t) image->rows; y++)
1536 {
cristy4c08aed2011-07-01 19:47:50 +00001537 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +01001538 *magick_restrict p;
cristy90dbac72010-08-22 15:08:40 +00001539
cristy3a37efd2011-08-28 20:31:03 +00001540 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001541 if (p == (const Quantum *) NULL)
cristy90dbac72010-08-22 15:08:40 +00001542 break;
cristy4c08aed2011-07-01 19:47:50 +00001543 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy3a37efd2011-08-28 20:31:03 +00001544 AlphaQuantum,pixels,exception);
cristy90dbac72010-08-22 15:08:40 +00001545 count=WriteBlob(image,length,pixels);
1546 if (count != (ssize_t) length)
1547 break;
1548 }
1549 if (image->previous == (Image *) NULL)
1550 {
1551 status=SetImageProgress(image,SaveImageTag,5,6);
1552 if (status == MagickFalse)
1553 break;
1554 }
1555 }
1556 if (image_info->interlace == PartitionInterlace)
1557 (void) CopyMagickString(image->filename,image_info->filename,
cristy151b66d2015-04-15 10:50:31 +00001558 MagickPathExtent);
cristy90dbac72010-08-22 15:08:40 +00001559 if (image->previous == (Image *) NULL)
1560 {
1561 status=SetImageProgress(image,SaveImageTag,6,6);
cristy3ed852e2009-09-05 21:47:34 +00001562 if (status == MagickFalse)
1563 break;
1564 }
1565 break;
1566 }
1567 case PartitionInterlace:
1568 {
cristy3ed852e2009-09-05 21:47:34 +00001569 /*
1570 Partition interlacing: RRRRRR..., GGGGGG..., BBBBBB...
1571 */
cristy90dbac72010-08-22 15:08:40 +00001572 AppendImageFormat("R",image->filename);
1573 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
cristy3a37efd2011-08-28 20:31:03 +00001574 AppendBinaryBlobMode,exception);
cristy90dbac72010-08-22 15:08:40 +00001575 if (status == MagickFalse)
1576 return(status);
1577 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001578 {
cristy4c08aed2011-07-01 19:47:50 +00001579 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +01001580 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001581
cristy3a37efd2011-08-28 20:31:03 +00001582 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001583 if (p == (const Quantum *) NULL)
cristy90dbac72010-08-22 15:08:40 +00001584 break;
cristy4c08aed2011-07-01 19:47:50 +00001585 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy3a37efd2011-08-28 20:31:03 +00001586 RedQuantum,pixels,exception);
cristy90dbac72010-08-22 15:08:40 +00001587 count=WriteBlob(image,length,pixels);
1588 if (count != (ssize_t) length)
1589 break;
1590 }
1591 if (image->previous == (Image *) NULL)
1592 {
1593 status=SetImageProgress(image,SaveImageTag,1,6);
1594 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001595 break;
1596 }
cristy90dbac72010-08-22 15:08:40 +00001597 (void) CloseBlob(image);
1598 AppendImageFormat("G",image->filename);
1599 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
cristy3a37efd2011-08-28 20:31:03 +00001600 AppendBinaryBlobMode,exception);
cristy90dbac72010-08-22 15:08:40 +00001601 if (status == MagickFalse)
1602 return(status);
1603 for (y=0; y < (ssize_t) image->rows; y++)
1604 {
cristy4c08aed2011-07-01 19:47:50 +00001605 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +01001606 *magick_restrict p;
cristy90dbac72010-08-22 15:08:40 +00001607
cristy3a37efd2011-08-28 20:31:03 +00001608 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001609 if (p == (const Quantum *) NULL)
cristy90dbac72010-08-22 15:08:40 +00001610 break;
cristy4c08aed2011-07-01 19:47:50 +00001611 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy3a37efd2011-08-28 20:31:03 +00001612 GreenQuantum,pixels,exception);
cristy90dbac72010-08-22 15:08:40 +00001613 count=WriteBlob(image,length,pixels);
1614 if (count != (ssize_t) length)
1615 break;
1616 }
1617 if (image->previous == (Image *) NULL)
1618 {
1619 status=SetImageProgress(image,SaveImageTag,2,6);
1620 if (status == MagickFalse)
1621 break;
1622 }
1623 (void) CloseBlob(image);
1624 AppendImageFormat("B",image->filename);
1625 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
cristy3a37efd2011-08-28 20:31:03 +00001626 AppendBinaryBlobMode,exception);
cristy90dbac72010-08-22 15:08:40 +00001627 if (status == MagickFalse)
1628 return(status);
1629 for (y=0; y < (ssize_t) image->rows; y++)
1630 {
cristy4c08aed2011-07-01 19:47:50 +00001631 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +01001632 *magick_restrict p;
cristy90dbac72010-08-22 15:08:40 +00001633
cristy3a37efd2011-08-28 20:31:03 +00001634 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001635 if (p == (const Quantum *) NULL)
cristy90dbac72010-08-22 15:08:40 +00001636 break;
cristy4c08aed2011-07-01 19:47:50 +00001637 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy3a37efd2011-08-28 20:31:03 +00001638 BlueQuantum,pixels,exception);
cristy90dbac72010-08-22 15:08:40 +00001639 count=WriteBlob(image,length,pixels);
1640 if (count != (ssize_t) length)
1641 break;
1642 }
1643 if (image->previous == (Image *) NULL)
1644 {
1645 status=SetImageProgress(image,SaveImageTag,3,6);
1646 if (status == MagickFalse)
1647 break;
1648 }
cristy90dbac72010-08-22 15:08:40 +00001649 if (quantum_type == RGBAQuantum)
1650 {
1651 (void) CloseBlob(image);
1652 AppendImageFormat("A",image->filename);
1653 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
cristy3a37efd2011-08-28 20:31:03 +00001654 AppendBinaryBlobMode,exception);
cristy90dbac72010-08-22 15:08:40 +00001655 if (status == MagickFalse)
1656 return(status);
1657 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001658 {
cristy4c08aed2011-07-01 19:47:50 +00001659 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +01001660 *magick_restrict p;
cristy90dbac72010-08-22 15:08:40 +00001661
cristy3a37efd2011-08-28 20:31:03 +00001662 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001663 if (p == (const Quantum *) NULL)
cristy90dbac72010-08-22 15:08:40 +00001664 break;
cristy4c08aed2011-07-01 19:47:50 +00001665 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy3a37efd2011-08-28 20:31:03 +00001666 AlphaQuantum,pixels,exception);
cristy90dbac72010-08-22 15:08:40 +00001667 count=WriteBlob(image,length,pixels);
1668 if (count != (ssize_t) length)
cristy3ed852e2009-09-05 21:47:34 +00001669 break;
1670 }
cristy90dbac72010-08-22 15:08:40 +00001671 if (image->previous == (Image *) NULL)
1672 {
1673 status=SetImageProgress(image,SaveImageTag,5,6);
1674 if (status == MagickFalse)
1675 break;
1676 }
1677 }
1678 (void) CloseBlob(image);
cristy3ed852e2009-09-05 21:47:34 +00001679 (void) CopyMagickString(image->filename,image_info->filename,
cristy151b66d2015-04-15 10:50:31 +00001680 MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00001681 if (image->previous == (Image *) NULL)
1682 {
cristy90dbac72010-08-22 15:08:40 +00001683 status=SetImageProgress(image,SaveImageTag,6,6);
cristy3ed852e2009-09-05 21:47:34 +00001684 if (status == MagickFalse)
1685 break;
1686 }
1687 break;
1688 }
1689 }
1690 quantum_info=DestroyQuantumInfo(quantum_info);
1691 if (GetNextImageInList(image) == (Image *) NULL)
1692 break;
1693 image=SyncNextImageInList(image);
Cristyc45b2bb2018-04-07 12:32:12 -04001694 status=SetImageProgress(image,SaveImagesTag,scene++,imageListLength);
cristy3ed852e2009-09-05 21:47:34 +00001695 if (status == MagickFalse)
1696 break;
1697 } while (image_info->adjoin != MagickFalse);
1698 (void) CloseBlob(image);
1699 return(MagickTrue);
1700}