icon.c revision 4b708b85d92f5ee5e5996b1b019b45136e45e33a
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                                %
163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                John Cristy                                  %
173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                 July 1992                                   %
183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
201454be7db7a897f42cd40e4165f945d77196a6f8cristy%  Copyright 1999-2012 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"
614c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/pixel-accessor.h"
624c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/quantize.h"
634c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/quantum-private.h"
644c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/static.h"
654c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/string_.h"
664c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/module.h"
673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Define declarations.
703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
710157aeadef2fce908277168097a160a8f15a6952cristy#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__MINGW32__)
723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define BI_RGB  0
733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define BI_RLE8  1
743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define BI_BITFIELDS  3
753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define MaxIcons  1024
773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Typedef declarations.
803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
813ed852eea50f9d4cd633efb8c2b054b8e33c253cristytypedef struct _IconEntry
823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned char
843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    width,
853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    height,
863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    colors,
873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    reserved;
883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned short int
903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    planes,
913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    bits_per_pixel;
923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
93bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  size_t
943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    size,
953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    offset;
963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} IconEntry;
973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
983ed852eea50f9d4cd633efb8c2b054b8e33c253cristytypedef struct _IconFile
993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
1003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  short
1013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    reserved,
1023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    resource_type,
1033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count;
1043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  IconEntry
1063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    directory[MaxIcons];
1073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} IconFile;
1083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1093ed852eea50f9d4cd633efb8c2b054b8e33c253cristytypedef struct _IconInfo
1103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
111bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  size_t
1123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    file_size,
1133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ba_offset,
1143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    offset_bits,
1153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    size;
1163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
117bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  ssize_t
1183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    width,
1193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    height;
1203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned short
1223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    planes,
1233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    bits_per_pixel;
1243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
125bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  size_t
1263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    compression,
1273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image_size,
1283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x_pixels,
1293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    y_pixels,
1303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    number_colors,
1313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    red_mask,
1323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    green_mask,
1333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    blue_mask,
1343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    alpha_mask,
1353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    colors_important;
1363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
137bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  ssize_t
1383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    colorspace;
1393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} IconInfo;
1403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
1423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Forward declaractions.
1433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
1443ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType
1451e178e70fb3c956f9fc1e30c3ba863e882666465cristy  WriteICONImage(const ImageInfo *,Image *,ExceptionInfo *);
1463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
1483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e a d I C O N I m a g e                                                 %
1533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ReadICONImage() reads a Microsoft icon image file and returns it.  It
1593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  allocates the memory necessary for the new Image structure and returns a
1603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  pointer to the new image.
1613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the ReadICONImage method is:
1633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      Image *ReadICONImage(const ImageInfo *image_info,
1653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        ExceptionInfo *exception)
1663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
1683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
1703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o exception: return any errors or warnings in this structure.
1723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
1743ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic Image *ReadICONImage(const ImageInfo *image_info,
1753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ExceptionInfo *exception)
1763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
1773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  IconFile
1783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    icon_file;
1793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  IconInfo
1813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    icon_info;
1823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
1843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *image;
1853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
1873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
1883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
189bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
1903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
1913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x;
1923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1934c08aed51c5899665ade97263692328eea4af106cristy  register Quantum
1943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
1953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register unsigned char
1973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
1983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
199bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  size_t
2003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    bit,
201eaedf06777741da32408da72c1e512975c600c48cristy    byte,
2023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    bytes_per_line,
203eaedf06777741da32408da72c1e512975c600c48cristy    one,
2043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    scanline_pad;
2053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
206ebc891a1d9621a19c509200d7bf3470ca18dde7fcristy  ssize_t
207ebc891a1d9621a19c509200d7bf3470ca18dde7fcristy    count,
208ebc891a1d9621a19c509200d7bf3470ca18dde7fcristy    offset,
209ebc891a1d9621a19c509200d7bf3470ca18dde7fcristy    y;
210ebc891a1d9621a19c509200d7bf3470ca18dde7fcristy
2113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
2123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open image file.
2133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
2143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
2153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info->signature == MagickSignature);
2163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) LogMagickEvent(CoderEvent,GetMagickModule(),"%s",image_info->filename);
2173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception != (ExceptionInfo *) NULL);
2183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception->signature == MagickSignature);
2191f1de1882cd91b3fffd8b701d70fbf0949c6cf50cristy  image=AcquireImage(image_info,exception);
2203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
2213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
2223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
2233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image=DestroyImageList(image);
2243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return((Image *) NULL);
2253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
2263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  icon_file.reserved=(short) ReadBlobLSBShort(image);
2273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  icon_file.resource_type=(short) ReadBlobLSBShort(image);
2283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  icon_file.count=(short) ReadBlobLSBShort(image);
2293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((icon_file.reserved != 0) ||
2303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ((icon_file.resource_type != 1) && (icon_file.resource_type != 2)) ||
2313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (icon_file.count > MaxIcons))
2323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
2333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < icon_file.count; i++)
2343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
2353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    icon_file.directory[i].width=(unsigned char) ReadBlobByte(image);
2363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    icon_file.directory[i].height=(unsigned char) ReadBlobByte(image);
2373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    icon_file.directory[i].colors=(unsigned char) ReadBlobByte(image);
2383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    icon_file.directory[i].reserved=(unsigned char) ReadBlobByte(image);
2393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    icon_file.directory[i].planes=(unsigned short) ReadBlobLSBShort(image);
2403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    icon_file.directory[i].bits_per_pixel=(unsigned short)
2413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ReadBlobLSBShort(image);
2423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    icon_file.directory[i].size=ReadBlobLSBLong(image);
2433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    icon_file.directory[i].offset=ReadBlobLSBLong(image);
2443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
245eaedf06777741da32408da72c1e512975c600c48cristy  one=1;
2463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < icon_file.count; i++)
2473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
2483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
2493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Verify Icon identifier.
2503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
2513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    offset=(ssize_t) SeekBlob(image,(MagickOffsetType)
2523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      icon_file.directory[i].offset,SEEK_SET);
2533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (offset < 0)
2543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
2553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    icon_info.size=ReadBlobLSBLong(image);
256d63c05090aab1e473b06640f5d0d5cf15a2e71adcristy    icon_info.width=(unsigned char) ((int) ReadBlobLSBLong(image));
257d63c05090aab1e473b06640f5d0d5cf15a2e71adcristy    icon_info.height=(unsigned char) ((int) ReadBlobLSBLong(image)/2);
2584e09e0312060a073162b0e5a796495e61fccada5cristy    icon_info.planes=ReadBlobLSBShort(image);
2594e09e0312060a073162b0e5a796495e61fccada5cristy    icon_info.bits_per_pixel=ReadBlobLSBShort(image);
2604e09e0312060a073162b0e5a796495e61fccada5cristy    if ((icon_info.planes == 18505) && (icon_info.bits_per_pixel == 21060))
2613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
2623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Image
2633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          *icon_image;
2643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ImageInfo
2663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          *read_info;
2673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
268f054ee74c237471da2f9be084079112f3c89669ccristy        size_t
269f054ee74c237471da2f9be084079112f3c89669ccristy          length;
270f054ee74c237471da2f9be084079112f3c89669ccristy
271f054ee74c237471da2f9be084079112f3c89669ccristy        unsigned char
272f054ee74c237471da2f9be084079112f3c89669ccristy          *png;
273f054ee74c237471da2f9be084079112f3c89669ccristy
2743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
2753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Icon image encoded as a compressed PNG image.
2763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
277f054ee74c237471da2f9be084079112f3c89669ccristy        length=icon_file.directory[i].size;
2784e09e0312060a073162b0e5a796495e61fccada5cristy        png=(unsigned char *) AcquireQuantumMemory(length+16,sizeof(*png));
279f054ee74c237471da2f9be084079112f3c89669ccristy        if (png == (unsigned char *) NULL)
280f054ee74c237471da2f9be084079112f3c89669ccristy          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
281f054ee74c237471da2f9be084079112f3c89669ccristy        (void) CopyMagickMemory(png,"\211PNG\r\n\032\n\000\000\000\015",12);
2824e09e0312060a073162b0e5a796495e61fccada5cristy        png[12]=(unsigned char) icon_info.planes;
2834e09e0312060a073162b0e5a796495e61fccada5cristy        png[13]=(unsigned char) (icon_info.planes >> 8);
2844e09e0312060a073162b0e5a796495e61fccada5cristy        png[14]=(unsigned char) icon_info.bits_per_pixel;
2854e09e0312060a073162b0e5a796495e61fccada5cristy        png[15]=(unsigned char) (icon_info.bits_per_pixel >> 8);
2864e09e0312060a073162b0e5a796495e61fccada5cristy        count=ReadBlob(image,length-16,png+16);
2874e09e0312060a073162b0e5a796495e61fccada5cristy        if (count != (ssize_t) (length-16))
288f054ee74c237471da2f9be084079112f3c89669ccristy          {
289f054ee74c237471da2f9be084079112f3c89669ccristy            png=(unsigned char *) RelinquishMagickMemory(png);
290f054ee74c237471da2f9be084079112f3c89669ccristy            ThrowReaderException(CorruptImageError,
291f054ee74c237471da2f9be084079112f3c89669ccristy              "InsufficientImageDataInFile");
292f054ee74c237471da2f9be084079112f3c89669ccristy          }
2933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        read_info=CloneImageInfo(image_info);
2943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) CopyMagickString(read_info->magick,"PNG",MaxTextExtent);
2954e09e0312060a073162b0e5a796495e61fccada5cristy        icon_image=BlobToImage(read_info,png,length+16,exception);
2963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        read_info=DestroyImageInfo(read_info);
297f054ee74c237471da2f9be084079112f3c89669ccristy        png=(unsigned char *) RelinquishMagickMemory(png);
29847de5a9da4464b279806af8f178ceb801bc3fc7acristy        if (icon_image == (Image *) NULL)
2993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
30047de5a9da4464b279806af8f178ceb801bc3fc7acristy            image=DestroyImageList(image);
30147de5a9da4464b279806af8f178ceb801bc3fc7acristy            return((Image *) NULL);
3023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
30347de5a9da4464b279806af8f178ceb801bc3fc7acristy        DestroyBlob(icon_image);
30447de5a9da4464b279806af8f178ceb801bc3fc7acristy        icon_image->blob=ReferenceBlob(image->blob);
30547de5a9da4464b279806af8f178ceb801bc3fc7acristy        ReplaceImageInList(&image,icon_image);
3063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
3073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
3083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
309f054ee74c237471da2f9be084079112f3c89669ccristy        if (icon_info.bits_per_pixel > 32)
310f054ee74c237471da2f9be084079112f3c89669ccristy          ThrowReaderException(CorruptImageError,"ImproperImageHeader");
311f054ee74c237471da2f9be084079112f3c89669ccristy        icon_info.compression=ReadBlobLSBLong(image);
312f054ee74c237471da2f9be084079112f3c89669ccristy        icon_info.image_size=ReadBlobLSBLong(image);
313f054ee74c237471da2f9be084079112f3c89669ccristy        icon_info.x_pixels=ReadBlobLSBLong(image);
314f054ee74c237471da2f9be084079112f3c89669ccristy        icon_info.y_pixels=ReadBlobLSBLong(image);
315f054ee74c237471da2f9be084079112f3c89669ccristy        icon_info.number_colors=ReadBlobLSBLong(image);
316f054ee74c237471da2f9be084079112f3c89669ccristy        icon_info.colors_important=ReadBlobLSBLong(image);
317f054ee74c237471da2f9be084079112f3c89669ccristy        image->matte=MagickTrue;
318f054ee74c237471da2f9be084079112f3c89669ccristy        image->columns=(size_t) icon_file.directory[i].width;
319f054ee74c237471da2f9be084079112f3c89669ccristy        if ((ssize_t) image->columns > icon_info.width)
320f054ee74c237471da2f9be084079112f3c89669ccristy          image->columns=(size_t) icon_info.width;
3214e09e0312060a073162b0e5a796495e61fccada5cristy        if (image->columns == 0)
3224e09e0312060a073162b0e5a796495e61fccada5cristy          image->columns=256;
323f054ee74c237471da2f9be084079112f3c89669ccristy        image->rows=(size_t) icon_file.directory[i].height;
324f054ee74c237471da2f9be084079112f3c89669ccristy        if ((ssize_t) image->rows > icon_info.height)
325f054ee74c237471da2f9be084079112f3c89669ccristy          image->rows=(size_t) icon_info.height;
3264e09e0312060a073162b0e5a796495e61fccada5cristy        if (image->rows == 0)
3274e09e0312060a073162b0e5a796495e61fccada5cristy          image->rows=256;
328f054ee74c237471da2f9be084079112f3c89669ccristy        image->depth=icon_info.bits_per_pixel;
329f054ee74c237471da2f9be084079112f3c89669ccristy        if (image->debug != MagickFalse)
330f054ee74c237471da2f9be084079112f3c89669ccristy          {
331f054ee74c237471da2f9be084079112f3c89669ccristy            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
332f054ee74c237471da2f9be084079112f3c89669ccristy              " scene    = %.20g",(double) i);
333f054ee74c237471da2f9be084079112f3c89669ccristy            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
334f054ee74c237471da2f9be084079112f3c89669ccristy              "   size   = %.20g",(double) icon_info.size);
335f054ee74c237471da2f9be084079112f3c89669ccristy            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
336f054ee74c237471da2f9be084079112f3c89669ccristy              "   width  = %.20g",(double) icon_file.directory[i].width);
337f054ee74c237471da2f9be084079112f3c89669ccristy            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
338f054ee74c237471da2f9be084079112f3c89669ccristy              "   height = %.20g",(double) icon_file.directory[i].height);
339f054ee74c237471da2f9be084079112f3c89669ccristy            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
340f054ee74c237471da2f9be084079112f3c89669ccristy              "   colors = %.20g",(double ) icon_info.number_colors);
341f054ee74c237471da2f9be084079112f3c89669ccristy            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
342f054ee74c237471da2f9be084079112f3c89669ccristy              "   planes = %.20g",(double) icon_info.planes);
343f054ee74c237471da2f9be084079112f3c89669ccristy            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
344f054ee74c237471da2f9be084079112f3c89669ccristy              "   bpp    = %.20g",(double) icon_info.bits_per_pixel);
345f054ee74c237471da2f9be084079112f3c89669ccristy          }
346f054ee74c237471da2f9be084079112f3c89669ccristy      if ((icon_info.number_colors != 0) || (icon_info.bits_per_pixel <= 16))
347f054ee74c237471da2f9be084079112f3c89669ccristy        {
348f054ee74c237471da2f9be084079112f3c89669ccristy          image->storage_class=PseudoClass;
349f054ee74c237471da2f9be084079112f3c89669ccristy          image->colors=icon_info.number_colors;
350f054ee74c237471da2f9be084079112f3c89669ccristy          if (image->colors == 0)
351f054ee74c237471da2f9be084079112f3c89669ccristy            image->colors=one << icon_info.bits_per_pixel;
352f054ee74c237471da2f9be084079112f3c89669ccristy        }
353f054ee74c237471da2f9be084079112f3c89669ccristy      if (image->storage_class == PseudoClass)
354f054ee74c237471da2f9be084079112f3c89669ccristy        {
355f054ee74c237471da2f9be084079112f3c89669ccristy          register ssize_t
356f054ee74c237471da2f9be084079112f3c89669ccristy            i;
357f054ee74c237471da2f9be084079112f3c89669ccristy
358f054ee74c237471da2f9be084079112f3c89669ccristy          size_t
359f054ee74c237471da2f9be084079112f3c89669ccristy            number_colors,
360f054ee74c237471da2f9be084079112f3c89669ccristy            one;
361f054ee74c237471da2f9be084079112f3c89669ccristy
362f054ee74c237471da2f9be084079112f3c89669ccristy          unsigned char
363f054ee74c237471da2f9be084079112f3c89669ccristy            *icon_colormap;
364ebc891a1d9621a19c509200d7bf3470ca18dde7fcristy
365f054ee74c237471da2f9be084079112f3c89669ccristy          /*
366f054ee74c237471da2f9be084079112f3c89669ccristy            Read Icon raster colormap.
367f054ee74c237471da2f9be084079112f3c89669ccristy          */
368f054ee74c237471da2f9be084079112f3c89669ccristy          one=1;
369f054ee74c237471da2f9be084079112f3c89669ccristy          number_colors=one << icon_info.bits_per_pixel;
370f054ee74c237471da2f9be084079112f3c89669ccristy          if (AcquireImageColormap(image,number_colors,exception) == MagickFalse)
371f054ee74c237471da2f9be084079112f3c89669ccristy            ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
372f054ee74c237471da2f9be084079112f3c89669ccristy          icon_colormap=(unsigned char *) AcquireQuantumMemory((size_t)
373f054ee74c237471da2f9be084079112f3c89669ccristy            image->colors,4UL*sizeof(*icon_colormap));
374f054ee74c237471da2f9be084079112f3c89669ccristy          if (icon_colormap == (unsigned char *) NULL)
375f054ee74c237471da2f9be084079112f3c89669ccristy            ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
376f054ee74c237471da2f9be084079112f3c89669ccristy          count=ReadBlob(image,(size_t) (4*image->colors),icon_colormap);
377f054ee74c237471da2f9be084079112f3c89669ccristy          if (count != (ssize_t) (4*image->colors))
378f054ee74c237471da2f9be084079112f3c89669ccristy            ThrowReaderException(CorruptImageError,
379f054ee74c237471da2f9be084079112f3c89669ccristy              "InsufficientImageDataInFile");
380f054ee74c237471da2f9be084079112f3c89669ccristy          p=icon_colormap;
381f054ee74c237471da2f9be084079112f3c89669ccristy          for (i=0; i < (ssize_t) image->colors; i++)
382f054ee74c237471da2f9be084079112f3c89669ccristy          {
383f054ee74c237471da2f9be084079112f3c89669ccristy            image->colormap[i].blue=(Quantum) ScaleCharToQuantum(*p++);
384f054ee74c237471da2f9be084079112f3c89669ccristy            image->colormap[i].green=(Quantum) ScaleCharToQuantum(*p++);
385f054ee74c237471da2f9be084079112f3c89669ccristy            image->colormap[i].red=(Quantum) ScaleCharToQuantum(*p++);
386f054ee74c237471da2f9be084079112f3c89669ccristy            p++;
387f054ee74c237471da2f9be084079112f3c89669ccristy          }
388f054ee74c237471da2f9be084079112f3c89669ccristy          icon_colormap=(unsigned char *) RelinquishMagickMemory(icon_colormap);
389f054ee74c237471da2f9be084079112f3c89669ccristy        }
3903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
3913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Convert Icon raster image to pixel packets.
3923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
393f054ee74c237471da2f9be084079112f3c89669ccristy        if ((image_info->ping != MagickFalse) &&
394f054ee74c237471da2f9be084079112f3c89669ccristy            (image_info->number_scenes != 0))
395f054ee74c237471da2f9be084079112f3c89669ccristy          if (image->scene >= (image_info->scene+image_info->number_scenes-1))
396f054ee74c237471da2f9be084079112f3c89669ccristy            break;
3973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        bytes_per_line=(((image->columns*icon_info.bits_per_pixel)+31) &
3983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ~31) >> 3;
399da16f16767eb31921af855f17bda465fffc4e000cristy        (void) bytes_per_line;
4003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        scanline_pad=((((image->columns*icon_info.bits_per_pixel)+31) & ~31)-
4013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (image->columns*icon_info.bits_per_pixel)) >> 3;
4023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        switch (icon_info.bits_per_pixel)
4033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
4043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 1:
4053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
4063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
4073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Convert bitmap scanline.
4083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
409bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            for (y=(ssize_t) image->rows-1; y >= 0; y--)
4103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
4113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
412acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy              if (q == (Quantum *) NULL)
4133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
414bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < (ssize_t) (image->columns-7); x+=8)
4153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
416f054ee74c237471da2f9be084079112f3c89669ccristy                byte=(size_t) ReadBlobByte(image);
4173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                for (bit=0; bit < 8; bit++)
4184c08aed51c5899665ade97263692328eea4af106cristy                {
4194c08aed51c5899665ade97263692328eea4af106cristy                  SetPixelIndex(image,((byte & (0x80 >> bit)) != 0 ? 0x01 :
4204c08aed51c5899665ade97263692328eea4af106cristy                    0x00),q);
421ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                  q+=GetPixelChannels(image);
4224c08aed51c5899665ade97263692328eea4af106cristy                }
4233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
4243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if ((image->columns % 8) != 0)
4253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
426f054ee74c237471da2f9be084079112f3c89669ccristy                  byte=(size_t) ReadBlobByte(image);
4273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  for (bit=0; bit < (image->columns % 8); bit++)
4284c08aed51c5899665ade97263692328eea4af106cristy                  {
4294c08aed51c5899665ade97263692328eea4af106cristy                    SetPixelIndex(image,((byte & (0x80 >> bit)) != 0 ? 0x01 :
4304c08aed51c5899665ade97263692328eea4af106cristy                      0x00),q);
431ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                    q+=GetPixelChannels(image);
4324c08aed51c5899665ade97263692328eea4af106cristy                  }
4333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
434bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < (ssize_t) scanline_pad; x++)
435f054ee74c237471da2f9be084079112f3c89669ccristy                (void) ReadBlobByte(image);
4363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (SyncAuthenticPixels(image,exception) == MagickFalse)
4373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
4383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (image->previous == (Image *) NULL)
4393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
4403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  status=SetImageProgress(image,LoadImageTag,image->rows-y-1,
4413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image->rows);
4423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (status == MagickFalse)
4433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    break;
4443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
4453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
4463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
4473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
4483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 4:
4493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
4503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
4513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Read 4-bit Icon scanline.
4523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
453bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            for (y=(ssize_t) image->rows-1; y >= 0; y--)
4543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
4553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
456acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy              if (q == (Quantum *) NULL)
4573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
458bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < ((ssize_t) image->columns-1); x+=2)
4593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
460f054ee74c237471da2f9be084079112f3c89669ccristy                byte=(size_t) ReadBlobByte(image);
4614c08aed51c5899665ade97263692328eea4af106cristy                SetPixelIndex(image,((byte >> 4) & 0xf),q);
462ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                q+=GetPixelChannels(image);
4634c08aed51c5899665ade97263692328eea4af106cristy                SetPixelIndex(image,((byte) & 0xf),q);
464ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                q+=GetPixelChannels(image);
4653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
4663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if ((image->columns % 2) != 0)
4673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
468f054ee74c237471da2f9be084079112f3c89669ccristy                  byte=(size_t) ReadBlobByte(image);
4694c08aed51c5899665ade97263692328eea4af106cristy                  SetPixelIndex(image,((byte >> 4) & 0xf),q);
470ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                  q+=GetPixelChannels(image);
4713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
472bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < (ssize_t) scanline_pad; x++)
473f054ee74c237471da2f9be084079112f3c89669ccristy                (void) ReadBlobByte(image);
4743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (SyncAuthenticPixels(image,exception) == MagickFalse)
4753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
4763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (image->previous == (Image *) NULL)
4773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
4783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  status=SetImageProgress(image,LoadImageTag,image->rows-y-1,
4793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image->rows);
4803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (status == MagickFalse)
4813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    break;
4823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
4833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
4843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
4853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
4863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 8:
4873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
4883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
4893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Convert PseudoColor scanline.
4903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
491bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            for (y=(ssize_t) image->rows-1; y >= 0; y--)
4923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
4933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
494acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy              if (q == (Quantum *) NULL)
4953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
496bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < (ssize_t) image->columns; x++)
4973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
498f054ee74c237471da2f9be084079112f3c89669ccristy                byte=(size_t) ReadBlobByte(image);
4994c08aed51c5899665ade97263692328eea4af106cristy                SetPixelIndex(image,byte,q);
500ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                q+=GetPixelChannels(image);
5013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
502bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < (ssize_t) scanline_pad; x++)
503f054ee74c237471da2f9be084079112f3c89669ccristy                (void) ReadBlobByte(image);
5043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (SyncAuthenticPixels(image,exception) == MagickFalse)
5053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
5063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (image->previous == (Image *) NULL)
5073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
5083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  status=SetImageProgress(image,LoadImageTag,image->rows-y-1,
5093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image->rows);
5103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (status == MagickFalse)
5113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    break;
5123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
5133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
5143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
5153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
5163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 16:
5173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
5183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
5193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Convert PseudoColor scanline.
5203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
521bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            for (y=(ssize_t) image->rows-1; y >= 0; y--)
5223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
5233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
524acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy              if (q == (Quantum *) NULL)
5253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
526bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < (ssize_t) image->columns; x++)
5273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
528f054ee74c237471da2f9be084079112f3c89669ccristy                byte=(size_t) ReadBlobByte(image);
529f054ee74c237471da2f9be084079112f3c89669ccristy                byte|=(size_t) (ReadBlobByte(image) << 8);
5304c08aed51c5899665ade97263692328eea4af106cristy                SetPixelIndex(image,byte,q);
531ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                q+=GetPixelChannels(image);
5323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
533bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < (ssize_t) scanline_pad; x++)
534f054ee74c237471da2f9be084079112f3c89669ccristy                (void) ReadBlobByte(image);
5353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (SyncAuthenticPixels(image,exception) == MagickFalse)
5363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
5373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (image->previous == (Image *) NULL)
5383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
5393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  status=SetImageProgress(image,LoadImageTag,image->rows-y-1,
5403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image->rows);
5413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (status == MagickFalse)
5423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    break;
5433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
5443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
5453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
5463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
5473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 24:
5483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 32:
5493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
5503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
5513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Convert DirectColor scanline.
5523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
553bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            for (y=(ssize_t) image->rows-1; y >= 0; y--)
5543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
5553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
556acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy              if (q == (Quantum *) NULL)
5573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
558bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < (ssize_t) image->columns; x++)
5593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
560f054ee74c237471da2f9be084079112f3c89669ccristy                SetPixelBlue(image,ScaleCharToQuantum((unsigned char)
561f054ee74c237471da2f9be084079112f3c89669ccristy                  ReadBlobByte(image)),q);
562f054ee74c237471da2f9be084079112f3c89669ccristy                SetPixelGreen(image,ScaleCharToQuantum((unsigned char)
563f054ee74c237471da2f9be084079112f3c89669ccristy                  ReadBlobByte(image)),q);
564f054ee74c237471da2f9be084079112f3c89669ccristy                SetPixelRed(image,ScaleCharToQuantum((unsigned char)
565f054ee74c237471da2f9be084079112f3c89669ccristy                  ReadBlobByte(image)),q);
5663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (icon_info.bits_per_pixel == 32)
567f054ee74c237471da2f9be084079112f3c89669ccristy                  SetPixelAlpha(image,ScaleCharToQuantum((unsigned char)
568f054ee74c237471da2f9be084079112f3c89669ccristy                    ReadBlobByte(image)),q);
569ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                q+=GetPixelChannels(image);
5703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
5713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (icon_info.bits_per_pixel == 24)
572bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy                for (x=0; x < (ssize_t) scanline_pad; x++)
573f054ee74c237471da2f9be084079112f3c89669ccristy                  (void) ReadBlobByte(image);
5743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (SyncAuthenticPixels(image,exception) == MagickFalse)
5753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
5763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (image->previous == (Image *) NULL)
5773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
5783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  status=SetImageProgress(image,LoadImageTag,image->rows-y-1,
5793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    image->rows);
5803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (status == MagickFalse)
5813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    break;
5823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
5833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
5843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
5853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
5863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          default:
5873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            ThrowReaderException(CorruptImageError,"ImproperImageHeader");
5883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
5895dd718802969a0ef5386a9f68ddaee5469fd9e87cristy        if (image_info->ping == MagickFalse)
590ea1a8aa04a9fe1500104284407c1cc06d20da699cristy          (void) SyncImage(image,exception);
5913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (icon_info.bits_per_pixel != 32)
5923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
5933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
5943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Read the ICON alpha mask.
5953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
5963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->storage_class=DirectClass;
597bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            for (y=(ssize_t) image->rows-1; y >= 0; y--)
5983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
5993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
600acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy              if (q == (Quantum *) NULL)
6013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
602bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < ((ssize_t) image->columns-7); x+=8)
6033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
604f054ee74c237471da2f9be084079112f3c89669ccristy                byte=(size_t) ReadBlobByte(image);
6053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                for (bit=0; bit < 8; bit++)
6064c08aed51c5899665ade97263692328eea4af106cristy                {
6074c08aed51c5899665ade97263692328eea4af106cristy                  SetPixelAlpha(image,(((byte & (0x80 >> bit)) != 0) ?
6084c08aed51c5899665ade97263692328eea4af106cristy                    TransparentAlpha : OpaqueAlpha),q);
609ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                  q+=GetPixelChannels(image);
6104c08aed51c5899665ade97263692328eea4af106cristy                }
6113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
6123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if ((image->columns % 8) != 0)
6133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
614f054ee74c237471da2f9be084079112f3c89669ccristy                  byte=(size_t) ReadBlobByte(image);
6153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  for (bit=0; bit < (image->columns % 8); bit++)
6164c08aed51c5899665ade97263692328eea4af106cristy                  {
6174c08aed51c5899665ade97263692328eea4af106cristy                    SetPixelAlpha(image,(((byte & (0x80 >> bit)) != 0) ?
6184c08aed51c5899665ade97263692328eea4af106cristy                      TransparentAlpha : OpaqueAlpha),q);
619ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                    q+=GetPixelChannels(image);
6204c08aed51c5899665ade97263692328eea4af106cristy                  }
6213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
6220e8200f78c4cb859725d32da48fcaf6f41f6ca02cristy              if ((image->columns % 32) != 0)
623bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy                for (x=0; x < (ssize_t) ((32-(image->columns % 32))/8); x++)
624f054ee74c237471da2f9be084079112f3c89669ccristy                  (void) ReadBlobByte(image);
6253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (SyncAuthenticPixels(image,exception) == MagickFalse)
6263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
6273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
6283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
6293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (EOFBlob(image) != MagickFalse)
6303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
6313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            ThrowFileException(exception,CorruptImageError,
6323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              "UnexpectedEndOfFile",image->filename);
6333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
6343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
6353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
6363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
6373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Proceed to next image.
6383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
6393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (image_info->number_scenes != 0)
6403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
6413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        break;
642bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    if (i < (ssize_t) (icon_file.count-1))
6433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
6443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
6453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Allocate next image structure.
6463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
6471f1de1882cd91b3fffd8b701d70fbf0949c6cf50cristy        AcquireNextImage(image_info,image,exception);
6483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (GetNextImageInList(image) == (Image *) NULL)
6493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
6503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image=DestroyImageList(image);
6513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            return((Image *) NULL);
6523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
6533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image=SyncNextImageInList(image);
6543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
6553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          GetBlobSize(image));
6563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (status == MagickFalse)
6573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
6583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
6593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
6603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(image);
6613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(GetFirstImageInList(image));
6623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
6633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
6653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
6673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
6683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
6693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e g i s t e r I C O N I m a g e                                         %
6703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
6713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
6723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
6733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  RegisterICONImage() adds attributes for the Icon image format to
6763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  the list of supported formats.  The attributes include the image format
6773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  tag, a method to read and/or write the format, whether the format
6783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  supports the saving of more than one frame to the same file or blob,
6793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  whether the format supports native in-memory I/O, and a brief
6803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  description of the format.
6813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the RegisterICONImage method is:
6833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
684bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy%      size_t RegisterICONImage(void)
6853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
687bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristyModuleExport size_t RegisterICONImage(void)
6883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
6893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickInfo
6903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *entry;
6913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry=SetMagickInfo("CUR");
6933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadICONImage;
6943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WriteICONImage;
6953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->adjoin=MagickFalse;
6963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->seekable_stream=MagickTrue;
6973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->description=ConstantString("Microsoft icon");
6983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->module=ConstantString("CUR");
6993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
7003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry=SetMagickInfo("ICO");
7013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadICONImage;
7023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WriteICONImage;
7033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->adjoin=MagickTrue;
7043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->seekable_stream=MagickTrue;
7053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->description=ConstantString("Microsoft icon");
7063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->module=ConstantString("ICON");
7073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
7083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry=SetMagickInfo("ICON");
7093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadICONImage;
7103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WriteICONImage;
7113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->adjoin=MagickFalse;
7123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->seekable_stream=MagickTrue;
7133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->description=ConstantString("Microsoft icon");
7143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->module=ConstantString("ICON");
7153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
7163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickImageCoderSignature);
7173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
7183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
7203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   U n r e g i s t e r I C O N I m a g e                                     %
7253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  UnregisterICONImage() removes format registrations made by the
7313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ICON module from the list of supported formats.
7323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the UnregisterICONImage method is:
7343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      UnregisterICONImage(void)
7363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
7383ed852eea50f9d4cd633efb8c2b054b8e33c253cristyModuleExport void UnregisterICONImage(void)
7393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
7403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("CUR");
7413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("ICO");
7423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("ICON");
7433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
7443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
7463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   W r i t e I C O N I m a g e                                               %
7513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  WriteICONImage() writes an image in Microsoft Windows bitmap encoded
7573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  image format, version 3 for Windows or (if the image has a matte channel)
7583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  version 4.
7593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7604b708b85d92f5ee5e5996b1b019b45136e45e33aglennrp%  It encodes any subimage as a compressed PNG image ("BI_PNG)",
7614b708b85d92f5ee5e5996b1b019b45136e45e33aglennrp%  only when its dimensions are 256x256 and image->compression is
7624b708b85d92f5ee5e5996b1b019b45136e45e33aglennrp%  undefined or is defined as ZipCompression.
7634b708b85d92f5ee5e5996b1b019b45136e45e33aglennrp%
7643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the WriteICONImage method is:
7653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType WriteICONImage(const ImageInfo *image_info,
7671e178e70fb3c956f9fc1e30c3ba863e882666465cristy%        Image *image,ExceptionInfo *exception)
7683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows.
7703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
7723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image:  The image.
7743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7751e178e70fb3c956f9fc1e30c3ba863e882666465cristy%    o exception: return any errors or warnings in this structure.
7761e178e70fb3c956f9fc1e30c3ba863e882666465cristy%
7773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
7783ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType WriteICONImage(const ImageInfo *image_info,
7791e178e70fb3c956f9fc1e30c3ba863e882666465cristy  Image *image,ExceptionInfo *exception)
7803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
7813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  IconFile
7823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    icon_file;
7833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  IconInfo
7853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    icon_info;
7863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
7883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *next;
7893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
7913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
7923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickOffsetType
7943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    offset,
7953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    scene;
7963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7974c08aed51c5899665ade97263692328eea4af106cristy  register const Quantum
7983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
7993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
800bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
8013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
8023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x;
8033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register unsigned char
8053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
8063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
807ebc891a1d9621a19c509200d7bf3470ca18dde7fcristy  size_t
808ebc891a1d9621a19c509200d7bf3470ca18dde7fcristy    bytes_per_line,
809ebc891a1d9621a19c509200d7bf3470ca18dde7fcristy    scanline_pad;
810ebc891a1d9621a19c509200d7bf3470ca18dde7fcristy
811ebc891a1d9621a19c509200d7bf3470ca18dde7fcristy  ssize_t
812ebc891a1d9621a19c509200d7bf3470ca18dde7fcristy    y;
813ebc891a1d9621a19c509200d7bf3470ca18dde7fcristy
8143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned char
8153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    bit,
8163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    byte,
8173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *pixels;
8183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
8203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open output image file.
8213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
8223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
8233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info->signature == MagickSignature);
8243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
8253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image->signature == MagickSignature);
8263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(CoderEvent,GetMagickModule(),"%s",image->filename);
8273a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  assert(exception != (ExceptionInfo *) NULL);
8283a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  assert(exception->signature == MagickSignature);
8291e178e70fb3c956f9fc1e30c3ba863e882666465cristy  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
8303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
8313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(status);
8323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  scene=0;
8333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  next=image;
8343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  do
8353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
8363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if ((image->columns > 256L) || (image->rows > 256L))
8373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
8383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    scene++;
8393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    next=SyncNextImageInList(next);
8403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  } while ((next != (Image *) NULL) && (image_info->adjoin != MagickFalse));
8413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
8423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Dump out a ICON header template to be properly initialized later.
8433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
8443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobLSBShort(image,0);
8453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobLSBShort(image,1);
8463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobLSBShort(image,(unsigned char) scene);
8473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ResetMagickMemory(&icon_file,0,sizeof(icon_file));
8483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ResetMagickMemory(&icon_info,0,sizeof(icon_info));
8493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  scene=0;
8503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  next=image;
8513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  do
8523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
8533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(image,icon_file.directory[scene].width);
8543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(image,icon_file.directory[scene].height);
8553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(image,icon_file.directory[scene].colors);
8563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(image,icon_file.directory[scene].reserved);
8573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobLSBShort(image,icon_file.directory[scene].planes);
8583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobLSBShort(image,icon_file.directory[scene].bits_per_pixel);
8590b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy    (void) WriteBlobLSBLong(image,(unsigned int)
8600b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy      icon_file.directory[scene].size);
8610b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy    (void) WriteBlobLSBLong(image,(unsigned int)
8620b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy      icon_file.directory[scene].offset);
8633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    scene++;
8643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    next=SyncNextImageInList(next);
8653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  } while ((next != (Image *) NULL) && (image_info->adjoin != MagickFalse));
8663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  scene=0;
8673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  next=image;
8683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  do
8693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
8704b708b85d92f5ee5e5996b1b019b45136e45e33aglennrp    if ((next->columns > 255L) && (next->rows > 255L) &&
8714b708b85d92f5ee5e5996b1b019b45136e45e33aglennrp        ((next->compression == UndefinedCompression) ||
8724b708b85d92f5ee5e5996b1b019b45136e45e33aglennrp        (next->compression == ZipCompression)))
8733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
8743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Image
8753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          *write_image;
8763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ImageInfo
8783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          *write_info;
8793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        size_t
8813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          length;
8823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        unsigned char
8843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          *png;
8853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8861e178e70fb3c956f9fc1e30c3ba863e882666465cristy        write_image=CloneImage(next,0,0,MagickTrue,exception);
8873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (write_image == (Image *) NULL)
8883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          return(MagickFalse);
8893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        write_info=CloneImageInfo(image_info);
8903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) CopyMagickString(write_info->filename,"PNG:",MaxTextExtent);
8914b708b85d92f5ee5e5996b1b019b45136e45e33aglennrp
8924b708b85d92f5ee5e5996b1b019b45136e45e33aglennrp        /* Don't write any ancillary chunks except for gAMA */
8934b708b85d92f5ee5e5996b1b019b45136e45e33aglennrp        (void) SetImageArtifact(write_image,"png:include-chunk","none,gama");
8944b708b85d92f5ee5e5996b1b019b45136e45e33aglennrp
8954b708b85d92f5ee5e5996b1b019b45136e45e33aglennrp        /* Only write PNG32 formatted PNG (32-bit RGBA), 8 bits per channel */
8964b708b85d92f5ee5e5996b1b019b45136e45e33aglennrp        (void) SetImageArtifact(write_image,"png:format","png32");
8974b708b85d92f5ee5e5996b1b019b45136e45e33aglennrp
8983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        png=(unsigned char *) ImageToBlob(write_info,write_image,&length,
8991e178e70fb3c956f9fc1e30c3ba863e882666465cristy          exception);
9003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        write_image=DestroyImage(write_image);
9013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        write_info=DestroyImageInfo(write_info);
9023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (png == (unsigned char *) NULL)
9033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          return(MagickFalse);
9043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_file.directory[scene].width=0;
9053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_file.directory[scene].height=0;
9063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_file.directory[scene].colors=0;
9073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_file.directory[scene].reserved=0;
9083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_file.directory[scene].planes=1;
9093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_file.directory[scene].bits_per_pixel=32;
910bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        icon_file.directory[scene].size=(size_t) length;
911bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        icon_file.directory[scene].offset=(size_t) TellBlob(image);
9123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) WriteBlob(image,(size_t) length,png);
9133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        png=(unsigned char *) RelinquishMagickMemory(png);
9143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
9153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
9163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
9173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
9183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Initialize ICON raster file header.
9193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
9203d9f5ba107b160e1819bb6baeeb3a9f521e9f450cristy        if (IssRGBCompatibleColorspace(next->colorspace) == MagickFalse)
921c511e881bdb2adc9c87173f8c3a6a747a96dbabdcristy          (void) TransformImageColorspace(next,sRGBColorspace,exception);
9223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.file_size=14+12+28;
9233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.offset_bits=icon_info.file_size;
9243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.compression=BI_RGB;
9253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if ((next->storage_class != DirectClass) && (next->colors > 256))
9261e178e70fb3c956f9fc1e30c3ba863e882666465cristy          (void) SetImageStorageClass(next,DirectClass,exception);
9273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (next->storage_class == DirectClass)
9283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
9293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
9303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Full color ICON raster.
9313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
9323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            icon_info.number_colors=0;
9333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            icon_info.bits_per_pixel=32;
934bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            icon_info.compression=(size_t) BI_RGB;
9353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
9363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        else
9373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
93835ef824baa82511126ff0072ae30eee0da9c05a3cristy            size_t
93935ef824baa82511126ff0072ae30eee0da9c05a3cristy              one;
94035ef824baa82511126ff0072ae30eee0da9c05a3cristy
9413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
9423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Colormapped ICON raster.
9433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
9443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            icon_info.bits_per_pixel=8;
9453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (next->colors <= 256)
9463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              icon_info.bits_per_pixel=8;
9473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (next->colors <= 16)
9483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              icon_info.bits_per_pixel=4;
9493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (next->colors <= 2)
9503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              icon_info.bits_per_pixel=1;
95135ef824baa82511126ff0072ae30eee0da9c05a3cristy            one=1;
95235ef824baa82511126ff0072ae30eee0da9c05a3cristy            icon_info.number_colors=one << icon_info.bits_per_pixel;
9533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (icon_info.number_colors < next->colors)
9543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
9551e178e70fb3c956f9fc1e30c3ba863e882666465cristy                (void) SetImageStorageClass(next,DirectClass,exception);
9563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                icon_info.number_colors=0;
9573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                icon_info.bits_per_pixel=(unsigned short) 24;
958bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy                icon_info.compression=(size_t) BI_RGB;
9593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
9603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
9613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
9620b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy                size_t
9630b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy                  one;
9640b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy
9650b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy                one=1;
9660b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy                icon_info.file_size+=3*(one << icon_info.bits_per_pixel);
9670b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy                icon_info.offset_bits+=3*(one << icon_info.bits_per_pixel);
9680b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy                icon_info.file_size+=(one << icon_info.bits_per_pixel);
9690b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy                icon_info.offset_bits+=(one << icon_info.bits_per_pixel);
9703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
9713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
9723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        bytes_per_line=(((next->columns*icon_info.bits_per_pixel)+31) &
9733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ~31) >> 3;
9743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.ba_offset=0;
975bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        icon_info.width=(ssize_t) next->columns;
976bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        icon_info.height=(ssize_t) next->rows;
9773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.planes=1;
9783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.image_size=bytes_per_line*next->rows;
9793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.size=40;
9803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.size+=(4*icon_info.number_colors);
9813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.size+=icon_info.image_size;
9823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.size+=(((icon_info.width+31) & ~31) >> 3)*icon_info.height;
9833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.file_size+=icon_info.image_size;
9843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.x_pixels=0;
9853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.y_pixels=0;
9863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        switch (next->units)
9873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
9883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case UndefinedResolution:
9893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case PixelsPerInchResolution:
9903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
9912a11befa48257796843468409d77bb8cfb129cdccristy            icon_info.x_pixels=(size_t) (100.0*next->resolution.x/2.54);
9922a11befa48257796843468409d77bb8cfb129cdccristy            icon_info.y_pixels=(size_t) (100.0*next->resolution.y/2.54);
9933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
9943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
9953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case PixelsPerCentimeterResolution:
9963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
9972a11befa48257796843468409d77bb8cfb129cdccristy            icon_info.x_pixels=(size_t) (100.0*next->resolution.x);
9982a11befa48257796843468409d77bb8cfb129cdccristy            icon_info.y_pixels=(size_t) (100.0*next->resolution.y);
9993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
10003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
10013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
10023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_info.colors_important=icon_info.number_colors;
10033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
10043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Convert MIFF to ICON raster pixels.
10053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
10063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixels=(unsigned char *) AcquireQuantumMemory((size_t)
10073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          icon_info.image_size,sizeof(*pixels));
10083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (pixels == (unsigned char *) NULL)
10093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
10103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) ResetMagickMemory(pixels,0,(size_t) icon_info.image_size);
10113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        switch (icon_info.bits_per_pixel)
10123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
10133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 1:
10143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
1015bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            size_t
10163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              bit,
10173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              byte;
10183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
10203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Convert PseudoClass image to a ICON monochrome image.
10213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
1022bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            for (y=0; y < (ssize_t) next->rows; y++)
10233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
10241e178e70fb3c956f9fc1e30c3ba863e882666465cristy              p=GetVirtualPixels(next,0,y,next->columns,1,exception);
10254c08aed51c5899665ade97263692328eea4af106cristy              if (p == (const Quantum *) NULL)
10263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
10273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              q=pixels+(next->rows-y-1)*bytes_per_line;
10283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              bit=0;
10293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              byte=0;
1030bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < (ssize_t) next->columns; x++)
10313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
10323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                byte<<=1;
10334c08aed51c5899665ade97263692328eea4af106cristy                byte|=GetPixelIndex(next,p) != 0 ? 0x01 : 0x00;
10343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                bit++;
10353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (bit == 8)
10363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
10373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    *q++=(unsigned char) byte;
10383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    bit=0;
10393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    byte=0;
10403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  }
1041ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                p+=GetPixelChannels(image);
10424c08aed51c5899665ade97263692328eea4af106cristy              }
10433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (bit != 0)
10443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                *q++=(unsigned char) (byte << (8-bit));
10453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (next->previous == (Image *) NULL)
10463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
10473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  status=SetImageProgress(next,SaveImageTag,y,next->rows);
10483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (status == MagickFalse)
10493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    break;
10503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
10513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
10523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
10533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
10543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 4:
10553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
1056bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            size_t
10573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              nibble,
10583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              byte;
10593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
10613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Convert PseudoClass image to a ICON monochrome image.
10623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
1063bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            for (y=0; y < (ssize_t) next->rows; y++)
10643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
10651e178e70fb3c956f9fc1e30c3ba863e882666465cristy              p=GetVirtualPixels(next,0,y,next->columns,1,exception);
10664c08aed51c5899665ade97263692328eea4af106cristy              if (p == (const Quantum *) NULL)
10673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
10683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              q=pixels+(next->rows-y-1)*bytes_per_line;
10693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              nibble=0;
10703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              byte=0;
1071bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < (ssize_t) next->columns; x++)
10723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
10733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                byte<<=4;
10744c08aed51c5899665ade97263692328eea4af106cristy                byte|=((size_t) GetPixelIndex(next,p) & 0x0f);
10753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                nibble++;
10763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (nibble == 2)
10773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
10783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    *q++=(unsigned char) byte;
10793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    nibble=0;
10803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    byte=0;
10813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  }
1082ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                p+=GetPixelChannels(image);
10834c08aed51c5899665ade97263692328eea4af106cristy              }
10843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (nibble != 0)
10853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                *q++=(unsigned char) (byte << 4);
10863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (next->previous == (Image *) NULL)
10873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
10883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  status=SetImageProgress(next,SaveImageTag,y,next->rows);
10893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (status == MagickFalse)
10903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    break;
10913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
10923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
10933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
10943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
10953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 8:
10963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
10973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
10983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Convert PseudoClass packet to ICON pixel.
10993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
1100bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            for (y=0; y < (ssize_t) next->rows; y++)
11013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
11021e178e70fb3c956f9fc1e30c3ba863e882666465cristy              p=GetVirtualPixels(next,0,y,next->columns,1,exception);
11034c08aed51c5899665ade97263692328eea4af106cristy              if (p == (const Quantum *) NULL)
11043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
11053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              q=pixels+(next->rows-y-1)*bytes_per_line;
1106bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < (ssize_t) next->columns; x++)
11074c08aed51c5899665ade97263692328eea4af106cristy              {
11084c08aed51c5899665ade97263692328eea4af106cristy                *q++=(unsigned char) GetPixelIndex(next,p);
1109ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                p+=GetPixelChannels(image);
11104c08aed51c5899665ade97263692328eea4af106cristy              }
11113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (next->previous == (Image *) NULL)
11123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
11133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  status=SetImageProgress(next,SaveImageTag,y,next->rows);
11143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (status == MagickFalse)
11153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    break;
11163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
11173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
11183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
11193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
11203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 24:
11213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 32:
11223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
11233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
11243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Convert DirectClass packet to ICON BGR888 or BGRA8888 pixel.
11253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
1126bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            for (y=0; y < (ssize_t) next->rows; y++)
11273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
11281e178e70fb3c956f9fc1e30c3ba863e882666465cristy              p=GetVirtualPixels(next,0,y,next->columns,1,exception);
11294c08aed51c5899665ade97263692328eea4af106cristy              if (p == (const Quantum *) NULL)
11303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                break;
11313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              q=pixels+(next->rows-y-1)*bytes_per_line;
1132bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy              for (x=0; x < (ssize_t) next->columns; x++)
11333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
11344c08aed51c5899665ade97263692328eea4af106cristy                *q++=ScaleQuantumToChar(GetPixelBlue(next,p));
11354c08aed51c5899665ade97263692328eea4af106cristy                *q++=ScaleQuantumToChar(GetPixelGreen(next,p));
11364c08aed51c5899665ade97263692328eea4af106cristy                *q++=ScaleQuantumToChar(GetPixelRed(next,p));
11373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (next->matte == MagickFalse)
11383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  *q++=ScaleQuantumToChar(QuantumRange);
11393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                else
11404c08aed51c5899665ade97263692328eea4af106cristy                  *q++=ScaleQuantumToChar(GetPixelAlpha(next,p));
1141ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                p+=GetPixelChannels(next);
11423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
11433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (icon_info.bits_per_pixel == 24)
1144bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy                for (x=3L*(ssize_t) next->columns; x < (ssize_t) bytes_per_line; x++)
11453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  *q++=0x00;
11463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (next->previous == (Image *) NULL)
11473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
11483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  status=SetImageProgress(next,SaveImageTag,y,next->rows);
11493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  if (status == MagickFalse)
11503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    break;
11513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
11523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
11533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
11543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
11553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
11563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
11573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Write 40-byte version 3+ bitmap header.
11583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
11593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_file.directory[scene].width=(unsigned char) icon_info.width;
11603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_file.directory[scene].height=(unsigned char) icon_info.height;
11613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_file.directory[scene].colors=(unsigned char)
11623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          icon_info.number_colors;
11633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_file.directory[scene].reserved=0;
11643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_file.directory[scene].planes=icon_info.planes;
11653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_file.directory[scene].bits_per_pixel=icon_info.bits_per_pixel;
11663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        icon_file.directory[scene].size=icon_info.size;
1167bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        icon_file.directory[scene].offset=(size_t) TellBlob(image);
116835ef824baa82511126ff0072ae30eee0da9c05a3cristy        (void) WriteBlobLSBLong(image,(unsigned int) 40);
116935ef824baa82511126ff0072ae30eee0da9c05a3cristy        (void) WriteBlobLSBLong(image,(unsigned int) icon_info.width);
117035ef824baa82511126ff0072ae30eee0da9c05a3cristy        (void) WriteBlobLSBLong(image,(unsigned int) icon_info.height*2);
11713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) WriteBlobLSBShort(image,icon_info.planes);
11723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) WriteBlobLSBShort(image,icon_info.bits_per_pixel);
117335ef824baa82511126ff0072ae30eee0da9c05a3cristy        (void) WriteBlobLSBLong(image,(unsigned int) icon_info.compression);
117435ef824baa82511126ff0072ae30eee0da9c05a3cristy        (void) WriteBlobLSBLong(image,(unsigned int) icon_info.image_size);
117535ef824baa82511126ff0072ae30eee0da9c05a3cristy        (void) WriteBlobLSBLong(image,(unsigned int) icon_info.x_pixels);
117635ef824baa82511126ff0072ae30eee0da9c05a3cristy        (void) WriteBlobLSBLong(image,(unsigned int) icon_info.y_pixels);
117735ef824baa82511126ff0072ae30eee0da9c05a3cristy        (void) WriteBlobLSBLong(image,(unsigned int) icon_info.number_colors);
117835ef824baa82511126ff0072ae30eee0da9c05a3cristy        (void) WriteBlobLSBLong(image,(unsigned int) icon_info.colors_important);
11793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (next->storage_class == PseudoClass)
11803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
11813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            unsigned char
11823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *icon_colormap;
11833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
11843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
11853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Dump colormap to file.
11863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
11873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            icon_colormap=(unsigned char *) AcquireQuantumMemory((size_t)
11883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (1UL << icon_info.bits_per_pixel),4UL*sizeof(*icon_colormap));
11893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (icon_colormap == (unsigned char *) NULL)
11903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
11913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q=icon_colormap;
1192bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            for (i=0; i < (ssize_t) next->colors; i++)
11933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
11943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *q++=ScaleQuantumToChar(next->colormap[i].blue);
11953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *q++=ScaleQuantumToChar(next->colormap[i].green);
11963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *q++=ScaleQuantumToChar(next->colormap[i].red);
11973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *q++=(unsigned char) 0x0;
11983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
1199bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            for ( ; i < (ssize_t) (1UL << icon_info.bits_per_pixel); i++)
12003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
12013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *q++=(unsigned char) 0x00;
12023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *q++=(unsigned char) 0x00;
12033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *q++=(unsigned char) 0x00;
12043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *q++=(unsigned char) 0x00;
12053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
12063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) WriteBlob(image,(size_t) (4UL*(1UL <<
12073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              icon_info.bits_per_pixel)),icon_colormap);
12083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            icon_colormap=(unsigned char *) RelinquishMagickMemory(
12093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              icon_colormap);
12103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
12113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) WriteBlob(image,(size_t) icon_info.image_size,pixels);
12123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixels=(unsigned char *) RelinquishMagickMemory(pixels);
12133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
12143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Write matte mask.
12153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
12163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        scanline_pad=(((next->columns+31) & ~31)-next->columns) >> 3;
1217bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        for (y=((ssize_t) next->rows - 1); y >= 0; y--)
12183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
12191e178e70fb3c956f9fc1e30c3ba863e882666465cristy          p=GetVirtualPixels(next,0,y,next->columns,1,exception);
12204c08aed51c5899665ade97263692328eea4af106cristy          if (p == (const Quantum *) NULL)
12213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
12223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          bit=0;
12233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          byte=0;
1224bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy          for (x=0; x < (ssize_t) next->columns; x++)
12253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
12263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            byte<<=1;
12273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if ((next->matte == MagickTrue) &&
12284c08aed51c5899665ade97263692328eea4af106cristy                (GetPixelAlpha(next,p) == (Quantum) TransparentAlpha))
12293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              byte|=0x01;
12303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            bit++;
12313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (bit == 8)
12323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
12333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (void) WriteBlobByte(image,(unsigned char) byte);
12343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                bit=0;
12353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                byte=0;
12363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
1237ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy            p+=GetPixelChannels(next);
12383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
12393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (bit != 0)
12403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) WriteBlobByte(image,(unsigned char) (byte << (8-bit)));
1241bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy          for (i=0; i < (ssize_t) scanline_pad; i++)
12423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            (void) WriteBlobByte(image,(unsigned char) 0);
12433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
12443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
12453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (GetNextImageInList(next) == (Image *) NULL)
12463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
12473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    next=SyncNextImageInList(next);
12483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status=SetImageProgress(next,SaveImagesTag,scene++,
12493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      GetImageListLength(next));
12503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (status == MagickFalse)
12513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
12523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  } while ((next != (Image *) NULL) && (image_info->adjoin != MagickFalse));
12533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  offset=SeekBlob(image,0,SEEK_SET);
1254da16f16767eb31921af855f17bda465fffc4e000cristy  (void) offset;
12553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobLSBShort(image,0);
12563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobLSBShort(image,1);
12573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobLSBShort(image,(unsigned short) (scene+1));
12583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  scene=0;
12593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  next=image;
12603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  do
12613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
12623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(image,icon_file.directory[scene].width);
12633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(image,icon_file.directory[scene].height);
12643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(image,icon_file.directory[scene].colors);
12653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(image,icon_file.directory[scene].reserved);
12663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobLSBShort(image,icon_file.directory[scene].planes);
12673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobLSBShort(image,icon_file.directory[scene].bits_per_pixel);
12680b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy    (void) WriteBlobLSBLong(image,(unsigned int)
12690b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy      icon_file.directory[scene].size);
12700b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy    (void) WriteBlobLSBLong(image,(unsigned int)
12710b29b25525c4612c77b1b3c8abcc40685d0aa33fcristy      icon_file.directory[scene].offset);
12723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    scene++;
12733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    next=SyncNextImageInList(next);
12743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  } while ((next != (Image *) NULL) && (image_info->adjoin != MagickFalse));
12753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(image);
12763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
12773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1278