pcd.c revision de984cdc3631106b1cbbb8d3972b76a0fc27e8e8
13ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
23ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
43ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
53ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
63ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                            PPPP    CCCC  DDDD                               %
73ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                            P   P  C      D   D                              %
83ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                            PPPP   C      D   D                              %
93ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                            P      C      D   D                              %
103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                            P       CCCC  DDDD                               %
113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                     Read/Write Photo CD Image Format                        %
143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                              Software Design                                %
16de984cdc3631106b1cbbb8d3972b76a0fc27e8e8cristy%                                   Cristy                                    %
173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                 July 1992                                   %
183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
20fe676ee3a9cf43404bdc9ba8b27f597b5e4e28f7cristy%  Copyright 1999-2014 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"
434c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/property.h"
444c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/blob.h"
454c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/blob-private.h"
464c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/cache.h"
474c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/client.h"
484c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/colorspace.h"
49510d06a3f7063e91993e13d546d5685048248074cristy#include "MagickCore/colorspace-private.h"
504c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/constitute.h"
514c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/decorate.h"
52c53413df5789700e14e1a67e6cc2716d1716a387cristy#include "MagickCore/distort.h"
534c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception.h"
544c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception-private.h"
554c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/gem.h"
564c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/geometry.h"
574c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image.h"
584c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image-private.h"
594c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/list.h"
604c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/magick.h"
614c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/memory_.h"
624c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/monitor.h"
634c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/monitor-private.h"
644c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/montage.h"
654c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/pixel-accessor.h"
664c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/resize.h"
674c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/quantum-private.h"
684c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/static.h"
694c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/string_.h"
704c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/module.h"
714c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/transform.h"
724c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/utility.h"
733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Forward declarations.
763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
773ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType
781e178e70fb3c956f9fc1e30c3ba863e882666465cristy  WritePCDImage(const ImageInfo *,Image *,ExceptionInfo *);
793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   D e c o d e I m a g e                                                     %
863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  DecodeImage recovers the Huffman encoded luminance and chrominance
923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  deltas.
933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the DecodeImage method is:
953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType DecodeImage(Image *image,unsigned char *luma,
973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        unsigned char *chroma1,unsigned char *chroma2)
983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
1003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image: the address of a structure of type Image.
1023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o luma: the address of a character buffer that contains the
1043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      luminance information.
1053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o chroma1: the address of a character buffer that contains the
1073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      chrominance information.
1083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o chroma2: the address of a character buffer that contains the
1103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      chrominance information.
1113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
1133ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType DecodeImage(Image *image,unsigned char *luma,
114018f07f7333b25743d0afff892450cebdb905c1acristy  unsigned char *chroma1,unsigned char *chroma2,ExceptionInfo *exception)
1153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
116c31f22eed93546cfdcc39b64cd2e7543e9f94e38cristy#define IsSync(sum)  ((sum & 0xffffff00UL) == 0xfffffe00UL)
1173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define PCDGetBits(n) \
1183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{  \
1193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  sum=(sum << n) & 0xffffffff; \
1203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  bits-=n; \
1213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  while (bits <= 24) \
1223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  { \
1233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (p >= (buffer+0x800)) \
1243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      { \
1253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        count=ReadBlob(image,0x800,buffer); \
1263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        p=buffer; \
1273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      } \
1283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sum|=((unsigned int) (*p) << (24-bits)); \
1293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    bits+=8; \
1303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    p++; \
1313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  } \
1323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  typedef struct PCDTable
1353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
1363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    unsigned int
1373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      length,
1383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      sequence;
1393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    MagickStatusType
1413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mask;
1423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    unsigned char
1443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      key;
1453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  } PCDTable;
1463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  PCDTable
1483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *pcd_table[3];
1493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
150bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
1513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
1523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    j;
1533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register PCDTable
1553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *r;
1563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register unsigned char
1583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p,
1593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
1603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  size_t
1623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    bits,
163aff6d807f839a998fff6e87198f2418868ab508ecristy    length,
1643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    plane,
1653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pcd_length[3],
1663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    row,
1673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sum;
1683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
169aff6d807f839a998fff6e87198f2418868ab508ecristy  ssize_t
170aff6d807f839a998fff6e87198f2418868ab508ecristy    count,
171aff6d807f839a998fff6e87198f2418868ab508ecristy    quantum;
172aff6d807f839a998fff6e87198f2418868ab508ecristy
173aff6d807f839a998fff6e87198f2418868ab508ecristy  unsigned char
174aff6d807f839a998fff6e87198f2418868ab508ecristy    *buffer;
175aff6d807f839a998fff6e87198f2418868ab508ecristy
1763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
1773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Initialize Huffman tables.
1783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
1793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (const Image *) NULL);
1803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image->signature == MagickSignature);
1813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
1823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(luma != (unsigned char *) NULL);
1843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(chroma1 != (unsigned char *) NULL);
1853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(chroma2 != (unsigned char *) NULL);
1863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  buffer=(unsigned char *) AcquireQuantumMemory(0x800,sizeof(*buffer));
1873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (buffer == (unsigned char *) NULL)
1883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->filename);
1903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  sum=0;
1913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  bits=32;
1923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  p=buffer+0x800;
1933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < (image->columns > 1536 ? 3 : 1); i++)
1943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
1953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PCDGetBits(8);
1963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    length=(sum & 0xff)+1;
1973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pcd_table[i]=(PCDTable *) AcquireQuantumMemory(length,
1983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      sizeof(*pcd_table[i]));
1993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (pcd_table[i] == (PCDTable *) NULL)
2003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
2013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->filename);
2043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
2053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    r=pcd_table[i];
206bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (j=0; j < (ssize_t) length; j++)
2073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
2083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      PCDGetBits(8);
2093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r->length=(unsigned int) (sum & 0xff)+1;
2103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (r->length > 16)
2113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
2123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          return(MagickFalse);
2143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
2153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      PCDGetBits(16);
2163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r->sequence=(unsigned int) (sum & 0xffff) << 16;
2173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      PCDGetBits(8);
2183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r->key=(unsigned char) (sum & 0xff);
2193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r->mask=(~((1U << (32-r->length))-1));
2203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r++;
2213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
222bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    pcd_length[i]=(size_t) length;
2233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
2243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
2253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Search for Sync byte.
2263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
2273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 1; i++)
2283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PCDGetBits(16);
2293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 1; i++)
2303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PCDGetBits(16);
2313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  while ((sum & 0x00fff000UL) != 0x00fff000UL)
2323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PCDGetBits(8);
233c31f22eed93546cfdcc39b64cd2e7543e9f94e38cristy  while (IsSync(sum) == 0)
2343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PCDGetBits(1);
2353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
2363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Recover the Huffman encoded luminance and chrominance deltas.
2373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
2383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  count=0;
2393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  length=0;
2403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  plane=0;
2413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  row=0;
2423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  q=luma;
2433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for ( ; ; )
2443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
245c31f22eed93546cfdcc39b64cd2e7543e9f94e38cristy    if (IsSync(sum) != 0)
2463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
2473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
2483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Determine plane and row number.
2493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
2503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        PCDGetBits(16);
2513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        row=((sum >> 9) & 0x1fff);
2523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (row == image->rows)
2533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
2543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        PCDGetBits(8);
2553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        plane=sum >> 30;
2563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        PCDGetBits(16);
2573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        switch (plane)
2583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
2593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 0:
2603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
2613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q=luma+row*image->columns;
2623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            count=(ssize_t) image->columns;
2633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
2643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
2653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 2:
2663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
2673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q=chroma1+(row >> 1)*image->columns;
2683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            count=(ssize_t) (image->columns >> 1);
2693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            plane--;
2703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
2713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
2723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 3:
2733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
2743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q=chroma2+(row >> 1)*image->columns;
2753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            count=(ssize_t) (image->columns >> 1);
2763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            plane--;
2773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
2783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
2793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          default:
2803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
2813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            ThrowBinaryException(CorruptImageError,"CorruptImage",
2823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              image->filename);
2833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
2843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
2853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        length=pcd_length[plane];
2863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
2873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
2883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
2893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Decode luminance or chrominance deltas.
2903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
2913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    r=pcd_table[plane];
292bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (i=0; ((i < (ssize_t) length) && ((sum & r->mask) != r->sequence)); i++)
2933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r++;
2945d41880f52dcb79d3681d0841cb8882ee614a8f0cristy    if ((row > image->rows) || (r == (PCDTable *) NULL))
2953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
296c82a27bb8e3138ff9bbf0f696663bdf3e704cedecristy        (void) ThrowMagickException(exception,GetMagickModule(),
2973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          CorruptImageWarning,"SkipToSyncByte","`%s'",image->filename);
2983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        while ((sum & 0x00fff000) != 0x00fff000)
2993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PCDGetBits(8);
300c31f22eed93546cfdcc39b64cd2e7543e9f94e38cristy        while (IsSync(sum) == 0)
3013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PCDGetBits(1);
3023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
3033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
3043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (r->key < 128)
305bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      quantum=(ssize_t) (*q)+r->key;
3063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
307bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      quantum=(ssize_t) (*q)+r->key-256;
3083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q=(unsigned char) ((quantum < 0) ? 0 : (quantum > 255) ? 255 : quantum);
3093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q++;
3103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PCDGetBits(r->length);
3113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count--;
3123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
3133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
3143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Relinquish resources.
3153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
3163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < (image->columns > 1536 ? 3 : 1); i++)
3173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pcd_table[i]=(PCDTable *) RelinquishMagickMemory(pcd_table[i]);
3183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  buffer=(unsigned char *) RelinquishMagickMemory(buffer);
3193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
3203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
3233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   I s P C D                                                                 %
3283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  IsPCD() returns MagickTrue if the image format type, identified by the
3343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  magick string, is PCD.
3353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the IsPCD method is:
3373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType IsPCD(const unsigned char *magick,const size_t length)
3393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
3413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o magick: compare image format pattern against these bytes.
3433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o length: Specifies the length of the magick string.
3453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
3473ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType IsPCD(const unsigned char *magick,const size_t length)
3483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
3493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (length < 2052)
3503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
3513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (LocaleNCompare((const char *) magick+2048,"PCD_",4) == 0)
3523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickTrue);
3533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickFalse);
3543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
3573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e a d P C D I m a g e                                                   %
3623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ReadPCDImage() reads a Photo CD image file and returns it.  It
3683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  allocates the memory necessary for the new Image structure and returns a
3693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  pointer to the new image.  Much of the PCD decoder was derived from
3703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  the program hpcdtoppm(1) by Hadmut Danisch.
3713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the ReadPCDImage method is:
3733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      image=ReadPCDImage(image_info)
3753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
3773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
3793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o exception: return any errors or warnings in this structure.
3813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
3833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3843ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic inline size_t MagickMin(const size_t x,const size_t y)
3853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
3863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (x < y)
3873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(x);
3883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(y);
3893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3913ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic Image *OverviewImage(const ImageInfo *image_info,Image *image,
3923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ExceptionInfo *exception)
3933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
3943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
3953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *montage_image;
3963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MontageInfo
3983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *montage_info;
3993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register Image
4013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
4023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
4043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Create the PCD Overview image.
4053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
4063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (p=image; p != (Image *) NULL; p=p->next)
4073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
4083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) DeleteImageProperty(p,"label");
409d15e65928aec551b7388c2863de3e3e628e2e0ddcristy    (void) SetImageProperty(p,"label",DefaultTileLabel,exception);
4103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
4113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  montage_info=CloneMontageInfo(image_info,(MontageInfo *) NULL);
4123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CopyMagickString(montage_info->filename,image_info->filename,
4133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    MaxTextExtent);
4143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  montage_image=MontageImageList(image_info,montage_info,image,exception);
4153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  montage_info=DestroyMontageInfo(montage_info);
4163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (montage_image == (Image *) NULL)
4173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
4183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image=DestroyImage(image);
4193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(montage_image);
4203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
4213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
422bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristystatic void Upsample(const size_t width,const size_t height,
423bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  const size_t scaled_width,unsigned char *pixels)
4243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
425bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
4263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x,
4273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    y;
4283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register unsigned char
4303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p,
4313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q,
4323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *r;
4333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
4353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Create a new image that is a integral size greater than an existing one.
4363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
4373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(pixels != (unsigned char *) NULL);
438bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) height; y++)
4393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
4403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    p=pixels+(height-1-y)*scaled_width+(width-1);
4413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q=pixels+((height-1-y) << 1)*scaled_width+((width-1) << 1);
4423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q=(*p);
4433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *(q+1)=(*(p));
444bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=1; x < (ssize_t) width; x++)
4453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
4463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      p--;
4473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q-=2;
4483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *q=(*p);
449aff6d807f839a998fff6e87198f2418868ab508ecristy      *(q+1)=(unsigned char) ((((size_t) *p)+((size_t) *(p+1))+1) >> 1);
4503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
4513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
452bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) (height-1); y++)
4533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
454bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    p=pixels+((size_t) y << 1)*scaled_width;
4553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q=p+scaled_width;
4563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    r=q+scaled_width;
457bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) (width-1); x++)
4583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
459bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      *q=(unsigned char) ((((size_t) *p)+((size_t) *r)+1) >> 1);
460bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      *(q+1)=(unsigned char) ((((size_t) *p)+((size_t) *(p+2))+
461bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        ((size_t) *r)+((size_t) *(r+2))+2) >> 2);
4623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q+=2;
4633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      p+=2;
4643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r+=2;
4653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
466aff6d807f839a998fff6e87198f2418868ab508ecristy    *q++=(unsigned char) ((((size_t) *p++)+((size_t) *r++)+1) >> 1);
467aff6d807f839a998fff6e87198f2418868ab508ecristy    *q++=(unsigned char) ((((size_t) *p++)+((size_t) *r++)+1) >> 1);
4683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
4693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  p=pixels+(2*height-2)*scaled_width;
4703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  q=pixels+(2*height-1)*scaled_width;
4713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CopyMagickMemory(q,p,(size_t) (2*width));
4723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
4733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4743ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic Image *ReadPCDImage(const ImageInfo *image_info,ExceptionInfo *exception)
4753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
4763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
4773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *image;
4783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
4803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
4813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickOffsetType
4833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    offset;
4843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickSizeType
4863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    number_pixels;
4873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
488bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
4893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
4903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    y;
4913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4924c08aed51c5899665ade97263692328eea4af106cristy  register Quantum
4933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
4943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register unsigned char
4963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *c1,
4973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *c2,
4983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *yy;
4993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
500aff6d807f839a998fff6e87198f2418868ab508ecristy  size_t
501aff6d807f839a998fff6e87198f2418868ab508ecristy    height,
502aff6d807f839a998fff6e87198f2418868ab508ecristy    number_images,
503aff6d807f839a998fff6e87198f2418868ab508ecristy    rotate,
504aff6d807f839a998fff6e87198f2418868ab508ecristy    scene,
505aff6d807f839a998fff6e87198f2418868ab508ecristy    width;
506aff6d807f839a998fff6e87198f2418868ab508ecristy
5073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ssize_t
508aff6d807f839a998fff6e87198f2418868ab508ecristy    count,
509aff6d807f839a998fff6e87198f2418868ab508ecristy    x;
5103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned char
5123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *chroma1,
5133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *chroma2,
5143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *header,
5153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *luma;
5163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned int
5183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    overview;
5193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
5213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open image file.
5223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
5233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
5243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info->signature == MagickSignature);
5253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->debug != MagickFalse)
5263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
5273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image_info->filename);
5283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception != (ExceptionInfo *) NULL);
5293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception->signature == MagickSignature);
5309950d57e1124b73f684fb5946e206994cefda628cristy  image=AcquireImage(image_info,exception);
5313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
5323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
5333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
5343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image=DestroyImageList(image);
5353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return((Image *) NULL);
5363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
5373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
5383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Determine if this a PCD file.
5393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
5403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  header=(unsigned char *) AcquireQuantumMemory(0x800,3UL*sizeof(*header));
5413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (header == (unsigned char *) NULL)
5423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
5433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  count=ReadBlob(image,3*0x800,header);
5443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  overview=LocaleNCompare((char *) header,"PCD_OPA",7) == 0;
5453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((count == 0) ||
546c31f22eed93546cfdcc39b64cd2e7543e9f94e38cristy      ((LocaleNCompare((char *) header+0x800,"PCD",3) != 0) && (overview ==0)))
5473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
5483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  rotate=header[0x0e02] & 0x03;
5493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  number_images=(header[10] << 8) | header[11];
5503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  header=(unsigned char *) RelinquishMagickMemory(header);
5513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
5523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Determine resolution by scene specification.
5533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
5543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((image->columns == 0) || (image->rows == 0))
5553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    scene=3;
5563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
5573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
5583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      width=192;
5593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      height=128;
5603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (scene=1; scene < 6; scene++)
5613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
5623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if ((width >= image->columns) && (height >= image->rows))
5633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
5643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        width<<=1;
5653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        height<<=1;
5663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
5673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
5683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->number_scenes != 0)
569bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    scene=(size_t) MagickMin(image_info->scene,6);
570c31f22eed93546cfdcc39b64cd2e7543e9f94e38cristy  if (overview != 0)
5713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    scene=1;
5723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
5733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Initialize image structure.
5743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
5753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  width=192;
5763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  height=128;
577bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (i=1; i < (ssize_t) MagickMin(scene,3); i++)
5783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
5793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    width<<=1;
5803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    height<<=1;
5813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
5823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->columns=width;
5833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->rows=height;
5843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->depth=8;
585bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for ( ; i < (ssize_t) scene; i++)
5863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
5873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image->columns<<=1;
5883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image->rows<<=1;
5893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
5903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
5915d41880f52dcb79d3681d0841cb8882ee614a8f0cristy    Allocate luma and chroma memory.
5923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
5933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  number_pixels=(MagickSizeType) image->columns*image->rows;
5943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (number_pixels != (size_t) number_pixels)
5953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
5963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chroma1=(unsigned char *) AcquireQuantumMemory(image->columns+1UL,image->rows*
597c31f22eed93546cfdcc39b64cd2e7543e9f94e38cristy    10*sizeof(*chroma1));
5983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chroma2=(unsigned char *) AcquireQuantumMemory(image->columns+1UL,image->rows*
599c31f22eed93546cfdcc39b64cd2e7543e9f94e38cristy    10*sizeof(*chroma2));
6003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  luma=(unsigned char *) AcquireQuantumMemory(image->columns+1UL,image->rows*
601c31f22eed93546cfdcc39b64cd2e7543e9f94e38cristy    10*sizeof(*luma));
6023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((chroma1 == (unsigned char *) NULL) ||
6033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (chroma2 == (unsigned char *) NULL) || (luma == (unsigned char *) NULL))
6043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
6053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
6063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Advance to image data.
6073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
6083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  offset=93;
609c31f22eed93546cfdcc39b64cd2e7543e9f94e38cristy  if (overview != 0)
6103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    offset=2;
6113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
6123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (scene == 2)
6133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      offset=20;
6143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
6153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (scene <= 1)
6163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset=1;
617bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (i=0; i < (ssize_t) (offset*0x800); i++)
6183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) ReadBlobByte(image);
619c31f22eed93546cfdcc39b64cd2e7543e9f94e38cristy  if (overview != 0)
6203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
6213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Image
6223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *overview_image;
6233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      MagickProgressMonitor
6253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        progress_monitor;
6263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
627bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      register ssize_t
6283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        j;
6293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
6313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Read thumbnails from overview image.
6323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
633bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      for (j=1; j <= (ssize_t) number_images; j++)
6343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
6353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        progress_monitor=SetImageProgressMonitor(image,
6363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (MagickProgressMonitor) NULL,image->client_data);
637b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy        (void) FormatLocaleString(image->filename,MaxTextExtent,
638f2faecf9facdbbb14fcba373365f9f691a9658e0cristy          "images/img%04ld.pcd",(long) j);
639b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy        (void) FormatLocaleString(image->magick_filename,MaxTextExtent,
640f2faecf9facdbbb14fcba373365f9f691a9658e0cristy          "images/img%04ld.pcd",(long) j);
641bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        image->scene=(size_t) j;
6423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->columns=width;
6433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->rows=height;
6443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->depth=8;
6453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        yy=luma;
6463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        c1=chroma1;
6473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        c2=chroma2;
648bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        for (y=0; y < (ssize_t) height; y+=2)
6493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
6503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          count=ReadBlob(image,width,yy);
6513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          yy+=image->columns;
6523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          count=ReadBlob(image,width,yy);
6533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          yy+=image->columns;
6543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          count=ReadBlob(image,width >> 1,c1);
6553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          c1+=image->columns;
6563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          count=ReadBlob(image,width >> 1,c2);
6573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          c2+=image->columns;
6583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
6593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Upsample(image->columns >> 1,image->rows >> 1,image->columns,chroma1);
6603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Upsample(image->columns >> 1,image->rows >> 1,image->columns,chroma2);
6613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
6623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Transfer luminance and chrominance channels.
6633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
6643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        yy=luma;
6653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        c1=chroma1;
6663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        c2=chroma2;
667bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        for (y=0; y < (ssize_t) image->rows; y++)
6683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
6693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
670acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy          if (q == (Quantum *) NULL)
6713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
672bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy          for (x=0; x < (ssize_t) image->columns; x++)
6733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
6744c08aed51c5899665ade97263692328eea4af106cristy            SetPixelRed(image,ScaleCharToQuantum(*yy++),q);
6754c08aed51c5899665ade97263692328eea4af106cristy            SetPixelGreen(image,ScaleCharToQuantum(*c1++),q);
6764c08aed51c5899665ade97263692328eea4af106cristy            SetPixelBlue(image,ScaleCharToQuantum(*c2++),q);
677ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy            q+=GetPixelChannels(image);
6783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
6793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (SyncAuthenticPixels(image,exception) == MagickFalse)
6803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
6813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
6823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->colorspace=YCCColorspace;
6833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (LocaleCompare(image_info->magick,"PCDS") == 0)
684e2c4f18a7274c0c5c6231a2f3d73741a87d583facristy          SetImageColorspace(image,sRGBColorspace,exception);
685bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        if (j < (ssize_t) number_images)
6863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
6873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
6883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Allocate next image structure.
6893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
6909950d57e1124b73f684fb5946e206994cefda628cristy            AcquireNextImage(image_info,image,exception);
6913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (GetNextImageInList(image) == (Image *) NULL)
6923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
6933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image=DestroyImageList(image);
6943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                return((Image *) NULL);
6953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
6963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image=SyncNextImageInList(image);
6973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
6983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) SetImageProgressMonitor(image,progress_monitor,
6993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->client_data);
7003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (image->previous == (Image *) NULL)
7013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
7023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            status=SetImageProgress(image,LoadImageTag,j-1,number_images);
7033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (status == MagickFalse)
7043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              break;
7053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
7063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
7073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      chroma2=(unsigned char *) RelinquishMagickMemory(chroma2);
7083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      chroma1=(unsigned char *) RelinquishMagickMemory(chroma1);
7093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      luma=(unsigned char *) RelinquishMagickMemory(luma);
7103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image=GetFirstImageInList(image);
7113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      overview_image=OverviewImage(image_info,image,exception);
7123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return(overview_image);
7133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
7153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Read interleaved image.
7163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
7173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  yy=luma;
7183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  c1=chroma1;
7193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  c2=chroma2;
720bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) height; y+=2)
7213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
7223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count=ReadBlob(image,width,yy);
7233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    yy+=image->columns;
7243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count=ReadBlob(image,width,yy);
7253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    yy+=image->columns;
7263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count=ReadBlob(image,width >> 1,c1);
7273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    c1+=image->columns;
7283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count=ReadBlob(image,width >> 1,c2);
7293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    c2+=image->columns;
7303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
7313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (scene >= 4)
7323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
7333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
7343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Recover luminance deltas for 1536x1024 image.
7353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
7363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Upsample(768,512,image->columns,luma);
7373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Upsample(384,256,image->columns,chroma1);
7383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Upsample(384,256,image->columns,chroma2);
7393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->rows=1024;
7403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (i=0; i < (4*0x800); i++)
7413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) ReadBlobByte(image);
742018f07f7333b25743d0afff892450cebdb905c1acristy      status=DecodeImage(image,luma,chroma1,chroma2,exception);
7433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((scene >= 5) && status)
7443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
7453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /*
7463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            Recover luminance deltas for 3072x2048 image.
7473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          */
7483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Upsample(1536,1024,image->columns,luma);
7493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Upsample(768,512,image->columns,chroma1);
7503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Upsample(768,512,image->columns,chroma2);
7513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->rows=2048;
7523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          offset=TellBlob(image)/0x800+12;
7533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          offset=SeekBlob(image,offset*0x800,SEEK_SET);
754018f07f7333b25743d0afff892450cebdb905c1acristy          status=DecodeImage(image,luma,chroma1,chroma2,exception);
7553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if ((scene >= 6) && (status != MagickFalse))
7563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
7573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              /*
7583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                Recover luminance deltas for 6144x4096 image (vaporware).
7593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              */
7603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Upsample(3072,2048,image->columns,luma);
7613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Upsample(1536,1024,image->columns,chroma1);
7623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Upsample(1536,1024,image->columns,chroma2);
7633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              image->rows=4096;
7643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
7653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
7663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Upsample(image->columns >> 1,image->rows >> 1,image->columns,chroma1);
7683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Upsample(image->columns >> 1,image->rows >> 1,image->columns,chroma2);
7693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
7703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Transfer luminance and chrominance channels.
7713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
7723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  yy=luma;
7733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  c1=chroma1;
7743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  c2=chroma2;
775bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) image->rows; y++)
7763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
7773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
778acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy    if (q == (Quantum *) NULL)
7793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
780bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) image->columns; x++)
7813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
7824c08aed51c5899665ade97263692328eea4af106cristy      SetPixelRed(image,ScaleCharToQuantum(*yy++),q);
7834c08aed51c5899665ade97263692328eea4af106cristy      SetPixelGreen(image,ScaleCharToQuantum(*c1++),q);
7844c08aed51c5899665ade97263692328eea4af106cristy      SetPixelBlue(image,ScaleCharToQuantum(*c2++),q);
785ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy      q+=GetPixelChannels(image);
7863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (SyncAuthenticPixels(image,exception) == MagickFalse)
7883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
7893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (image->previous == (Image *) NULL)
7903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
791cee9711bbc334b5677d5ec4ea1cc70340d35ee35cristy        status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
792cee9711bbc334b5677d5ec4ea1cc70340d35ee35cristy                image->rows);
7933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (status == MagickFalse)
7943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
7953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
7963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
7973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chroma2=(unsigned char *) RelinquishMagickMemory(chroma2);
7983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chroma1=(unsigned char *) RelinquishMagickMemory(chroma1);
7993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  luma=(unsigned char *) RelinquishMagickMemory(luma);
8003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (EOFBlob(image) != MagickFalse)
8013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
8023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->filename);
8033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(image);
8043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->ping == MagickFalse)
8053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if ((rotate == 1) || (rotate == 3))
8063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
8073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        double
8083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          degrees;
8093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Image
8113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          *rotate_image;
8123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
8143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Rotate image.
8153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
8163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        degrees=rotate == 1 ? -90.0 : 90.0;
8173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        rotate_image=RotateImage(image,degrees,exception);
8183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (rotate_image != (Image *) NULL)
8193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
8203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image=DestroyImage(image);
8213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image=rotate_image;
8223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
8233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
8243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
8253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Set CCIR 709 primaries with a D65 white point.
8263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
8273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.red_primary.x=0.6400f;
8283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.red_primary.y=0.3300f;
8293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.green_primary.x=0.3000f;
8303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.green_primary.y=0.6000f;
8313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.blue_primary.x=0.1500f;
8323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.blue_primary.y=0.0600f;
8333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.white_point.x=0.3127f;
8343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.white_point.y=0.3290f;
8353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->gamma=1.000f/2.200f;
8363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->colorspace=YCCColorspace;
8373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (LocaleCompare(image_info->magick,"PCDS") == 0)
838e2c4f18a7274c0c5c6231a2f3d73741a87d583facristy    SetImageColorspace(image,sRGBColorspace,exception);
8393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(GetFirstImageInList(image));
8403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
8413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
8433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e g i s t e r P C D I m a g e                                           %
8483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  RegisterPCDImage() adds attributes for the PCD image format to
8543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  the list of supported formats.  The attributes include the image format
8553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  tag, a method to read and/or write the format, whether the format
8563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  supports the saving of more than one frame to the same file or blob,
8573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  whether the format supports native in-memory I/O, and a brief
8583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  description of the format.
8593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the RegisterPCDImage method is:
8613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
862bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy%      size_t RegisterPCDImage(void)
8633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
865bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristyModuleExport size_t RegisterPCDImage(void)
8663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
8673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickInfo
8683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *entry;
8693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry=SetMagickInfo("PCD");
8713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadPCDImage;
8723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WritePCDImage;
8733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->magick=(IsImageFormatHandler *) IsPCD;
8743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->adjoin=MagickFalse;
875ffaf9781fa632998c711fd43f305a737df94b50ccristy  entry->seekable_stream=MagickTrue;
8763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->description=ConstantString("Photo CD");
8773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->module=ConstantString("PCD");
8783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
8793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry=SetMagickInfo("PCDS");
8803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadPCDImage;
8813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WritePCDImage;
8823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->adjoin=MagickFalse;
883ffaf9781fa632998c711fd43f305a737df94b50ccristy  entry->seekable_stream=MagickTrue;
8843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->description=ConstantString("Photo CD");
8853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->module=ConstantString("PCD");
8863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
8873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickImageCoderSignature);
8883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
8893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
8913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   U n r e g i s t e r P C D I m a g e                                       %
8963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  UnregisterPCDImage() removes format registrations made by the
9023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  PCD module from the list of supported formats.
9033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the UnregisterPCDImage method is:
9053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      UnregisterPCDImage(void)
9073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
9093ed852eea50f9d4cd633efb8c2b054b8e33c253cristyModuleExport void UnregisterPCDImage(void)
9103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
9113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("PCD");
9123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("PCDS");
9133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
9143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
9163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   W r i t e P C D I m a g e                                                 %
9213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  WritePCDImage() writes an image in the Photo CD encoded image format.
9273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the WritePCDImage method is:
9293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9301e178e70fb3c956f9fc1e30c3ba863e882666465cristy%      MagickBooleanType WritePCDImage(const ImageInfo *image_info,
9311e178e70fb3c956f9fc1e30c3ba863e882666465cristy%        Image *image,ExceptionInfo *exception)
9323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows.
9343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
9363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image:  The image.
9383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9391e178e70fb3c956f9fc1e30c3ba863e882666465cristy%    o exception: return any errors or warnings in this structure.
9401e178e70fb3c956f9fc1e30c3ba863e882666465cristy%
9413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
9423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9433ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType WritePCDTile(Image *image,const char *page_geometry,
944e941a75fe8bf344bc5c06a7f74bb5173c87db115cristy  const char *tile_geometry,ExceptionInfo *exception)
9453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
9463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  GeometryInfo
9473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry_info;
9483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
9503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *downsample_image,
9513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *tile_image;
9523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
9543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
9553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickStatusType
9573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    flags;
9583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  RectangleInfo
9603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry;
9613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9624c08aed51c5899665ade97263692328eea4af106cristy  register const Quantum
9633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p,
9643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
9653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
966bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
9673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
9683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x;
9693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
970aff6d807f839a998fff6e87198f2418868ab508ecristy  ssize_t
971aff6d807f839a998fff6e87198f2418868ab508ecristy    y;
972aff6d807f839a998fff6e87198f2418868ab508ecristy
9733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
9743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Scale image to tile size.
9753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
9763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  SetGeometry(image,&geometry);
9773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ParseMetaGeometry(page_geometry,&geometry.x,&geometry.y,
9783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    &geometry.width,&geometry.height);
9793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((geometry.width % 2) != 0)
9803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry.width--;
9813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((geometry.height % 2) != 0)
9823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry.height--;
9833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  tile_image=ResizeImage(image,geometry.width,geometry.height,TriangleFilter,
984aa2c16cb5e695053aa78e40f66bc36fbef4b1ed1cristy    exception);
9853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (tile_image == (Image *) NULL)
9863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
9873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  flags=ParseGeometry(page_geometry,&geometry_info);
988bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  geometry.width=(size_t) geometry_info.rho;
989bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  geometry.height=(size_t) geometry_info.sigma;
9903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((flags & SigmaValue) == 0)
9913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry.height=geometry.width;
9923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((tile_image->columns != geometry.width) ||
9933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (tile_image->rows != geometry.height))
9943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
9953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Image
9963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *bordered_image;
9973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      RectangleInfo
9993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        border_info;
10003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
10023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Put a border around the image.
10033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
10043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      border_info.width=(geometry.width-tile_image->columns+1) >> 1;
10053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      border_info.height=(geometry.height-tile_image->rows+1) >> 1;
1006633f0c61bb0414b644dccf4f335576a10bca0329cristy      bordered_image=BorderImage(tile_image,&border_info,image->compose,
1007c82a27bb8e3138ff9bbf0f696663bdf3e704cedecristy        exception);
10083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (bordered_image == (Image *) NULL)
10093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        return(MagickFalse);
10103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      tile_image=DestroyImage(tile_image);
10113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      tile_image=bordered_image;
10123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
1013e941a75fe8bf344bc5c06a7f74bb5173c87db115cristy  (void) TransformImage(&tile_image,(char *) NULL,tile_geometry,exception);
10143d9f5ba107b160e1819bb6baeeb3a9f521e9f450cristy  if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1015e941a75fe8bf344bc5c06a7f74bb5173c87db115cristy    (void) TransformImageColorspace(tile_image,YCCColorspace,exception);
10163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  downsample_image=ResizeImage(tile_image,tile_image->columns/2,
1017aa2c16cb5e695053aa78e40f66bc36fbef4b1ed1cristy    tile_image->rows/2,TriangleFilter,exception);
10183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (downsample_image == (Image *) NULL)
10193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
10203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
10213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Write tile to PCD file.
10223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
1023bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) tile_image->rows; y+=2)
10243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
1025c82a27bb8e3138ff9bbf0f696663bdf3e704cedecristy    p=GetVirtualPixels(tile_image,0,y,tile_image->columns,2,exception);
10264c08aed51c5899665ade97263692328eea4af106cristy    if (p == (const Quantum *) NULL)
10273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
1028bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) (tile_image->columns << 1); x++)
10293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
10304c08aed51c5899665ade97263692328eea4af106cristy      (void) WriteBlobByte(image,ScaleQuantumToChar(GetPixelRed(tile_image,p)));
1031ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy      p+=GetPixelChannels(tile_image);
10323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
1033c82a27bb8e3138ff9bbf0f696663bdf3e704cedecristy    q=GetVirtualPixels(downsample_image,0,y >> 1,downsample_image->columns,1,
1034c82a27bb8e3138ff9bbf0f696663bdf3e704cedecristy      exception);
1035acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy    if (q == (Quantum *) NULL)
10363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
1037bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) downsample_image->columns; x++)
10383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
10394c08aed51c5899665ade97263692328eea4af106cristy      (void) WriteBlobByte(image,ScaleQuantumToChar(
10404c08aed51c5899665ade97263692328eea4af106cristy        GetPixelGreen(tile_image,q)));
10413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q++;
10423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
1043c82a27bb8e3138ff9bbf0f696663bdf3e704cedecristy    q=GetVirtualPixels(downsample_image,0,y >> 1,downsample_image->columns,1,
1044c82a27bb8e3138ff9bbf0f696663bdf3e704cedecristy      exception);
1045acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy    if (q == (Quantum *) NULL)
10463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
1047bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) downsample_image->columns; x++)
10483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
10494c08aed51c5899665ade97263692328eea4af106cristy      (void) WriteBlobByte(image,ScaleQuantumToChar(
10504c08aed51c5899665ade97263692328eea4af106cristy        GetPixelBlue(tile_image,q)));
10513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q++;
10523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
10533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status=SetImageProgress(image,SaveImageTag,y,tile_image->rows);
10543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (status == MagickFalse)
10553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
10563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
10573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 0x800; i++)
10583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(image,'\0');
10593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  downsample_image=DestroyImage(downsample_image);
10603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  tile_image=DestroyImage(tile_image);
10613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
10623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
10633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10641e178e70fb3c956f9fc1e30c3ba863e882666465cristystatic MagickBooleanType WritePCDImage(const ImageInfo *image_info,Image *image,
10651e178e70fb3c956f9fc1e30c3ba863e882666465cristy  ExceptionInfo *exception)
10663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
10673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
10683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *pcd_image;
10693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
10713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
10723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1073bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
10743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i;
10753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
10773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info->signature == MagickSignature);
10783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
10793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image->signature == MagickSignature);
10803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
10813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
10823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  pcd_image=image;
10833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->columns < image->rows)
10843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
10853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Image
10863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *rotate_image;
10873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
10893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Rotate portrait to landscape.
10903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
10911e178e70fb3c956f9fc1e30c3ba863e882666465cristy      rotate_image=RotateImage(image,90.0,exception);
10923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (rotate_image == (Image *) NULL)
10933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        return(MagickFalse);
10943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      pcd_image=rotate_image;
10953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
10963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
10973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open output image file.
10983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
10991e178e70fb3c956f9fc1e30c3ba863e882666465cristy  status=OpenBlob(image_info,pcd_image,WriteBinaryBlobMode,exception);
11003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
11013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(status);
11023d9f5ba107b160e1819bb6baeeb3a9f521e9f450cristy  if (IssRGBCompatibleColorspace(pcd_image->colorspace) == MagickFalse)
1103c511e881bdb2adc9c87173f8c3a6a747a96dbabdcristy    (void) TransformImageColorspace(pcd_image,sRGBColorspace,exception);
11043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
11053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Write PCD image header.
11063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
11073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 32; i++)
11083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,0xff);
11093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 4; i++)
11103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,0x0e);
11113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 8; i++)
11123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\0');
11133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 4; i++)
11143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,0x01);
11153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 4; i++)
11163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,0x05);
11173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 8; i++)
11183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\0');
11193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 4; i++)
11203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,0x0A);
11213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 36; i++)
11223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\0');
11233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 4; i++)
11243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,0x01);
11253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 1944; i++)
11263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\0');
11273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlob(pcd_image,7,(const unsigned char *) "PCD_IPI");
11283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobByte(pcd_image,0x06);
11293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 1530; i++)
11303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\0');
11313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->columns < image->rows)
11323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\1');
11333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
11343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\0');
11353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < (3*0x800-1539); i++)
11363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\0');
11373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
11383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Write PCD tiles.
11393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
1140e941a75fe8bf344bc5c06a7f74bb5173c87db115cristy  status=WritePCDTile(pcd_image,"768x512>","192x128",exception);
1141e941a75fe8bf344bc5c06a7f74bb5173c87db115cristy  status=WritePCDTile(pcd_image,"768x512>","384x256",exception);
1142e941a75fe8bf344bc5c06a7f74bb5173c87db115cristy  status=WritePCDTile(pcd_image,"768x512>","768x512",exception);
11433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(pcd_image);
11443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (pcd_image != image)
11453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pcd_image=DestroyImage(pcd_image);
11463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(status);
11473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1148