13ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
23ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
43ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
53ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
63ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                        IIIII   CCCC   OOO   N   N                           %
73ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                          I    C      O   O  NN  N                           %
83ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                          I    C      O   O  N N N                           %
93ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                          I    C      O   O  N  NN                           %
103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                        IIIII   CCCC   OOO   N   N                           %
113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                   Read Microsoft Windows Icon Format                        %
143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                              Software Design                                %
16de984cdc3631106b1cbbb8d3972b76a0fc27e8e8cristy%                                   Cristy                                    %
173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                 July 1992                                   %
183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
207ce65e7125a4e1df1a274ce373c537a9df9c16cdCristy%  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  dedicated to making software imaging solutions freely available.           %
223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  You may not use this file except in compliance with the License.  You may  %
243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  obtain a copy of the License at                                            %
253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    http://www.imagemagick.org/script/license.php                            %
273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Unless required by applicable law or agreed to in writing, software        %
293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  distributed under the License is distributed on an "AS IS" BASIS,          %
303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  See the License for the specific language governing permissions and        %
323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  limitations under the License.                                             %
333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Include declarations.
413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
424c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/studio.h"
43aa192b15c78ecafb5ee45ea185519ba2cf4e1f60glennrp#include "MagickCore/artifact.h"
444c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/blob.h"
454c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/blob-private.h"
464c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/cache.h"
474c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/colormap.h"
484c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/colorspace.h"
493d9f5ba107b160e1819bb6baeeb3a9f521e9f450cristy#include "MagickCore/colorspace-private.h"
504c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception.h"
514c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception-private.h"
524c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image.h"
534c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image-private.h"
544c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/list.h"
554c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/log.h"
564c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/magick.h"
574c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/memory_.h"
584c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/monitor.h"
594c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/monitor-private.h"
602c5fc27ae5b613b7fb9fd69c12a47b99c7d4d471cristy#include "MagickCore/nt-base-private.h"
619e137706f4a1f40d099c597992f43cd3fba033a7dirk#include "MagickCore/option.h"
624c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/pixel-accessor.h"
634c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/quantize.h"
644c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/quantum-private.h"
654c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/static.h"
664c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/string_.h"
674c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/module.h"
683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Define declarations.
713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
7207a3cca00593c795eb8e0427f5bc4c2bcad3f0fbcristy#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__MINGW32__) || defined(__MINGW64__)
733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define BI_RGB  0
743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define BI_RLE8  1
753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define BI_BITFIELDS  3
763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define MaxIcons  1024
783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Typedef declarations.
813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
823ed852eea50f9d4cd633efb8c2b054b8e33c253cristytypedef struct _IconEntry
833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned char
853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    width,
863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    height,
873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    colors,
883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    reserved;
893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned short int
913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    planes,
923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    bits_per_pixel;
933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
94bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  size_t
953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    size,
963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    offset;
973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} IconEntry;
983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
993ed852eea50f9d4cd633efb8c2b054b8e33c253cristytypedef struct _IconFile
1003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
1013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  short
1023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    reserved,
1033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    resource_type,
1043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count;
1053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  IconEntry
1073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    directory[MaxIcons];
1083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} IconFile;
1093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1103ed852eea50f9d4cd633efb8c2b054b8e33c253cristytypedef struct _IconInfo
1113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
112bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  size_t
1133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    file_size,
1143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ba_offset,
1153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    offset_bits,
1163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    size;
1173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
118bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  ssize_t
1193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    width,
1203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    height;
1213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned short
1233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    planes,
1243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    bits_per_pixel;
1253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
126bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  size_t
1273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    compression,
1283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image_size,
1293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x_pixels,
1303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    y_pixels,
1313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    number_colors,
1323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    red_mask,
1333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    green_mask,
1343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    blue_mask,
1353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    alpha_mask,
1363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    colors_important;
1373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
138bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  ssize_t
1393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    colorspace;
1403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} IconInfo;
1413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
1433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Forward declaractions.
1443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
145501a11e6e582db752c80a35d2444e6a689a400addirkstatic Image
146501a11e6e582db752c80a35d2444e6a689a400addirk  *AutoResizeImage(const Image *,const char *,MagickOffsetType *,
147501a11e6e582db752c80a35d2444e6a689a400addirk    ExceptionInfo *);
148501a11e6e582db752c80a35d2444e6a689a400addirk
1493ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType
1501e178e70fb3c956f9fc1e30c3ba863e882666465cristy  WriteICONImage(const ImageInfo *,Image *,ExceptionInfo *);
151501a11e6e582db752c80a35d2444e6a689a400addirk
152501a11e6e582db752c80a35d2444e6a689a400addirkImage *AutoResizeImage(const Image *image,const char *option,
153501a11e6e582db752c80a35d2444e6a689a400addirk  MagickOffsetType *count,ExceptionInfo *exception)
154501a11e6e582db752c80a35d2444e6a689a400addirk{
155501a11e6e582db752c80a35d2444e6a689a400addirk  #define MAX_SIZES 16
156501a11e6e582db752c80a35d2444e6a689a400addirk
157501a11e6e582db752c80a35d2444e6a689a400addirk  char
158501a11e6e582db752c80a35d2444e6a689a400addirk    *q;
159501a11e6e582db752c80a35d2444e6a689a400addirk
160501a11e6e582db752c80a35d2444e6a689a400addirk  const char
161501a11e6e582db752c80a35d2444e6a689a400addirk    *p;
162501a11e6e582db752c80a35d2444e6a689a400addirk
163501a11e6e582db752c80a35d2444e6a689a400addirk  Image
164501a11e6e582db752c80a35d2444e6a689a400addirk    *resized,
165501a11e6e582db752c80a35d2444e6a689a400addirk    *images;
166501a11e6e582db752c80a35d2444e6a689a400addirk
167501a11e6e582db752c80a35d2444e6a689a400addirk  register ssize_t
168501a11e6e582db752c80a35d2444e6a689a400addirk    i;
169501a11e6e582db752c80a35d2444e6a689a400addirk
170501a11e6e582db752c80a35d2444e6a689a400addirk  size_t
171501a11e6e582db752c80a35d2444e6a689a400addirk    sizes[MAX_SIZES]={256,192,128,96,64,48,40,32,24,16};
172501a11e6e582db752c80a35d2444e6a689a400addirk
173501a11e6e582db752c80a35d2444e6a689a400addirk  images=NULL;
174501a11e6e582db752c80a35d2444e6a689a400addirk  *count=0;
175501a11e6e582db752c80a35d2444e6a689a400addirk  i=0;
176501a11e6e582db752c80a35d2444e6a689a400addirk  p=option;
177501a11e6e582db752c80a35d2444e6a689a400addirk  while (*p != '\0' && i < MAX_SIZES)
178501a11e6e582db752c80a35d2444e6a689a400addirk  {
179501a11e6e582db752c80a35d2444e6a689a400addirk    size_t
180501a11e6e582db752c80a35d2444e6a689a400addirk      size;
181501a11e6e582db752c80a35d2444e6a689a400addirk
182501a11e6e582db752c80a35d2444e6a689a400addirk    while ((isspace((int) ((unsigned char) *p)) != 0))
183501a11e6e582db752c80a35d2444e6a689a400addirk      p++;
184501a11e6e582db752c80a35d2444e6a689a400addirk
185501a11e6e582db752c80a35d2444e6a689a400addirk    size=(size_t)strtol(p,&q,10);
1860f6fc2d5bf8f500820c3dbcf0d23ee14f2d9f734cristy    if ((p == q) || (size < 16) || (size > 256))
1870f6fc2d5bf8f500820c3dbcf0d23ee14f2d9f734cristy      return((Image *) NULL);
188501a11e6e582db752c80a35d2444e6a689a400addirk
189501a11e6e582db752c80a35d2444e6a689a400addirk    p=q;
190501a11e6e582db752c80a35d2444e6a689a400addirk    sizes[i++]=size;
191501a11e6e582db752c80a35d2444e6a689a400addirk
192501a11e6e582db752c80a35d2444e6a689a400addirk    while ((isspace((int) ((unsigned char) *p)) != 0) || (*p == ','))
193501a11e6e582db752c80a35d2444e6a689a400addirk      p++;
194501a11e6e582db752c80a35d2444e6a689a400addirk  }
195501a11e6e582db752c80a35d2444e6a689a400addirk
196501a11e6e582db752c80a35d2444e6a689a400addirk  if (i==0)
197501a11e6e582db752c80a35d2444e6a689a400addirk    i=10;
198501a11e6e582db752c80a35d2444e6a689a400addirk  *count=i;
199501a11e6e582db752c80a35d2444e6a689a400addirk  for (i=0; i < *count; i++)
200501a11e6e582db752c80a35d2444e6a689a400addirk  {
201501a11e6e582db752c80a35d2444e6a689a400addirk    resized=ResizeImage(image,sizes[i],sizes[i],image->filter,exception);
202501a11e6e582db752c80a35d2444e6a689a400addirk    if (resized == (Image *) NULL)
203501a11e6e582db752c80a35d2444e6a689a400addirk      return(DestroyImageList(images));
204501a11e6e582db752c80a35d2444e6a689a400addirk
205501a11e6e582db752c80a35d2444e6a689a400addirk    if (images == (Image *) NULL)
206501a11e6e582db752c80a35d2444e6a689a400addirk      images=resized;
207501a11e6e582db752c80a35d2444e6a689a400addirk    else
208501a11e6e582db752c80a35d2444e6a689a400addirk      AppendImageToList(&images,resized);
209501a11e6e582db752c80a35d2444e6a689a400addirk  }
210501a11e6e582db752c80a35d2444e6a689a400addirk  return(images);
211501a11e6e582db752c80a35d2444e6a689a400addirk}
2123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
2143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e a d I C O N I m a g e                                                 %
2193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ReadICONImage() reads a Microsoft icon image file and returns it.  It
2253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  allocates the memory necessary for the new Image structure and returns a
2263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  pointer to the new image.
2273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the ReadICONImage method is:
2293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      Image *ReadICONImage(const ImageInfo *image_info,
2313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        ExceptionInfo *exception)
2323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
2343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
2363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o exception: return any errors or warnings in this structure.
2383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
2403ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic Image *ReadICONImage(const ImageInfo *image_info,
2413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ExceptionInfo *exception)
2423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
2433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  IconFile
2443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    icon_file;
2453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  IconInfo
2473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    icon_info;
2483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
2503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *image;
2513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
2533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
2543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
255bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
2563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
2573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x;
2583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2594c08aed51c5899665ade97263692328eea4af106cristy  register Quantum
2603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
2613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register unsigned char
2633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
2643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
265bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  size_t
2663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    bit,
267eaedf06777741da32408da72c1e512975c600c48cristy    byte,
2683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    bytes_per_line,
269eaedf06777741da32408da72c1e512975c600c48cristy    one,
2703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    scanline_pad;
2713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
272ebc891a1d9621a19c509200d7bf3470ca18dde7fcristy  ssize_t
273ebc891a1d9621a19c509200d7bf3470ca18dde7fcristy    count,
274ebc891a1d9621a19c509200d7bf3470ca18dde7fcristy    offset,
275ebc891a1d9621a19c509200d7bf3470ca18dde7fcristy    y;
276ebc891a1d9621a19c509200d7bf3470ca18dde7fcristy
2773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
2783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open image file.
2793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
2803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
281e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image_info->signature == MagickCoreSignature);
2823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) LogMagickEvent(CoderEvent,GetMagickModule(),"%s",image_info->filename);
2833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception != (ExceptionInfo *) NULL);
284e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(exception->signature == MagickCoreSignature);
2851f1de1882cd91b3fffd8b701d70fbf0949c6cf50cristy  image=AcquireImage(image_info,exception);
2863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
2873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
2883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
2893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image=DestroyImageList(image);
2903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return((Image *) NULL);
2913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
2923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  icon_file.reserved=(short) ReadBlobLSBShort(image);
2933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  icon_file.resource_type=(short) ReadBlobLSBShort(image);
2943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  icon_file.count=(short) ReadBlobLSBShort(image);
2953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((icon_file.reserved != 0) ||
2963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ((icon_file.resource_type != 1) && (icon_file.resource_type != 2)) ||
2973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (icon_file.count > MaxIcons))
2983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
2993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < icon_file.count; i++)
3003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
3013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    icon_file.directory[i].width=(unsigned char) ReadBlobByte(image);
3023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    icon_file.directory[i].height=(unsigned char) ReadBlobByte(image);
3033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    icon_file.directory[i].colors=(unsigned char) ReadBlobByte(image);
3043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    icon_file.directory[i].reserved=(unsigned char) ReadBlobByte(image);
3053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    icon_file.directory[i].planes=(unsigned short) ReadBlobLSBShort(image);
3063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    icon_file.directory[i].bits_per_pixel=(unsigned short)
3073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ReadBlobLSBShort(image);
3083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    icon_file.directory[i].size=ReadBlobLSBLong(image);
3093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    icon_file.directory[i].offset=ReadBlobLSBLong(image);
3109c4177bdc6ef5bdc0a0c739401eb6f23233a5262cristy    if (EOFBlob(image) != MagickFalse)
311c6c70bb24e8ce03432af9d2149664c46895d17d9Cristy      break;
3123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
313c6c70bb24e8ce03432af9d2149664c46895d17d9Cristy  if (EOFBlob(image) != MagickFalse)
314c6c70bb24e8ce03432af9d2149664c46895d17d9Cristy    ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
315eaedf06777741da32408da72c1e512975c600c48cristy  one=1;
3163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < icon_file.count; i++)
3173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
3183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
3193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Verify Icon identifier.
3203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
3213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    offset=(ssize_t) SeekBlob(image,(MagickOffsetType)
3223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      icon_file.directory[i].offset,SEEK_SET);
3233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (offset < 0)
3243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
3253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    icon_info.size=ReadBlobLSBLong(image);
3261fe0b879964fa7797e3d68574d297922a47c4034Cristy    icon_info.width=(unsigned char) ReadBlobLSBSignedLong(image);
3271fe0b879964fa7797e3d68574d297922a47c4034Cristy    icon_info.height=(unsigned char) (ReadBlobLSBSignedLong(image)/2);
3284e09e0312060a073162b0e5a796495e61fccada5cristy    icon_info.planes=ReadBlobLSBShort(image);
3294e09e0312060a073162b0e5a796495e61fccada5cristy    icon_info.bits_per_pixel=ReadBlobLSBShort(image);
330995156fce3e61f5abb141526dbe707868a1c7a49cristy    if (EOFBlob(image) != MagickFalse)
331995156fce3e61f5abb141526dbe707868a1c7a49cristy      {
332995156fce3e61f5abb141526dbe707868a1c7a49cristy        ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
333995156fce3e61f5abb141526dbe707868a1c7a49cristy          image->filename);
334995156fce3e61f5abb141526dbe707868a1c7a49cristy        break;
335995156fce3e61f5abb141526dbe707868a1c7a49cristy      }
3364360277abefc7141b744bbfbb23218c0249a6e78cristy    if (((icon_info.planes == 18505) && (icon_info.bits_per_pixel == 21060)) ||
3374360277abefc7141b744bbfbb23218c0249a6e78cristy        (icon_info.size == 0x474e5089))
3383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
3393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Image
3403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          *icon_image;
3413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ImageInfo
3433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          *read_info;
3443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
345f054ee74c237471da2f9be084079112f3c89669ccristy        size_t
346f054ee74c237471da2f9be084079112f3c89669ccristy          length;
347f054ee74c237471da2f9be084079112f3c89669ccristy
348f054ee74c237471da2f9be084079112f3c89669ccristy        unsigned char
349f054ee74c237471da2f9be084079112f3c89669ccristy          *png;
350f054ee74c237471da2f9be084079112f3c89669ccristy
3513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
3523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Icon image encoded as a compressed PNG image.
3533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
354f054ee74c237471da2f9be084079112f3c89669ccristy        length=icon_file.directory[i].size;
3550ee195d805aa6f030cd3da8ebc8f9a640b946debdirk        if ((length < 16) || (~length < 16))
3560f6fc2d5bf8f500820c3dbcf0d23ee14f2d9f734cristy          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
3574e09e0312060a073162b0e5a796495e61fccada5cristy        png=(unsigned char *) AcquireQuantumMemory(length+16,sizeof(*png));
358f054ee74c237471da2f9be084079112f3c89669ccristy        if (png == (unsigned char *) NULL)
359f054ee74c237471da2f9be084079112f3c89669ccristy          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
360f054ee74c237471da2f9be084079112f3c89669ccristy        (void) CopyMagickMemory(png,"\211PNG\r\n\032\n\000\000\000\015",12);
3614e09e0312060a073162b0e5a796495e61fccada5cristy        png[12]=(unsigned char) icon_info.planes;
3624e09e0312060a073162b0e5a796495e61fccada5cristy        png[13]=(unsigned char) (icon_info.planes >> 8);
3634e09e0312060a073162b0e5a796495e61fccada5cristy        png[14]=(unsigned char) icon_info.bits_per_pixel;
3644e09e0312060a073162b0e5a796495e61fccada5cristy        png[15]=(unsigned char) (icon_info.bits_per_pixel >> 8);
3654e09e0312060a073162b0e5a796495e61fccada5cristy        count=ReadBlob(image,length-16,png+16);
366833908d4cf871e4104728dfd375eecde76a346f1dirk        icon_image=(Image *) NULL;
367833908d4cf871e4104728dfd375eecde76a346f1dirk        if (count > 0)
368f054ee74c237471da2f9be084079112f3c89669ccristy          {
369833908d4cf871e4104728dfd375eecde76a346f1dirk            read_info=CloneImageInfo(image_info);
370151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy            (void) CopyMagickString(read_info->magick,"PNG",MagickPathExtent);
371833908d4cf871e4104728dfd375eecde76a346f1dirk            icon_image=BlobToImage(read_info,png,length+16,exception);
372833908d4cf871e4104728dfd375eecde76a346f1dirk            read_info=DestroyImageInfo(read_info);
373f054ee74c237471da2f9be084079112f3c89669ccristy          }
374f054ee74c237471da2f9be084079112f3c89669ccristy        png=(unsigned char *) RelinquishMagickMemory(png);
37547de5a9da4464b279806af8f178ceb801bc3fc7acristy        if (icon_image == (Image *) NULL)
3763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
377833908d4cf871e4104728dfd375eecde76a346f1dirk            if (count != (ssize_t) (length-16))
378833908d4cf871e4104728dfd375eecde76a346f1dirk              ThrowReaderException(CorruptImageError,
379833908d4cf871e4104728dfd375eecde76a346f1dirk                "InsufficientImageDataInFile");
38047de5a9da4464b279806af8f178ceb801bc3fc7acristy            image=DestroyImageList(image);
38147de5a9da4464b279806af8f178ceb801bc3fc7acristy            return((Image *) NULL);
3823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
38347de5a9da4464b279806af8f178ceb801bc3fc7acristy        DestroyBlob(icon_image);
38447de5a9da4464b279806af8f178ceb801bc3fc7acristy        icon_image->blob=ReferenceBlob(image->blob);
38547de5a9da4464b279806af8f178ceb801bc3fc7acristy        ReplaceImageInList(&image,icon_image);
3863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
3873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
3883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
389f054ee74c237471da2f9be084079112f3c89669ccristy        if (icon_info.bits_per_pixel > 32)
390f054ee74c237471da2f9be084079112f3c89669ccristy          ThrowReaderException(CorruptImageError,"ImproperImageHeader");
391f054ee74c237471da2f9be084079112f3c89669ccristy        icon_info.compression=ReadBlobLSBLong(image);
392f054ee74c237471da2f9be084079112f3c89669ccristy        icon_info.image_size=ReadBlobLSBLong(image);
393f054ee74c237471da2f9be084079112f3c89669ccristy        icon_info.x_pixels=ReadBlobLSBLong(image);
394f054ee74c237471da2f9be084079112f3c89669ccristy        icon_info.y_pixels=ReadBlobLSBLong(image);
395f054ee74c237471da2f9be084079112f3c89669ccristy        icon_info.number_colors=ReadBlobLSBLong(image);
396f054ee74c237471da2f9be084079112f3c89669ccristy        icon_info.colors_important=ReadBlobLSBLong(image);
3978a46d827a124555f0c48fb2368ec1bba8e079ab6cristy        image->alpha_trait=BlendPixelTrait;
398f054ee74c237471da2f9be084079112f3c89669ccristy        image->columns=(size_t) icon_file.directory[i].width;
399f054ee74c237471da2f9be084079112f3c89669ccristy        if ((ssize_t) image->columns > icon_info.width)
400f054ee74c237471da2f9be084079112f3c89669ccristy          image->columns=(size_t) icon_info.width;
4014e09e0312060a073162b0e5a796495e61fccada5cristy        if (image->columns == 0)
4024e09e0312060a073162b0e5a796495e61fccada5cristy          image->columns=256;
403f054ee74c237471da2f9be084079112f3c89669ccristy        image->rows=(size_t) icon_file.directory[i].height;
404f054ee74c237471da2f9be084079112f3c89669ccristy        if ((ssize_t) image->rows > icon_info.height)
405f054ee74c237471da2f9be084079112f3c89669ccristy          image->rows=(size_t) icon_info.height;
4064e09e0312060a073162b0e5a796495e61fccada5cristy        if (image->rows == 0)
4074e09e0312060a073162b0e5a796495e61fccada5cristy          image->rows=256;
408f054ee74c237471da2f9be084079112f3c89669ccristy        image->depth=icon_info.bits_per_pixel;
409f054ee74c237471da2f9be084079112f3c89669ccristy        if (image->debug != MagickFalse)
410f054ee74c237471da2f9be084079112f3c89669ccristy          {
411f054ee74c237471da2f9be084079112f3c89669ccristy            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
412f054ee74c237471da2f9be084079112f3c89669ccristy              " scene    = %.20g",(double) i);
413f054ee74c237471da2f9be084079112f3c89669ccristy            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
414f054ee74c237471da2f9be084079112f3c89669ccristy              "   size   = %.20g",(double) icon_info.size);
415f054ee74c237471da2f9be084079112f3c89669ccristy            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
416f054ee74c237471da2f9be084079112f3c89669ccristy              "   width  = %.20g",(double) icon_file.directory[i].width);
417f054ee74c237471da2f9be084079112f3c89669ccristy            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
418f054ee74c237471da2f9be084079112f3c89669ccristy              "   height = %.20g",(double) icon_file.directory[i].height);
419f054ee74c237471da2f9be084079112f3c89669ccristy            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
420f054ee74c237471da2f9be084079112f3c89669ccristy              "   colors = %.20g",(double ) icon_info.number_colors);
421f054ee74c237471da2f9be084079112f3c89669ccristy            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
422f054ee74c237471da2f9be084079112f3c89669ccristy              "   planes = %.20g",(double) icon_info.planes);
423f054ee74c237471da2f9be084079112f3c89669ccristy            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
424f054ee74c237471da2f9be084079112f3c89669ccristy              "   bpp    = %.20g",(double) icon_info.bits_per_pixel);
425f054ee74c237471da2f9be084079112f3c89669ccristy          }
426a2fb29a72ee8d5293e0980c026d2555c482d04e8cristy      if ((icon_info.number_colors != 0) || (icon_info.bits_per_pixel <= 16U))
427f054ee74c237471da2f9be084079112f3c89669ccristy        {
428f054ee74c237471da2f9be084079112f3c89669ccristy          image->storage_class=PseudoClass;
429f054ee74c237471da2f9be084079112f3c89669ccristy          image->colors=icon_info.number_colors;
430f054ee74c237471da2f9be084079112f3c89669ccristy          if (image->colors == 0)
431f054ee74c237471da2f9be084079112f3c89669ccristy            image->colors=one << icon_info.bits_per_pixel;
432f054ee74c237471da2f9be084079112f3c89669ccristy        }
433f054ee74c237471da2f9be084079112f3c89669ccristy      if (image->storage_class == PseudoClass)
434f054ee74c237471da2f9be084079112f3c89669ccristy        {
435f054ee74c237471da2f9be084079112f3c89669ccristy          register ssize_t
436f054ee74c237471da2f9be084079112f3c89669ccristy            i;
437f054ee74c237471da2f9be084079112f3c89669ccristy
438f054ee74c237471da2f9be084079112f3c89669ccristy          unsigned char
439f054ee74c237471da2f9be084079112f3c89669ccristy            *icon_colormap;
440ebc891a1d9621a19c509200d7bf3470ca18dde7fcristy
441f054ee74c237471da2f9be084079112f3c89669ccristy          /*
442f054ee74c237471da2f9be084079112f3c89669ccristy            Read Icon raster colormap.
443f054ee74c237471da2f9be084079112f3c89669ccristy          */
444833908d4cf871e4104728dfd375eecde76a346f1dirk          if (AcquireImageColormap(image,image->colors,exception) ==
445833908d4cf871e4104728dfd375eecde76a346f1dirk              MagickFalse)
446f054ee74c237471da2f9be084079112f3c89669ccristy            ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
447f054ee74c237471da2f9be084079112f3c89669ccristy          icon_colormap=(unsigned char *) AcquireQuantumMemory((size_t)
448f054ee74c237471da2f9be084079112f3c89669ccristy            image->colors,4UL*sizeof(*icon_colormap));
449f054ee74c237471da2f9be084079112f3c89669ccristy          if (icon_colormap == (unsigned char *) NULL)
450f054ee74c237471da2f9be084079112f3c89669ccristy            ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
451f054ee74c237471da2f9be084079112f3c89669ccristy          count=ReadBlob(image,(size_t) (4*image->colors),icon_colormap);
452f054ee74c237471da2f9be084079112f3c89669ccristy          if (count != (ssize_t) (4*image->colors))
453f054ee74c237471da2f9be084079112f3c89669ccristy            ThrowReaderException(CorruptImageError,
454f054ee74c237471da2f9be084079112f3c89669ccristy              "InsufficientImageDataInFile");
455f054ee74c237471da2f9be084079112f3c89669ccristy          p=icon_colormap;
456f054ee74c237471da2f9be084079112f3c89669ccristy          for (i=0; i < (ssize_t) image->colors; i++)
457f054ee74c237471da2f9be084079112f3c89669ccristy          {
458f054ee74c237471da2f9be084079112f3c89669ccristy            image->colormap[i].blue=(Quantum) ScaleCharToQuantum(*p++);
459f054ee74c237471da2f9be084079112f3c89669ccristy            image->colormap[i].green=(Quantum) ScaleCharToQuantum(*p++);
460f054ee74c237471da2f9be084079112f3c89669ccristy            image->colormap[i].red=(Quantum) ScaleCharToQuantum(*p++);
461f054ee74c237471da2f9be084079112f3c89669ccristy            p++;
462f054ee74c237471da2f9be084079112f3c89669ccristy          }
463f054ee74c237471da2f9be084079112f3c89669ccristy          icon_colormap=(unsigned char *) RelinquishMagickMemory(icon_colormap);
464f054ee74c237471da2f9be084079112f3c89669ccristy        }
4653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
4663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Convert Icon raster image to pixel packets.
4673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
468f054ee74c237471da2f9be084079112f3c89669ccristy        if ((image_info->ping != MagickFalse) &&
469f054ee74c237471da2f9be084079112f3c89669ccristy            (image_info->number_scenes != 0))
470f054ee74c237471da2f9be084079112f3c89669ccristy          if (image->scene >= (image_info->scene+image_info->number_scenes-1))
471f054ee74c237471da2f9be084079112f3c89669ccristy            break;
472acabb847a592ca5e430c1c0949d03acfc0b78bb9cristy        status=SetImageExtent(image,image->columns,image->rows,exception);
473acabb847a592ca5e430c1c0949d03acfc0b78bb9cristy        if (status == MagickFalse)
474acabb847a592ca5e430c1c0949d03acfc0b78bb9cristy          return(DestroyImageList(image));
4753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        bytes_per_line=(((image->columns*icon_info.bits_per_pixel)+31) &
4763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ~31) >> 3;
477da16f16767eb31921af855f17bda465fffc4e000cristy        (void) bytes_per_line;
4783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        scanline_pad=((((image->columns*icon_info.bits_per_pixel)+31) & ~31)-
4793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (image->columns*icon_info.bits_per_pixel)) >> 3;
4803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        switch (icon_info.bits_per_pixel)
4813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
4823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 1:
4833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
4843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
4853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Convert bitmap scanline.
4863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
487bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            for (y=(ssize_t) image->rows-1; y >= 0; y--)
4883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
4893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
490acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy              if (q == (Quantum *) NULL)
4913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
492bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < (ssize_t) (image->columns-7); x+=8)
4933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
494f054ee74c237471da2f9be084079112f3c89669ccristy                byte=(size_t) ReadBlobByte(image);
4953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                for (bit=0; bit < 8; bit++)
4964c08aed51c5899665ade97263692328eea4af106cristy                {
4974c08aed51c5899665ade97263692328eea4af106cristy                  SetPixelIndex(image,((byte & (0x80 >> bit)) != 0 ? 0x01 :
4984c08aed51c5899665ade97263692328eea4af106cristy                    0x00),q);
499ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                  q+=GetPixelChannels(image);
5004c08aed51c5899665ade97263692328eea4af106cristy                }
5013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
5023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if ((image->columns % 8) != 0)
5033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
504f054ee74c237471da2f9be084079112f3c89669ccristy                  byte=(size_t) ReadBlobByte(image);
5053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  for (bit=0; bit < (image->columns % 8); bit++)
5064c08aed51c5899665ade97263692328eea4af106cristy                  {
5074c08aed51c5899665ade97263692328eea4af106cristy                    SetPixelIndex(image,((byte & (0x80 >> bit)) != 0 ? 0x01 :
5084c08aed51c5899665ade97263692328eea4af106cristy                      0x00),q);
509ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                    q+=GetPixelChannels(image);
5104c08aed51c5899665ade97263692328eea4af106cristy                  }
5113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
512bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < (ssize_t) scanline_pad; x++)
513f054ee74c237471da2f9be084079112f3c89669ccristy                (void) ReadBlobByte(image);
5143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (SyncAuthenticPixels(image,exception) == MagickFalse)
5153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
5163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (image->previous == (Image *) NULL)
5173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
5183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  status=SetImageProgress(image,LoadImageTag,image->rows-y-1,
5193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image->rows);
5203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (status == MagickFalse)
5213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    break;
5223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
5233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
5243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
5253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
5263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 4:
5273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
5283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
5293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Read 4-bit Icon scanline.
5303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
531bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            for (y=(ssize_t) image->rows-1; y >= 0; y--)
5323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
5333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
534acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy              if (q == (Quantum *) NULL)
5353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
536bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < ((ssize_t) image->columns-1); x+=2)
5373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
538f054ee74c237471da2f9be084079112f3c89669ccristy                byte=(size_t) ReadBlobByte(image);
5394c08aed51c5899665ade97263692328eea4af106cristy                SetPixelIndex(image,((byte >> 4) & 0xf),q);
540ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                q+=GetPixelChannels(image);
5414c08aed51c5899665ade97263692328eea4af106cristy                SetPixelIndex(image,((byte) & 0xf),q);
542ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                q+=GetPixelChannels(image);
5433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
5443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if ((image->columns % 2) != 0)
5453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
546f054ee74c237471da2f9be084079112f3c89669ccristy                  byte=(size_t) ReadBlobByte(image);
5474c08aed51c5899665ade97263692328eea4af106cristy                  SetPixelIndex(image,((byte >> 4) & 0xf),q);
548ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                  q+=GetPixelChannels(image);
5493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
550bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < (ssize_t) scanline_pad; x++)
551f054ee74c237471da2f9be084079112f3c89669ccristy                (void) ReadBlobByte(image);
5523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (SyncAuthenticPixels(image,exception) == MagickFalse)
5533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
5543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (image->previous == (Image *) NULL)
5553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
5563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  status=SetImageProgress(image,LoadImageTag,image->rows-y-1,
5573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image->rows);
5583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (status == MagickFalse)
5593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    break;
5603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
5613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
5623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
5633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
5643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 8:
5653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
5663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
5673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Convert PseudoColor scanline.
5683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
569bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            for (y=(ssize_t) image->rows-1; y >= 0; y--)
5703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
5713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
572acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy              if (q == (Quantum *) NULL)
5733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
574bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < (ssize_t) image->columns; x++)
5753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
576f054ee74c237471da2f9be084079112f3c89669ccristy                byte=(size_t) ReadBlobByte(image);
5771678aec3bf3630d92b415d39a58f049c16ac055cdirk                SetPixelIndex(image,(Quantum) byte,q);
578ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                q+=GetPixelChannels(image);
5793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
580bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < (ssize_t) scanline_pad; x++)
581f054ee74c237471da2f9be084079112f3c89669ccristy                (void) ReadBlobByte(image);
5823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (SyncAuthenticPixels(image,exception) == MagickFalse)
5833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
5843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (image->previous == (Image *) NULL)
5853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
5863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  status=SetImageProgress(image,LoadImageTag,image->rows-y-1,
5873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image->rows);
5883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (status == MagickFalse)
5893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    break;
5903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
5913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
5923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
5933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
5943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 16:
5953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
5963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
5973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Convert PseudoColor scanline.
5983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
599bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            for (y=(ssize_t) image->rows-1; y >= 0; y--)
6003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
6013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
602acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy              if (q == (Quantum *) NULL)
6033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
604bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < (ssize_t) image->columns; x++)
6053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
606f054ee74c237471da2f9be084079112f3c89669ccristy                byte=(size_t) ReadBlobByte(image);
607f054ee74c237471da2f9be084079112f3c89669ccristy                byte|=(size_t) (ReadBlobByte(image) << 8);
6081678aec3bf3630d92b415d39a58f049c16ac055cdirk                SetPixelIndex(image,(Quantum) byte,q);
609ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                q+=GetPixelChannels(image);
6103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
611bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < (ssize_t) scanline_pad; x++)
612f054ee74c237471da2f9be084079112f3c89669ccristy                (void) ReadBlobByte(image);
6133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (SyncAuthenticPixels(image,exception) == MagickFalse)
6143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
6153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (image->previous == (Image *) NULL)
6163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
6173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  status=SetImageProgress(image,LoadImageTag,image->rows-y-1,
6183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image->rows);
6193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (status == MagickFalse)
6203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    break;
6213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
6223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
6233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
6243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
6253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 24:
6263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 32:
6273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
6283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
6293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Convert DirectColor scanline.
6303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
631bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            for (y=(ssize_t) image->rows-1; y >= 0; y--)
6323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
6333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
634acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy              if (q == (Quantum *) NULL)
6353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
636bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < (ssize_t) image->columns; x++)
6373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
638f054ee74c237471da2f9be084079112f3c89669ccristy                SetPixelBlue(image,ScaleCharToQuantum((unsigned char)
639f054ee74c237471da2f9be084079112f3c89669ccristy                  ReadBlobByte(image)),q);
640f054ee74c237471da2f9be084079112f3c89669ccristy                SetPixelGreen(image,ScaleCharToQuantum((unsigned char)
641f054ee74c237471da2f9be084079112f3c89669ccristy                  ReadBlobByte(image)),q);
642f054ee74c237471da2f9be084079112f3c89669ccristy                SetPixelRed(image,ScaleCharToQuantum((unsigned char)
643f054ee74c237471da2f9be084079112f3c89669ccristy                  ReadBlobByte(image)),q);
6443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (icon_info.bits_per_pixel == 32)
645f054ee74c237471da2f9be084079112f3c89669ccristy                  SetPixelAlpha(image,ScaleCharToQuantum((unsigned char)
646f054ee74c237471da2f9be084079112f3c89669ccristy                    ReadBlobByte(image)),q);
647ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                q+=GetPixelChannels(image);
6483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
6493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (icon_info.bits_per_pixel == 24)
650bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy                for (x=0; x < (ssize_t) scanline_pad; x++)
651f054ee74c237471da2f9be084079112f3c89669ccristy                  (void) ReadBlobByte(image);
6523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (SyncAuthenticPixels(image,exception) == MagickFalse)
6533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
6543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (image->previous == (Image *) NULL)
6553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
6563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  status=SetImageProgress(image,LoadImageTag,image->rows-y-1,
6573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image->rows);
6583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (status == MagickFalse)
6593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    break;
6603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
6613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
6623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
6633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
6643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          default:
6653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            ThrowReaderException(CorruptImageError,"ImproperImageHeader");
6663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
667e0fe9894bff65028bea71df2bf6a4cd63da28c9eCristy        if ((image_info->ping == MagickFalse) &&
668e0fe9894bff65028bea71df2bf6a4cd63da28c9eCristy            (icon_info.bits_per_pixel <= 16))
669ea1a8aa04a9fe1500104284407c1cc06d20da699cristy          (void) SyncImage(image,exception);
6703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (icon_info.bits_per_pixel != 32)
6713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
6723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
6733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Read the ICON alpha mask.
6743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
6753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->storage_class=DirectClass;
676bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            for (y=(ssize_t) image->rows-1; y >= 0; y--)
6773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
6783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
679acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy              if (q == (Quantum *) NULL)
6803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
681bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < ((ssize_t) image->columns-7); x+=8)
6823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
683f054ee74c237471da2f9be084079112f3c89669ccristy                byte=(size_t) ReadBlobByte(image);
6843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                for (bit=0; bit < 8; bit++)
6854c08aed51c5899665ade97263692328eea4af106cristy                {
6864c08aed51c5899665ade97263692328eea4af106cristy                  SetPixelAlpha(image,(((byte & (0x80 >> bit)) != 0) ?
6874c08aed51c5899665ade97263692328eea4af106cristy                    TransparentAlpha : OpaqueAlpha),q);
688ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                  q+=GetPixelChannels(image);
6894c08aed51c5899665ade97263692328eea4af106cristy                }
6903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
6913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if ((image->columns % 8) != 0)
6923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
693f054ee74c237471da2f9be084079112f3c89669ccristy                  byte=(size_t) ReadBlobByte(image);
6943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  for (bit=0; bit < (image->columns % 8); bit++)
6954c08aed51c5899665ade97263692328eea4af106cristy                  {
6964c08aed51c5899665ade97263692328eea4af106cristy                    SetPixelAlpha(image,(((byte & (0x80 >> bit)) != 0) ?
6974c08aed51c5899665ade97263692328eea4af106cristy                      TransparentAlpha : OpaqueAlpha),q);
698ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                    q+=GetPixelChannels(image);
6994c08aed51c5899665ade97263692328eea4af106cristy                  }
7003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
7010e8200f78c4cb859725d32da48fcaf6f41f6ca02cristy              if ((image->columns % 32) != 0)
702bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy                for (x=0; x < (ssize_t) ((32-(image->columns % 32))/8); x++)
703f054ee74c237471da2f9be084079112f3c89669ccristy                  (void) ReadBlobByte(image);
7043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (SyncAuthenticPixels(image,exception) == MagickFalse)
7053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
7063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
7073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
7083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (EOFBlob(image) != MagickFalse)
7093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
7103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            ThrowFileException(exception,CorruptImageError,
7113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              "UnexpectedEndOfFile",image->filename);
7123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
7133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
7143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
7153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
7163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Proceed to next image.
7173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
7183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (image_info->number_scenes != 0)
7193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
7203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        break;
721bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    if (i < (ssize_t) (icon_file.count-1))
7223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
7233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
7243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Allocate next image structure.
7253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
7261f1de1882cd91b3fffd8b701d70fbf0949c6cf50cristy        AcquireNextImage(image_info,image,exception);
7273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (GetNextImageInList(image) == (Image *) NULL)
7283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
7293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image=DestroyImageList(image);
7303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            return((Image *) NULL);
7313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
7323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image=SyncNextImageInList(image);
7333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
7343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          GetBlobSize(image));
7353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (status == MagickFalse)
7363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
7373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
7383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
7393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(image);
7403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(GetFirstImageInList(image));
7413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
7423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
7443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e g i s t e r I C O N I m a g e                                         %
7493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  RegisterICONImage() adds attributes for the Icon image format to
7553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  the list of supported formats.  The attributes include the image format
7563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  tag, a method to read and/or write the format, whether the format
7573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  supports the saving of more than one frame to the same file or blob,
7583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  whether the format supports native in-memory I/O, and a brief
7593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  description of the format.
7603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the RegisterICONImage method is:
7623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
763bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy%      size_t RegisterICONImage(void)
7643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
766bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristyModuleExport size_t RegisterICONImage(void)
7673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
7683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickInfo
7693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *entry;
7703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
77106b627a07ff44e1ff93ef1288c9f428066ded10ddirk  entry=AcquireMagickInfo("ICON","CUR","Microsoft icon");
7723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadICONImage;
7733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WriteICONImage;
77408e9a113db499034abb5ad8d59b42f8eca3c641cdirk  entry->flags^=CoderAdjoinFlag;
77508e9a113db499034abb5ad8d59b42f8eca3c641cdirk  entry->flags|=CoderSeekableStreamFlag;
7763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
77706b627a07ff44e1ff93ef1288c9f428066ded10ddirk  entry=AcquireMagickInfo("ICON","ICO","Microsoft icon");
7783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadICONImage;
7793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WriteICONImage;
78008e9a113db499034abb5ad8d59b42f8eca3c641cdirk  entry->flags|=CoderSeekableStreamFlag;
7813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
78206b627a07ff44e1ff93ef1288c9f428066ded10ddirk  entry=AcquireMagickInfo("ICON","ICON","Microsoft icon");
7833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadICONImage;
7843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WriteICONImage;
78508e9a113db499034abb5ad8d59b42f8eca3c641cdirk  entry->flags^=CoderAdjoinFlag;
78608e9a113db499034abb5ad8d59b42f8eca3c641cdirk  entry->flags|=CoderSeekableStreamFlag;
7873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
7883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickImageCoderSignature);
7893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
7903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
7923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   U n r e g i s t e r I C O N I m a g e                                     %
7973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  UnregisterICONImage() removes format registrations made by the
8033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ICON module from the list of supported formats.
8043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the UnregisterICONImage method is:
8063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      UnregisterICONImage(void)
8083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
8103ed852eea50f9d4cd633efb8c2b054b8e33c253cristyModuleExport void UnregisterICONImage(void)
8113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
8123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("CUR");
8133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("ICO");
8143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("ICON");
8153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
8163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
8183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   W r i t e I C O N I m a g e                                               %
8233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  WriteICONImage() writes an image in Microsoft Windows bitmap encoded
8293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  image format, version 3 for Windows or (if the image has a matte channel)
8303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  version 4.
8313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
83283cb91e7f3699606809533d7bc76db69d3ea167dcristy%  It encodes any subimage as a compressed PNG image ("BI_PNG)", only when its
83383cb91e7f3699606809533d7bc76db69d3ea167dcristy%  dimensions are 256x256 and image->compression is undefined or is defined as
83483cb91e7f3699606809533d7bc76db69d3ea167dcristy%  ZipCompression.
8354b708b85d92f5ee5e5996b1b019b45136e45e33aglennrp%
8363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the WriteICONImage method is:
8373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType WriteICONImage(const ImageInfo *image_info,
8391e178e70fb3c956f9fc1e30c3ba863e882666465cristy%        Image *image,ExceptionInfo *exception)
8403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows.
8423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
8443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image:  The image.
8463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8471e178e70fb3c956f9fc1e30c3ba863e882666465cristy%    o exception: return any errors or warnings in this structure.
8481e178e70fb3c956f9fc1e30c3ba863e882666465cristy%
8493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
8503ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType WriteICONImage(const ImageInfo *image_info,
8511e178e70fb3c956f9fc1e30c3ba863e882666465cristy  Image *image,ExceptionInfo *exception)
8523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
853501a11e6e582db752c80a35d2444e6a689a400addirk  const char
854501a11e6e582db752c80a35d2444e6a689a400addirk    *option;
855501a11e6e582db752c80a35d2444e6a689a400addirk
8563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  IconFile
8573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    icon_file;
8583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  IconInfo
8603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    icon_info;
8613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
8639e137706f4a1f40d099c597992f43cd3fba033a7dirk    *images,
8643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *next;
8653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
8673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
8683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickOffsetType
8703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    offset,
8713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    scene;
8723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8734c08aed51c5899665ade97263692328eea4af106cristy  register const Quantum
8743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
8753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
876bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
8773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
8783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x;
8793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register unsigned char
8813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
8823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
883ebc891a1d9621a19c509200d7bf3470ca18dde7fcristy  size_t
884ebc891a1d9621a19c509200d7bf3470ca18dde7fcristy    bytes_per_line,
885ebc891a1d9621a19c509200d7bf3470ca18dde7fcristy    scanline_pad;
886ebc891a1d9621a19c509200d7bf3470ca18dde7fcristy
887ebc891a1d9621a19c509200d7bf3470ca18dde7fcristy  ssize_t
888ebc891a1d9621a19c509200d7bf3470ca18dde7fcristy    y;
889ebc891a1d9621a19c509200d7bf3470ca18dde7fcristy
8903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned char
8913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    bit,
8923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    byte,
8933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *pixels;
8943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
8963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open output image file.
8973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
8983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
899e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image_info->signature == MagickCoreSignature);
9003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
901e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image->signature == MagickCoreSignature);
9023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),"%s",image->filename);
9033a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  assert(exception != (ExceptionInfo *) NULL);
904e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(exception->signature == MagickCoreSignature);
9051e178e70fb3c956f9fc1e30c3ba863e882666465cristy  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
9063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
9073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(status);
9089e137706f4a1f40d099c597992f43cd3fba033a7dirk  images=(Image *) NULL;
909501a11e6e582db752c80a35d2444e6a689a400addirk  option=GetImageOption(image_info,"icon:auto-resize");
910501a11e6e582db752c80a35d2444e6a689a400addirk  if (option != (const char *) NULL)
9119e137706f4a1f40d099c597992f43cd3fba033a7dirk    {
912501a11e6e582db752c80a35d2444e6a689a400addirk      images=AutoResizeImage(image,option,&scene,exception);
9139e137706f4a1f40d099c597992f43cd3fba033a7dirk      if (images == (Image *) NULL)
914501a11e6e582db752c80a35d2444e6a689a400addirk        ThrowWriterException(ImageError,"InvalidDimensions");
9159e137706f4a1f40d099c597992f43cd3fba033a7dirk    }
9169e137706f4a1f40d099c597992f43cd3fba033a7dirk  else
9179e137706f4a1f40d099c597992f43cd3fba033a7dirk    {
9189e137706f4a1f40d099c597992f43cd3fba033a7dirk      scene=0;
9199e137706f4a1f40d099c597992f43cd3fba033a7dirk      next=image;
9209e137706f4a1f40d099c597992f43cd3fba033a7dirk      do
9219e137706f4a1f40d099c597992f43cd3fba033a7dirk      {
9229e137706f4a1f40d099c597992f43cd3fba033a7dirk        if ((image->columns > 256L) || (image->rows > 256L))
9239e137706f4a1f40d099c597992f43cd3fba033a7dirk          ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
9249e137706f4a1f40d099c597992f43cd3fba033a7dirk        scene++;
9259e137706f4a1f40d099c597992f43cd3fba033a7dirk        next=SyncNextImageInList(next);
9269e137706f4a1f40d099c597992f43cd3fba033a7dirk      } while ((next != (Image *) NULL) && (image_info->adjoin != MagickFalse));
9279e137706f4a1f40d099c597992f43cd3fba033a7dirk    }
9283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
9293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Dump out a ICON header template to be properly initialized later.
9303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
9313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobLSBShort(image,0);
9323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobLSBShort(image,1);
9333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobLSBShort(image,(unsigned char) scene);
9343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ResetMagickMemory(&icon_file,0,sizeof(icon_file));
9353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ResetMagickMemory(&icon_info,0,sizeof(icon_info));
9363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  scene=0;
9379e137706f4a1f40d099c597992f43cd3fba033a7dirk  next=(images != (Image *) NULL) ? images : image;
9383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  do
9393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
9403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(image,icon_file.directory[scene].width);
9413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(image,icon_file.directory[scene].height);
9423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(image,icon_file.directory[scene].colors);
9433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(image,icon_file.directory[scene].reserved);
9443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobLSBShort(image,icon_file.directory[scene].planes);
9453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobLSBShort(image,icon_file.directory[scene].bits_per_pixel);
9460b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy    (void) WriteBlobLSBLong(image,(unsigned int)
9470b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy      icon_file.directory[scene].size);
9480b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy    (void) WriteBlobLSBLong(image,(unsigned int)
9490b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy      icon_file.directory[scene].offset);
9503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    scene++;
9513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    next=SyncNextImageInList(next);
9523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  } while ((next != (Image *) NULL) && (image_info->adjoin != MagickFalse));
9533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  scene=0;
9549e137706f4a1f40d099c597992f43cd3fba033a7dirk  next=(images != (Image *) NULL) ? images : image;
9553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  do
9563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
9574b708b85d92f5ee5e5996b1b019b45136e45e33aglennrp    if ((next->columns > 255L) && (next->rows > 255L) &&
9584b708b85d92f5ee5e5996b1b019b45136e45e33aglennrp        ((next->compression == UndefinedCompression) ||
9594b708b85d92f5ee5e5996b1b019b45136e45e33aglennrp        (next->compression == ZipCompression)))
9603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
9613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Image
9623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          *write_image;
9633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ImageInfo
9653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          *write_info;
9663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        size_t
9683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          length;
9693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        unsigned char
9713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          *png;
9723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9731e178e70fb3c956f9fc1e30c3ba863e882666465cristy        write_image=CloneImage(next,0,0,MagickTrue,exception);
974c1e5200dbc332719a205fc2cf6004fa90258cfcbdirk        if (write_image == (Image *) NULL)
975c1e5200dbc332719a205fc2cf6004fa90258cfcbdirk          {
976c1e5200dbc332719a205fc2cf6004fa90258cfcbdirk            images=DestroyImageList(images);
977c1e5200dbc332719a205fc2cf6004fa90258cfcbdirk            return(MagickFalse);
9789e137706f4a1f40d099c597992f43cd3fba033a7dirk          }
9793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        write_info=CloneImageInfo(image_info);
980151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy        (void) CopyMagickString(write_info->filename,"PNG:",MagickPathExtent);
9814b708b85d92f5ee5e5996b1b019b45136e45e33aglennrp
9824b708b85d92f5ee5e5996b1b019b45136e45e33aglennrp        /* Don't write any ancillary chunks except for gAMA */
9834b708b85d92f5ee5e5996b1b019b45136e45e33aglennrp        (void) SetImageArtifact(write_image,"png:include-chunk","none,gama");
9844b708b85d92f5ee5e5996b1b019b45136e45e33aglennrp
9854b708b85d92f5ee5e5996b1b019b45136e45e33aglennrp        /* Only write PNG32 formatted PNG (32-bit RGBA), 8 bits per channel */
9864b708b85d92f5ee5e5996b1b019b45136e45e33aglennrp        (void) SetImageArtifact(write_image,"png:format","png32");
9874b708b85d92f5ee5e5996b1b019b45136e45e33aglennrp
9883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        png=(unsigned char *) ImageToBlob(write_info,write_image,&length,
9891e178e70fb3c956f9fc1e30c3ba863e882666465cristy          exception);
99015bc0d69cbb71ae6839b49361de19e0fd56985d9Cristy        write_image=DestroyImageList(write_image);
9913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        write_info=DestroyImageInfo(write_info);
992c1e5200dbc332719a205fc2cf6004fa90258cfcbdirk        if (png == (unsigned char *) NULL)
993c1e5200dbc332719a205fc2cf6004fa90258cfcbdirk          {
994c1e5200dbc332719a205fc2cf6004fa90258cfcbdirk            images=DestroyImageList(images);
995c1e5200dbc332719a205fc2cf6004fa90258cfcbdirk            return(MagickFalse);
9969e137706f4a1f40d099c597992f43cd3fba033a7dirk          }
9973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_file.directory[scene].width=0;
9983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_file.directory[scene].height=0;
9993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_file.directory[scene].colors=0;
10003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_file.directory[scene].reserved=0;
10013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_file.directory[scene].planes=1;
10023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_file.directory[scene].bits_per_pixel=32;
1003bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        icon_file.directory[scene].size=(size_t) length;
1004bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        icon_file.directory[scene].offset=(size_t) TellBlob(image);
10053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) WriteBlob(image,(size_t) length,png);
10063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        png=(unsigned char *) RelinquishMagickMemory(png);
10073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
10083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
10093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
10103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
10113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Initialize ICON raster file header.
10123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
1013af8d391906d11f0a1f2bbf4e2adbc4995c852d33cristy        (void) TransformImageColorspace(next,sRGBColorspace,exception);
10143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.file_size=14+12+28;
10153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.offset_bits=icon_info.file_size;
10163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.compression=BI_RGB;
10173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if ((next->storage_class != DirectClass) && (next->colors > 256))
10181e178e70fb3c956f9fc1e30c3ba863e882666465cristy          (void) SetImageStorageClass(next,DirectClass,exception);
10193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (next->storage_class == DirectClass)
10203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
10213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
10223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Full color ICON raster.
10233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
10243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            icon_info.number_colors=0;
10253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            icon_info.bits_per_pixel=32;
1026bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            icon_info.compression=(size_t) BI_RGB;
10273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
10283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        else
10293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
103035ef824baa82511126ff0072ae30eee0da9c05a3cristy            size_t
103135ef824baa82511126ff0072ae30eee0da9c05a3cristy              one;
103235ef824baa82511126ff0072ae30eee0da9c05a3cristy
10333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
10343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Colormapped ICON raster.
10353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
10363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            icon_info.bits_per_pixel=8;
10373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (next->colors <= 256)
10383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              icon_info.bits_per_pixel=8;
10393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (next->colors <= 16)
10403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              icon_info.bits_per_pixel=4;
10413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (next->colors <= 2)
10423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              icon_info.bits_per_pixel=1;
104335ef824baa82511126ff0072ae30eee0da9c05a3cristy            one=1;
104435ef824baa82511126ff0072ae30eee0da9c05a3cristy            icon_info.number_colors=one << icon_info.bits_per_pixel;
10453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (icon_info.number_colors < next->colors)
10463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
10471e178e70fb3c956f9fc1e30c3ba863e882666465cristy                (void) SetImageStorageClass(next,DirectClass,exception);
10483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                icon_info.number_colors=0;
10493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                icon_info.bits_per_pixel=(unsigned short) 24;
1050bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy                icon_info.compression=(size_t) BI_RGB;
10513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
10523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
10533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
10540b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy                size_t
10550b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy                  one;
10560b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy
10570b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy                one=1;
10580b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy                icon_info.file_size+=3*(one << icon_info.bits_per_pixel);
10590b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy                icon_info.offset_bits+=3*(one << icon_info.bits_per_pixel);
10600b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy                icon_info.file_size+=(one << icon_info.bits_per_pixel);
10610b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy                icon_info.offset_bits+=(one << icon_info.bits_per_pixel);
10623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
10633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
10643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        bytes_per_line=(((next->columns*icon_info.bits_per_pixel)+31) &
10653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ~31) >> 3;
10663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.ba_offset=0;
1067bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        icon_info.width=(ssize_t) next->columns;
1068bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        icon_info.height=(ssize_t) next->rows;
10693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.planes=1;
10703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.image_size=bytes_per_line*next->rows;
10713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.size=40;
10723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.size+=(4*icon_info.number_colors);
10733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.size+=icon_info.image_size;
10743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.size+=(((icon_info.width+31) & ~31) >> 3)*icon_info.height;
10753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.file_size+=icon_info.image_size;
10763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.x_pixels=0;
10773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.y_pixels=0;
10783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        switch (next->units)
10793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
10803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case UndefinedResolution:
10813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case PixelsPerInchResolution:
10823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
10832a11befa48257796843468409d77bb8cfb129cdccristy            icon_info.x_pixels=(size_t) (100.0*next->resolution.x/2.54);
10842a11befa48257796843468409d77bb8cfb129cdccristy            icon_info.y_pixels=(size_t) (100.0*next->resolution.y/2.54);
10853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
10863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
10873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case PixelsPerCentimeterResolution:
10883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
10892a11befa48257796843468409d77bb8cfb129cdccristy            icon_info.x_pixels=(size_t) (100.0*next->resolution.x);
10902a11befa48257796843468409d77bb8cfb129cdccristy            icon_info.y_pixels=(size_t) (100.0*next->resolution.y);
10913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
10923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
10933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
10943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.colors_important=icon_info.number_colors;
10953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
10963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Convert MIFF to ICON raster pixels.
10973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
10983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixels=(unsigned char *) AcquireQuantumMemory((size_t)
10993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          icon_info.image_size,sizeof(*pixels));
1100c1e5200dbc332719a205fc2cf6004fa90258cfcbdirk        if (pixels == (unsigned char *) NULL)
1101c1e5200dbc332719a205fc2cf6004fa90258cfcbdirk          {
11029e137706f4a1f40d099c597992f43cd3fba033a7dirk            images=DestroyImageList(images);
11039e137706f4a1f40d099c597992f43cd3fba033a7dirk            ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1104c1e5200dbc332719a205fc2cf6004fa90258cfcbdirk          }
11053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) ResetMagickMemory(pixels,0,(size_t) icon_info.image_size);
11063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        switch (icon_info.bits_per_pixel)
11073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
11083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 1:
11093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
1110bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            size_t
11113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              bit,
11123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              byte;
11133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
11143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
11153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Convert PseudoClass image to a ICON monochrome image.
11163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
1117bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            for (y=0; y < (ssize_t) next->rows; y++)
11183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
11191e178e70fb3c956f9fc1e30c3ba863e882666465cristy              p=GetVirtualPixels(next,0,y,next->columns,1,exception);
11204c08aed51c5899665ade97263692328eea4af106cristy              if (p == (const Quantum *) NULL)
11213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
11223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              q=pixels+(next->rows-y-1)*bytes_per_line;
11233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              bit=0;
11243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              byte=0;
1125bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < (ssize_t) next->columns; x++)
11263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
11273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                byte<<=1;
11284c08aed51c5899665ade97263692328eea4af106cristy                byte|=GetPixelIndex(next,p) != 0 ? 0x01 : 0x00;
11293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                bit++;
11303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (bit == 8)
11313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
11323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    *q++=(unsigned char) byte;
11333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    bit=0;
11343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    byte=0;
11353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  }
1136ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                p+=GetPixelChannels(image);
11374c08aed51c5899665ade97263692328eea4af106cristy              }
11383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (bit != 0)
11393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                *q++=(unsigned char) (byte << (8-bit));
11403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (next->previous == (Image *) NULL)
11413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
11423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  status=SetImageProgress(next,SaveImageTag,y,next->rows);
11433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (status == MagickFalse)
11443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    break;
11453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
11463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
11473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
11483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
11493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 4:
11503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
1151bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            size_t
11523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              nibble,
11533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              byte;
11543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
11553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
11563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Convert PseudoClass image to a ICON monochrome image.
11573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
1158bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            for (y=0; y < (ssize_t) next->rows; y++)
11593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
11601e178e70fb3c956f9fc1e30c3ba863e882666465cristy              p=GetVirtualPixels(next,0,y,next->columns,1,exception);
11614c08aed51c5899665ade97263692328eea4af106cristy              if (p == (const Quantum *) NULL)
11623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
11633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              q=pixels+(next->rows-y-1)*bytes_per_line;
11643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              nibble=0;
11653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              byte=0;
1166bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < (ssize_t) next->columns; x++)
11673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
11683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                byte<<=4;
11694c08aed51c5899665ade97263692328eea4af106cristy                byte|=((size_t) GetPixelIndex(next,p) & 0x0f);
11703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                nibble++;
11713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (nibble == 2)
11723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
11733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    *q++=(unsigned char) byte;
11743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    nibble=0;
11753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    byte=0;
11763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  }
1177ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                p+=GetPixelChannels(image);
11784c08aed51c5899665ade97263692328eea4af106cristy              }
11793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (nibble != 0)
11803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                *q++=(unsigned char) (byte << 4);
11813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (next->previous == (Image *) NULL)
11823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
11833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  status=SetImageProgress(next,SaveImageTag,y,next->rows);
11843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (status == MagickFalse)
11853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    break;
11863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
11873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
11883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
11893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
11903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 8:
11913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
11923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
11933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Convert PseudoClass packet to ICON pixel.
11943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
1195bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            for (y=0; y < (ssize_t) next->rows; y++)
11963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
11971e178e70fb3c956f9fc1e30c3ba863e882666465cristy              p=GetVirtualPixels(next,0,y,next->columns,1,exception);
11984c08aed51c5899665ade97263692328eea4af106cristy              if (p == (const Quantum *) NULL)
11993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
12003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              q=pixels+(next->rows-y-1)*bytes_per_line;
1201bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < (ssize_t) next->columns; x++)
12024c08aed51c5899665ade97263692328eea4af106cristy              {
12034c08aed51c5899665ade97263692328eea4af106cristy                *q++=(unsigned char) GetPixelIndex(next,p);
1204ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                p+=GetPixelChannels(image);
12054c08aed51c5899665ade97263692328eea4af106cristy              }
12063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (next->previous == (Image *) NULL)
12073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
12083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  status=SetImageProgress(next,SaveImageTag,y,next->rows);
12093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (status == MagickFalse)
12103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    break;
12113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
12123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
12133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
12143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
12153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 24:
12163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 32:
12173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
12183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
12193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Convert DirectClass packet to ICON BGR888 or BGRA8888 pixel.
12203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
1221bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            for (y=0; y < (ssize_t) next->rows; y++)
12223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
12231e178e70fb3c956f9fc1e30c3ba863e882666465cristy              p=GetVirtualPixels(next,0,y,next->columns,1,exception);
12244c08aed51c5899665ade97263692328eea4af106cristy              if (p == (const Quantum *) NULL)
12253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
12263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              q=pixels+(next->rows-y-1)*bytes_per_line;
1227bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < (ssize_t) next->columns; x++)
12283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
12294c08aed51c5899665ade97263692328eea4af106cristy                *q++=ScaleQuantumToChar(GetPixelBlue(next,p));
12304c08aed51c5899665ade97263692328eea4af106cristy                *q++=ScaleQuantumToChar(GetPixelGreen(next,p));
12314c08aed51c5899665ade97263692328eea4af106cristy                *q++=ScaleQuantumToChar(GetPixelRed(next,p));
123217f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy                if (next->alpha_trait == UndefinedPixelTrait)
12333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  *q++=ScaleQuantumToChar(QuantumRange);
12343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                else
12354c08aed51c5899665ade97263692328eea4af106cristy                  *q++=ScaleQuantumToChar(GetPixelAlpha(next,p));
1236ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                p+=GetPixelChannels(next);
12373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
12383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (icon_info.bits_per_pixel == 24)
1239bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy                for (x=3L*(ssize_t) next->columns; x < (ssize_t) bytes_per_line; x++)
12403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  *q++=0x00;
12413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (next->previous == (Image *) NULL)
12423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
12433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  status=SetImageProgress(next,SaveImageTag,y,next->rows);
12443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (status == MagickFalse)
12453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    break;
12463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
12473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
12483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
12493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
12503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
12513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
12523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Write 40-byte version 3+ bitmap header.
12533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
12543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_file.directory[scene].width=(unsigned char) icon_info.width;
12553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_file.directory[scene].height=(unsigned char) icon_info.height;
12563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_file.directory[scene].colors=(unsigned char)
12573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          icon_info.number_colors;
12583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_file.directory[scene].reserved=0;
12593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_file.directory[scene].planes=icon_info.planes;
12603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_file.directory[scene].bits_per_pixel=icon_info.bits_per_pixel;
12613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_file.directory[scene].size=icon_info.size;
1262bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        icon_file.directory[scene].offset=(size_t) TellBlob(image);
126335ef824baa82511126ff0072ae30eee0da9c05a3cristy        (void) WriteBlobLSBLong(image,(unsigned int) 40);
126435ef824baa82511126ff0072ae30eee0da9c05a3cristy        (void) WriteBlobLSBLong(image,(unsigned int) icon_info.width);
126535ef824baa82511126ff0072ae30eee0da9c05a3cristy        (void) WriteBlobLSBLong(image,(unsigned int) icon_info.height*2);
12663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) WriteBlobLSBShort(image,icon_info.planes);
12673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) WriteBlobLSBShort(image,icon_info.bits_per_pixel);
126835ef824baa82511126ff0072ae30eee0da9c05a3cristy        (void) WriteBlobLSBLong(image,(unsigned int) icon_info.compression);
126935ef824baa82511126ff0072ae30eee0da9c05a3cristy        (void) WriteBlobLSBLong(image,(unsigned int) icon_info.image_size);
127035ef824baa82511126ff0072ae30eee0da9c05a3cristy        (void) WriteBlobLSBLong(image,(unsigned int) icon_info.x_pixels);
127135ef824baa82511126ff0072ae30eee0da9c05a3cristy        (void) WriteBlobLSBLong(image,(unsigned int) icon_info.y_pixels);
127235ef824baa82511126ff0072ae30eee0da9c05a3cristy        (void) WriteBlobLSBLong(image,(unsigned int) icon_info.number_colors);
127335ef824baa82511126ff0072ae30eee0da9c05a3cristy        (void) WriteBlobLSBLong(image,(unsigned int) icon_info.colors_important);
12743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (next->storage_class == PseudoClass)
12753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
12763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            unsigned char
12773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *icon_colormap;
12783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
12803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Dump colormap to file.
12813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
12823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            icon_colormap=(unsigned char *) AcquireQuantumMemory((size_t)
12833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (1UL << icon_info.bits_per_pixel),4UL*sizeof(*icon_colormap));
1284c1e5200dbc332719a205fc2cf6004fa90258cfcbdirk            if (icon_colormap == (unsigned char *) NULL)
1285c1e5200dbc332719a205fc2cf6004fa90258cfcbdirk              {
1286c1e5200dbc332719a205fc2cf6004fa90258cfcbdirk                images=DestroyImageList(images);
1287c1e5200dbc332719a205fc2cf6004fa90258cfcbdirk                ThrowWriterException(ResourceLimitError,
1288c1e5200dbc332719a205fc2cf6004fa90258cfcbdirk                  "MemoryAllocationFailed");
12899e137706f4a1f40d099c597992f43cd3fba033a7dirk              }
12903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q=icon_colormap;
1291bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            for (i=0; i < (ssize_t) next->colors; i++)
12923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
12933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *q++=ScaleQuantumToChar(next->colormap[i].blue);
12943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *q++=ScaleQuantumToChar(next->colormap[i].green);
12953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *q++=ScaleQuantumToChar(next->colormap[i].red);
12963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *q++=(unsigned char) 0x0;
12973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
1298bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            for ( ; i < (ssize_t) (1UL << icon_info.bits_per_pixel); i++)
12993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
13003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *q++=(unsigned char) 0x00;
13013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *q++=(unsigned char) 0x00;
13023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *q++=(unsigned char) 0x00;
13033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *q++=(unsigned char) 0x00;
13043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
13053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) WriteBlob(image,(size_t) (4UL*(1UL <<
13063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              icon_info.bits_per_pixel)),icon_colormap);
13073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            icon_colormap=(unsigned char *) RelinquishMagickMemory(
13083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              icon_colormap);
13093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
13103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) WriteBlob(image,(size_t) icon_info.image_size,pixels);
13113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixels=(unsigned char *) RelinquishMagickMemory(pixels);
13123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
13133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Write matte mask.
13143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
13153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        scanline_pad=(((next->columns+31) & ~31)-next->columns) >> 3;
1316bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        for (y=((ssize_t) next->rows - 1); y >= 0; y--)
13173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
13181e178e70fb3c956f9fc1e30c3ba863e882666465cristy          p=GetVirtualPixels(next,0,y,next->columns,1,exception);
13194c08aed51c5899665ade97263692328eea4af106cristy          if (p == (const Quantum *) NULL)
13203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
13213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          bit=0;
13223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          byte=0;
1323bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy          for (x=0; x < (ssize_t) next->columns; x++)
13243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
13253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            byte<<=1;
132617f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy            if ((next->alpha_trait != UndefinedPixelTrait) &&
13274c08aed51c5899665ade97263692328eea4af106cristy                (GetPixelAlpha(next,p) == (Quantum) TransparentAlpha))
13283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              byte|=0x01;
13293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            bit++;
13303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (bit == 8)
13313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
13323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) WriteBlobByte(image,(unsigned char) byte);
13333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                bit=0;
13343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                byte=0;
13353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
1336ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy            p+=GetPixelChannels(next);
13373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
13383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (bit != 0)
13393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) WriteBlobByte(image,(unsigned char) (byte << (8-bit)));
1340bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy          for (i=0; i < (ssize_t) scanline_pad; i++)
13413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) WriteBlobByte(image,(unsigned char) 0);
13423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
13433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
13443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (GetNextImageInList(next) == (Image *) NULL)
13453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
13463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status=SetImageProgress(next,SaveImagesTag,scene++,
13473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      GetImageListLength(next));
13483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (status == MagickFalse)
13493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
13505467fcf6dfee9d372efee47bb4eb1fb8f3e118b4cristy    next=SyncNextImageInList(next);
13513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  } while ((next != (Image *) NULL) && (image_info->adjoin != MagickFalse));
13523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  offset=SeekBlob(image,0,SEEK_SET);
1353da16f16767eb31921af855f17bda465fffc4e000cristy  (void) offset;
13543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobLSBShort(image,0);
13553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobLSBShort(image,1);
13563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobLSBShort(image,(unsigned short) (scene+1));
13573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  scene=0;
13589e137706f4a1f40d099c597992f43cd3fba033a7dirk  next=(images != (Image *) NULL) ? images : image;
13593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  do
13603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
13613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(image,icon_file.directory[scene].width);
13623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(image,icon_file.directory[scene].height);
13633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(image,icon_file.directory[scene].colors);
13643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(image,icon_file.directory[scene].reserved);
13653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobLSBShort(image,icon_file.directory[scene].planes);
13663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobLSBShort(image,icon_file.directory[scene].bits_per_pixel);
13670b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy    (void) WriteBlobLSBLong(image,(unsigned int)
13680b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy      icon_file.directory[scene].size);
13690b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy    (void) WriteBlobLSBLong(image,(unsigned int)
13700b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy      icon_file.directory[scene].offset);
13713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    scene++;
13723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    next=SyncNextImageInList(next);
13733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  } while ((next != (Image *) NULL) && (image_info->adjoin != MagickFalse));
13743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(image);
13759e137706f4a1f40d099c597992f43cd3fba033a7dirk  images=DestroyImageList(images);
13763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
13773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1378