pcd.c revision bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6
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                                %
163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                John Cristy                                  %
173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                 July 1992                                   %
183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2016af1cbdffcc02e7239d432e5fb51734fcf9f9ffcristy%  Copyright 1999-2010 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*/
423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/studio.h"
433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/property.h"
443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/blob.h"
453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/blob-private.h"
463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/cache.h"
473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/client.h"
483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/colorspace.h"
493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/constitute.h"
503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/decorate.h"
513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/exception.h"
523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/exception-private.h"
533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/gem.h"
543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/geometry.h"
553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/image.h"
563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/image-private.h"
573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/list.h"
583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/magick.h"
593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/memory_.h"
603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/monitor.h"
613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/monitor-private.h"
623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/montage.h"
633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/resize.h"
643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/shear.h"
653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/quantum-private.h"
663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/static.h"
673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/string_.h"
683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/module.h"
693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/transform.h"
703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/utility.h"
713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Forward declarations.
743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
753ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType
763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  WritePCDImage(const ImageInfo *,Image *);
773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   D e c o d e I m a g e                                                     %
843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  DecodeImage recovers the Huffman encoded luminance and chrominance
903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  deltas.
913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the DecodeImage method is:
933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType DecodeImage(Image *image,unsigned char *luma,
953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        unsigned char *chroma1,unsigned char *chroma2)
963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image: the address of a structure of type Image.
1003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o luma: the address of a character buffer that contains the
1023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      luminance information.
1033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o chroma1: the address of a character buffer that contains the
1053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      chrominance information.
1063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o chroma2: the address of a character buffer that contains the
1083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      chrominance information.
1093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
1113ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType DecodeImage(Image *image,unsigned char *luma,
1123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned char *chroma1,unsigned char *chroma2)
1133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
1143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define IsSync  ((sum & 0xffffff00UL) == 0xfffffe00UL)
1153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define PCDGetBits(n) \
1163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{  \
1173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  sum=(sum << n) & 0xffffffff; \
1183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  bits-=n; \
1193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  while (bits <= 24) \
1203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  { \
1213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (p >= (buffer+0x800)) \
1223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      { \
1233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        count=ReadBlob(image,0x800,buffer); \
1243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        p=buffer; \
1253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      } \
1263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sum|=((unsigned int) (*p) << (24-bits)); \
1273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    bits+=8; \
1283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    p++; \
1293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  } \
1303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (EOFBlob(image) != MagickFalse) \
1313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    break; \
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
147bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  ssize_t
1483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    quantum;
1493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  PCDTable
1513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *pcd_table[3];
1523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
153bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
1543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
1553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    j;
1563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register PCDTable
1583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *r;
1593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register unsigned char
1613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p,
1623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
1633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  size_t
1653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    length;
1663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ssize_t
1683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count;
1693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned char
1713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *buffer;
1723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
173bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  size_t
1743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    bits,
1753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    plane,
1763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pcd_length[3],
1773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    row,
1783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sum;
1793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
1813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Initialize Huffman tables.
1823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
1833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (const Image *) NULL);
1843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image->signature == MagickSignature);
1853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
1863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(luma != (unsigned char *) NULL);
1883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(chroma1 != (unsigned char *) NULL);
1893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(chroma2 != (unsigned char *) NULL);
1903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  buffer=(unsigned char *) AcquireQuantumMemory(0x800,sizeof(*buffer));
1913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (buffer == (unsigned char *) NULL)
1923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->filename);
1943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  sum=0;
1953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  bits=32;
1963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  p=buffer+0x800;
1973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < (image->columns > 1536 ? 3 : 1); i++)
1983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
1993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PCDGetBits(8);
2003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    length=(sum & 0xff)+1;
2013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pcd_table[i]=(PCDTable *) AcquireQuantumMemory(length,
2023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      sizeof(*pcd_table[i]));
2033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (pcd_table[i] == (PCDTable *) NULL)
2043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
2053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->filename);
2083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
2093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    r=pcd_table[i];
210bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (j=0; j < (ssize_t) length; j++)
2113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
2123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      PCDGetBits(8);
2133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r->length=(unsigned int) (sum & 0xff)+1;
2143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (r->length > 16)
2153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
2163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          return(MagickFalse);
2183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
2193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      PCDGetBits(16);
2203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r->sequence=(unsigned int) (sum & 0xffff) << 16;
2213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      PCDGetBits(8);
2223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r->key=(unsigned char) (sum & 0xff);
2233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r->mask=(~((1U << (32-r->length))-1));
2243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r++;
2253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
226bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    pcd_length[i]=(size_t) length;
2273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
2283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
2293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Search for Sync byte.
2303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
2313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 1; i++)
2323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PCDGetBits(16);
2333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 1; i++)
2343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PCDGetBits(16);
2353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  while ((sum & 0x00fff000UL) != 0x00fff000UL)
2363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PCDGetBits(8);
2373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  while (IsSync == 0)
2383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PCDGetBits(1);
2393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
2403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Recover the Huffman encoded luminance and chrominance deltas.
2413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
2423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  count=0;
2433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  length=0;
2443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  plane=0;
2453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  row=0;
2463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  q=luma;
2473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for ( ; ; )
2483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
2493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (IsSync != 0)
2503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
2513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
2523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Determine plane and row number.
2533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
2543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        PCDGetBits(16);
2553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        row=((sum >> 9) & 0x1fff);
2563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (row == image->rows)
2573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
2583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        PCDGetBits(8);
2593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        plane=sum >> 30;
2603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        PCDGetBits(16);
2613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        switch (plane)
2623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
2633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 0:
2643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
2653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q=luma+row*image->columns;
2663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            count=(ssize_t) image->columns;
2673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
2683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
2693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 2:
2703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
2713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q=chroma1+(row >> 1)*image->columns;
2723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            count=(ssize_t) (image->columns >> 1);
2733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            plane--;
2743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
2753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
2763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 3:
2773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
2783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q=chroma2+(row >> 1)*image->columns;
2793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            count=(ssize_t) (image->columns >> 1);
2803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            plane--;
2813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
2823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
2833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          default:
2843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
2853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            ThrowBinaryException(CorruptImageError,"CorruptImage",
2863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              image->filename);
2873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
2883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
2893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        length=pcd_length[plane];
2903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
2913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
2923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
2933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Decode luminance or chrominance deltas.
2943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
2953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    r=pcd_table[plane];
296bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (i=0; ((i < (ssize_t) length) && ((sum & r->mask) != r->sequence)); i++)
2973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r++;
2985d41880f52dcb79d3681d0841cb8882ee614a8f0cristy    if ((row > image->rows) || (r == (PCDTable *) NULL))
2993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
3003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) ThrowMagickException(&image->exception,GetMagickModule(),
3013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          CorruptImageWarning,"SkipToSyncByte","`%s'",image->filename);
3023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        while ((sum & 0x00fff000) != 0x00fff000)
3033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PCDGetBits(8);
3043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        while (IsSync == 0)
3053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PCDGetBits(1);
3063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
3073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
3083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (r->key < 128)
309bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      quantum=(ssize_t) (*q)+r->key;
3103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
311bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      quantum=(ssize_t) (*q)+r->key-256;
3123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q=(unsigned char) ((quantum < 0) ? 0 : (quantum > 255) ? 255 : quantum);
3133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q++;
3143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PCDGetBits(r->length);
3153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count--;
3163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
3173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
3183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Relinquish resources.
3193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
3203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < (image->columns > 1536 ? 3 : 1); i++)
3213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pcd_table[i]=(PCDTable *) RelinquishMagickMemory(pcd_table[i]);
3223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  buffer=(unsigned char *) RelinquishMagickMemory(buffer);
3233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
3243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
3273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   I s P C D                                                                 %
3323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  IsPCD() returns MagickTrue if the image format type, identified by the
3383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  magick string, is PCD.
3393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the IsPCD method is:
3413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType IsPCD(const unsigned char *magick,const size_t length)
3433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
3453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o magick: compare image format pattern against these bytes.
3473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o length: Specifies the length of the magick string.
3493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
3513ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType IsPCD(const unsigned char *magick,const size_t length)
3523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
3533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (length < 2052)
3543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
3553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (LocaleNCompare((const char *) magick+2048,"PCD_",4) == 0)
3563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickTrue);
3573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickFalse);
3583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
3613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e a d P C D I m a g e                                                   %
3663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ReadPCDImage() reads a Photo CD image file and returns it.  It
3723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  allocates the memory necessary for the new Image structure and returns a
3733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  pointer to the new image.  Much of the PCD decoder was derived from
3743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  the program hpcdtoppm(1) by Hadmut Danisch.
3753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the ReadPCDImage method is:
3773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      image=ReadPCDImage(image_info)
3793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
3813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
3833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o exception: return any errors or warnings in this structure.
3853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
3873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3883ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic inline size_t MagickMin(const size_t x,const size_t y)
3893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
3903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (x < y)
3913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(x);
3923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(y);
3933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3953ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic Image *OverviewImage(const ImageInfo *image_info,Image *image,
3963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ExceptionInfo *exception)
3973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
3983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
3993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *montage_image;
4003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MontageInfo
4023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *montage_info;
4033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register Image
4053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
4063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
4083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Create the PCD Overview image.
4093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
4103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (p=image; p != (Image *) NULL; p=p->next)
4113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
4123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) DeleteImageProperty(p,"label");
4133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) SetImageProperty(p,"label",DefaultTileLabel);
4143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
4153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  montage_info=CloneMontageInfo(image_info,(MontageInfo *) NULL);
4163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CopyMagickString(montage_info->filename,image_info->filename,
4173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    MaxTextExtent);
4183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  montage_image=MontageImageList(image_info,montage_info,image,exception);
4193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  montage_info=DestroyMontageInfo(montage_info);
4203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (montage_image == (Image *) NULL)
4213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
4223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image=DestroyImage(image);
4233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(montage_image);
4243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
4253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
426bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristystatic void Upsample(const size_t width,const size_t height,
427bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  const size_t scaled_width,unsigned char *pixels)
4283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
429bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
4303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x,
4313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    y;
4323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register unsigned char
4343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p,
4353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q,
4363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *r;
4373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
4393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Create a new image that is a integral size greater than an existing one.
4403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
4413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(pixels != (unsigned char *) NULL);
442bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) height; y++)
4433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
4443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    p=pixels+(height-1-y)*scaled_width+(width-1);
4453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q=pixels+((height-1-y) << 1)*scaled_width+((width-1) << 1);
4463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q=(*p);
4473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *(q+1)=(*(p));
448bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=1; x < (ssize_t) width; x++)
4493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
4503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      p--;
4513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q-=2;
4523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *q=(*p);
453bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      *(q+1)=(unsigned char) ((((size_t) *p)+
454bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        ((size_t) *(p+1))+1) >> 1);
4553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
4563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
457bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) (height-1); y++)
4583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
459bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    p=pixels+((size_t) y << 1)*scaled_width;
4603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q=p+scaled_width;
4613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    r=q+scaled_width;
462bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) (width-1); x++)
4633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
464bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      *q=(unsigned char) ((((size_t) *p)+((size_t) *r)+1) >> 1);
465bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      *(q+1)=(unsigned char) ((((size_t) *p)+((size_t) *(p+2))+
466bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        ((size_t) *r)+((size_t) *(r+2))+2) >> 2);
4673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q+=2;
4683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      p+=2;
4693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r+=2;
4703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
471bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    *q++=(unsigned char) ((((size_t) *p++)+
472bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      ((size_t) *r++)+1) >> 1);
473bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    *q++=(unsigned char) ((((size_t) *p++)+
474bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      ((size_t) *r++)+1) >> 1);
4753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
4763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  p=pixels+(2*height-2)*scaled_width;
4773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  q=pixels+(2*height-1)*scaled_width;
4783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CopyMagickMemory(q,p,(size_t) (2*width));
4793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
4803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4813ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic Image *ReadPCDImage(const ImageInfo *image_info,ExceptionInfo *exception)
4823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
4833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
4843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *image;
4853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
486bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  ssize_t
4873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x;
4883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
4903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
4913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickOffsetType
4933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    offset;
4943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickSizeType
4963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    number_pixels;
4973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
498bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
4993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
5003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    y;
5013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register PixelPacket
5033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
5043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register unsigned char
5063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *c1,
5073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *c2,
5083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *yy;
5093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ssize_t
5113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count;
5123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned char
5143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *chroma1,
5153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *chroma2,
5163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *header,
5173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *luma;
5183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned int
5203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    overview;
5213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
522bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  size_t
5233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    height,
5243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    number_images,
5253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    rotate,
5263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    scene,
5273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    width;
5283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
5303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open image file.
5313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
5323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
5333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info->signature == MagickSignature);
5343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->debug != MagickFalse)
5353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
5363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image_info->filename);
5373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception != (ExceptionInfo *) NULL);
5383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception->signature == MagickSignature);
5393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image=AcquireImage(image_info);
5403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
5413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
5423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
5433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image=DestroyImageList(image);
5443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return((Image *) NULL);
5453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
5463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
5473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Determine if this a PCD file.
5483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
5493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  header=(unsigned char *) AcquireQuantumMemory(0x800,3UL*sizeof(*header));
5503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (header == (unsigned char *) NULL)
5513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
5523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  count=ReadBlob(image,3*0x800,header);
5533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  overview=LocaleNCompare((char *) header,"PCD_OPA",7) == 0;
5543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((count == 0) ||
5553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ((LocaleNCompare((char *) header+0x800,"PCD",3) != 0) && !overview))
5563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
5573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  rotate=header[0x0e02] & 0x03;
5583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  number_images=(header[10] << 8) | header[11];
5593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  header=(unsigned char *) RelinquishMagickMemory(header);
5603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
5613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Determine resolution by scene specification.
5623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
5633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((image->columns == 0) || (image->rows == 0))
5643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    scene=3;
5653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
5663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
5673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      width=192;
5683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      height=128;
5693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (scene=1; scene < 6; scene++)
5703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
5713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if ((width >= image->columns) && (height >= image->rows))
5723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
5733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        width<<=1;
5743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        height<<=1;
5753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
5763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
5773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->number_scenes != 0)
578bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    scene=(size_t) MagickMin(image_info->scene,6);
5793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (overview)
5803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    scene=1;
5813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
5823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Initialize image structure.
5833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
5843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  width=192;
5853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  height=128;
586bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (i=1; i < (ssize_t) MagickMin(scene,3); i++)
5873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
5883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    width<<=1;
5893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    height<<=1;
5903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
5913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->columns=width;
5923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->rows=height;
5933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->depth=8;
594bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for ( ; i < (ssize_t) scene; i++)
5953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
5963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image->columns<<=1;
5973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image->rows<<=1;
5983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
5993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
6005d41880f52dcb79d3681d0841cb8882ee614a8f0cristy    Allocate luma and chroma memory.
6013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
6023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  number_pixels=(MagickSizeType) image->columns*image->rows;
6033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (number_pixels != (size_t) number_pixels)
6043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
6053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chroma1=(unsigned char *) AcquireQuantumMemory(image->columns+1UL,image->rows*
6063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sizeof(*chroma1));
6073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chroma2=(unsigned char *) AcquireQuantumMemory(image->columns+1UL,image->rows*
6083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sizeof(*chroma2));
6093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  luma=(unsigned char *) AcquireQuantumMemory(image->columns+1UL,image->rows*
6103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sizeof(*luma));
6113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((chroma1 == (unsigned char *) NULL) ||
6123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (chroma2 == (unsigned char *) NULL) || (luma == (unsigned char *) NULL))
6133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
6143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
6153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Advance to image data.
6163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
6173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  offset=93;
6183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (overview)
6193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    offset=2;
6203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
6213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (scene == 2)
6223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      offset=20;
6233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
6243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (scene <= 1)
6253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset=1;
626bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (i=0; i < (ssize_t) (offset*0x800); i++)
6273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) ReadBlobByte(image);
6283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (overview)
6293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
6303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Image
6313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *overview_image;
6323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      MagickProgressMonitor
6343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        progress_monitor;
6353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
636bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      register ssize_t
6373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        j;
6383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
6403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Read thumbnails from overview image.
6413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
642bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      for (j=1; j <= (ssize_t) number_images; j++)
6433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
6443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        progress_monitor=SetImageProgressMonitor(image,
6453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (MagickProgressMonitor) NULL,image->client_data);
6463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) FormatMagickString(image->filename,MaxTextExtent,
6473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "images/img%04ld.pcd",j);
6483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) FormatMagickString(image->magick_filename,MaxTextExtent,
6493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "images/img%04ld.pcd",j);
650bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        image->scene=(size_t) j;
6513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->columns=width;
6523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->rows=height;
6533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->depth=8;
6543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        yy=luma;
6553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        c1=chroma1;
6563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        c2=chroma2;
657bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        for (y=0; y < (ssize_t) height; y+=2)
6583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
6593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          count=ReadBlob(image,width,yy);
6603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          yy+=image->columns;
6613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          count=ReadBlob(image,width,yy);
6623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          yy+=image->columns;
6633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          count=ReadBlob(image,width >> 1,c1);
6643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          c1+=image->columns;
6653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          count=ReadBlob(image,width >> 1,c2);
6663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          c2+=image->columns;
6673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
6683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Upsample(image->columns >> 1,image->rows >> 1,image->columns,chroma1);
6693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Upsample(image->columns >> 1,image->rows >> 1,image->columns,chroma2);
6703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
6713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Transfer luminance and chrominance channels.
6723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
6733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        yy=luma;
6743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        c1=chroma1;
6753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        c2=chroma2;
676bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        for (y=0; y < (ssize_t) image->rows; y++)
6773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
6783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
6793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (q == (PixelPacket *) NULL)
6803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
681bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy          for (x=0; x < (ssize_t) image->columns; x++)
6823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
6833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q->red=ScaleCharToQuantum(*yy++);
6843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q->green=ScaleCharToQuantum(*c1++);
6853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q->blue=ScaleCharToQuantum(*c2++);
6863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q++;
6873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
6883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (SyncAuthenticPixels(image,exception) == MagickFalse)
6893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
6903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
6913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->colorspace=YCCColorspace;
6923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (LocaleCompare(image_info->magick,"PCDS") == 0)
6933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->colorspace=sRGBColorspace;
694bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        if (j < (ssize_t) number_images)
6953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
6963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
6973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Allocate next image structure.
6983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
6993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            AcquireNextImage(image_info,image);
7003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (GetNextImageInList(image) == (Image *) NULL)
7013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
7023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image=DestroyImageList(image);
7033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                return((Image *) NULL);
7043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
7053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image=SyncNextImageInList(image);
7063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
7073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) SetImageProgressMonitor(image,progress_monitor,
7083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->client_data);
7093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (image->previous == (Image *) NULL)
7103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
7113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            status=SetImageProgress(image,LoadImageTag,j-1,number_images);
7123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (status == MagickFalse)
7133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              break;
7143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
7153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
7163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      chroma2=(unsigned char *) RelinquishMagickMemory(chroma2);
7173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      chroma1=(unsigned char *) RelinquishMagickMemory(chroma1);
7183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      luma=(unsigned char *) RelinquishMagickMemory(luma);
7193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image=GetFirstImageInList(image);
7203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      overview_image=OverviewImage(image_info,image,exception);
7213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return(overview_image);
7223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
7243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Read interleaved image.
7253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
7263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  yy=luma;
7273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  c1=chroma1;
7283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  c2=chroma2;
729bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) height; y+=2)
7303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
7313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count=ReadBlob(image,width,yy);
7323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    yy+=image->columns;
7333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count=ReadBlob(image,width,yy);
7343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    yy+=image->columns;
7353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count=ReadBlob(image,width >> 1,c1);
7363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    c1+=image->columns;
7373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count=ReadBlob(image,width >> 1,c2);
7383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    c2+=image->columns;
7393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
7403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (scene >= 4)
7413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
7423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
7433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Recover luminance deltas for 1536x1024 image.
7443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
7453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Upsample(768,512,image->columns,luma);
7463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Upsample(384,256,image->columns,chroma1);
7473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Upsample(384,256,image->columns,chroma2);
7483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->rows=1024;
7493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (i=0; i < (4*0x800); i++)
7503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) ReadBlobByte(image);
7513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      status=DecodeImage(image,luma,chroma1,chroma2);
7523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((scene >= 5) && status)
7533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
7543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /*
7553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            Recover luminance deltas for 3072x2048 image.
7563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          */
7573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Upsample(1536,1024,image->columns,luma);
7583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Upsample(768,512,image->columns,chroma1);
7593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Upsample(768,512,image->columns,chroma2);
7603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->rows=2048;
7613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          offset=TellBlob(image)/0x800+12;
7623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          offset=SeekBlob(image,offset*0x800,SEEK_SET);
7633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          status=DecodeImage(image,luma,chroma1,chroma2);
7643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if ((scene >= 6) && (status != MagickFalse))
7653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
7663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              /*
7673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                Recover luminance deltas for 6144x4096 image (vaporware).
7683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              */
7693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Upsample(3072,2048,image->columns,luma);
7703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Upsample(1536,1024,image->columns,chroma1);
7713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Upsample(1536,1024,image->columns,chroma2);
7723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              image->rows=4096;
7733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
7743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
7753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Upsample(image->columns >> 1,image->rows >> 1,image->columns,chroma1);
7773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Upsample(image->columns >> 1,image->rows >> 1,image->columns,chroma2);
7783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
7793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Transfer luminance and chrominance channels.
7803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
7813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  yy=luma;
7823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  c1=chroma1;
7833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  c2=chroma2;
784bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) image->rows; y++)
7853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
7863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
7873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (q == (PixelPacket *) NULL)
7883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
789bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) image->columns; x++)
7903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
7913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q->red=ScaleCharToQuantum(*yy++);
7923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q->green=ScaleCharToQuantum(*c1++);
7933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q->blue=ScaleCharToQuantum(*c2++);
7943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q++;
7953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (SyncAuthenticPixels(image,exception) == MagickFalse)
7973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
7983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (image->previous == (Image *) NULL)
7993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
8003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        status=SetImageProgress(image,LoadImageTag,y,image->rows);
8013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (status == MagickFalse)
8023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
8033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
8043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
8053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chroma2=(unsigned char *) RelinquishMagickMemory(chroma2);
8063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chroma1=(unsigned char *) RelinquishMagickMemory(chroma1);
8073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  luma=(unsigned char *) RelinquishMagickMemory(luma);
8083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (EOFBlob(image) != MagickFalse)
8093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
8103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->filename);
8113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(image);
8123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->ping == MagickFalse)
8133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if ((rotate == 1) || (rotate == 3))
8143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
8153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        double
8163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          degrees;
8173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Image
8193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          *rotate_image;
8203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
8223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Rotate image.
8233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
8243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        degrees=rotate == 1 ? -90.0 : 90.0;
8253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        rotate_image=RotateImage(image,degrees,exception);
8263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (rotate_image != (Image *) NULL)
8273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
8283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image=DestroyImage(image);
8293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image=rotate_image;
8303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
8313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
8323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
8333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Set CCIR 709 primaries with a D65 white point.
8343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
8353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.red_primary.x=0.6400f;
8363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.red_primary.y=0.3300f;
8373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.green_primary.x=0.3000f;
8383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.green_primary.y=0.6000f;
8393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.blue_primary.x=0.1500f;
8403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.blue_primary.y=0.0600f;
8413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.white_point.x=0.3127f;
8423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.white_point.y=0.3290f;
8433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->gamma=1.000f/2.200f;
8443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->colorspace=YCCColorspace;
8453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (LocaleCompare(image_info->magick,"PCDS") == 0)
8463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image->colorspace=sRGBColorspace;
8473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(GetFirstImageInList(image));
8483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
8493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
8513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e g i s t e r P C D I m a g e                                           %
8563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  RegisterPCDImage() adds attributes for the PCD image format to
8623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  the list of supported formats.  The attributes include the image format
8633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  tag, a method to read and/or write the format, whether the format
8643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  supports the saving of more than one frame to the same file or blob,
8653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  whether the format supports native in-memory I/O, and a brief
8663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  description of the format.
8673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the RegisterPCDImage method is:
8693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
870bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy%      size_t RegisterPCDImage(void)
8713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
873bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristyModuleExport size_t RegisterPCDImage(void)
8743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
8753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickInfo
8763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *entry;
8773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry=SetMagickInfo("PCD");
8793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadPCDImage;
8803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WritePCDImage;
8813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->magick=(IsImageFormatHandler *) IsPCD;
8823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->adjoin=MagickFalse;
8833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->description=ConstantString("Photo CD");
8843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->module=ConstantString("PCD");
8853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
8863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry=SetMagickInfo("PCDS");
8873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadPCDImage;
8883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WritePCDImage;
8893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->adjoin=MagickFalse;
8903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->description=ConstantString("Photo CD");
8913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->module=ConstantString("PCD");
8923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
8933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickImageCoderSignature);
8943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
8953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
8973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   U n r e g i s t e r P C D I m a g e                                       %
9023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  UnregisterPCDImage() removes format registrations made by the
9083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  PCD module from the list of supported formats.
9093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the UnregisterPCDImage method is:
9113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      UnregisterPCDImage(void)
9133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
9153ed852eea50f9d4cd633efb8c2b054b8e33c253cristyModuleExport void UnregisterPCDImage(void)
9163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
9173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("PCD");
9183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("PCDS");
9193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
9203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
9223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   W r i t e P C D I m a g e                                                 %
9273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  WritePCDImage() writes an image in the Photo CD encoded image format.
9333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the WritePCDImage method is:
9353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType WritePCDImage(const ImageInfo *image_info,Image *image)
9373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows.
9393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
9413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image:  The image.
9433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
9453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9463ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType WritePCDTile(Image *image,const char *page_geometry,
9473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const char *tile_geometry)
9483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
9493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  GeometryInfo
9503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry_info;
9513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
9533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *downsample_image,
9543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *tile_image;
9553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
956bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  ssize_t
9573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    y;
9583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
9603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
9613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickStatusType
9633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    flags;
9643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  RectangleInfo
9663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry;
9673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register const PixelPacket
9693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p,
9703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
9713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
972bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
9733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
9743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x;
9753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
9773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Scale image to tile size.
9783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
9793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  SetGeometry(image,&geometry);
9803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ParseMetaGeometry(page_geometry,&geometry.x,&geometry.y,
9813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    &geometry.width,&geometry.height);
9823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((geometry.width % 2) != 0)
9833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry.width--;
9843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((geometry.height % 2) != 0)
9853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry.height--;
9863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  tile_image=ResizeImage(image,geometry.width,geometry.height,TriangleFilter,
9873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    1.0,&image->exception);
9883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (tile_image == (Image *) NULL)
9893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
9903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  flags=ParseGeometry(page_geometry,&geometry_info);
991bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  geometry.width=(size_t) geometry_info.rho;
992bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  geometry.height=(size_t) geometry_info.sigma;
9933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((flags & SigmaValue) == 0)
9943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry.height=geometry.width;
9953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((tile_image->columns != geometry.width) ||
9963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (tile_image->rows != geometry.height))
9973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
9983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Image
9993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *bordered_image;
10003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      RectangleInfo
10023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        border_info;
10033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
10053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Put a border around the image.
10063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
10073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      border_info.width=(geometry.width-tile_image->columns+1) >> 1;
10083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      border_info.height=(geometry.height-tile_image->rows+1) >> 1;
10093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      bordered_image=BorderImage(tile_image,&border_info,&image->exception);
10103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (bordered_image == (Image *) NULL)
10113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        return(MagickFalse);
10123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      tile_image=DestroyImage(tile_image);
10133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      tile_image=bordered_image;
10143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
10153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) TransformImage(&tile_image,(char *) NULL,tile_geometry);
10163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->colorspace != RGBColorspace)
10173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) TransformImageColorspace(tile_image,YCCColorspace);
10183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  downsample_image=ResizeImage(tile_image,tile_image->columns/2,
10193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    tile_image->rows/2,TriangleFilter,1.0,&image->exception);
10203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (downsample_image == (Image *) NULL)
10213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
10223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
10233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Write tile to PCD file.
10243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
1025bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) tile_image->rows; y+=2)
10263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
10273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    p=GetVirtualPixels(tile_image,0,y,tile_image->columns,2,
10283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      &tile_image->exception);
10293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (p == (const PixelPacket *) NULL)
10303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
1031bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) (tile_image->columns << 1); x++)
10323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
1033ce70c17bb6433add2eb069515a4f3105989e0662cristy      (void) WriteBlobByte(image,ScaleQuantumToChar(GetRedPixelComponent(p)));
10343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      p++;
10353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
10363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q=GetVirtualPixels(downsample_image,0,y >> 1,downsample_image->columns,
10373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      1,&downsample_image->exception);
10383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (q == (const PixelPacket *) NULL)
10393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
1040bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) downsample_image->columns; x++)
10413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
10423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) WriteBlobByte(image,ScaleQuantumToChar(q->green));
10433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q++;
10443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
10453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q=GetVirtualPixels(downsample_image,0,y >> 1,downsample_image->columns,
10463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      1,&downsample_image->exception);
10473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (q == (const PixelPacket *) NULL)
10483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
1049bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) downsample_image->columns; x++)
10503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
10513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) WriteBlobByte(image,ScaleQuantumToChar(q->blue));
10523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q++;
10533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
10543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status=SetImageProgress(image,SaveImageTag,y,tile_image->rows);
10553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (status == MagickFalse)
10563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
10573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
10583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 0x800; i++)
10593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(image,'\0');
10603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  downsample_image=DestroyImage(downsample_image);
10613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  tile_image=DestroyImage(tile_image);
10623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
10633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
10643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10653ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType WritePCDImage(const ImageInfo *image_info,Image *image)
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      */
10913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      rotate_image=RotateImage(image,90.0,&image->exception);
10923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (rotate_image == (Image *) NULL)
10933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        return(MagickFalse);
10943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      pcd_image=rotate_image;
10953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
10963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
10973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open output image file.
10983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
10993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=OpenBlob(image_info,pcd_image,WriteBinaryBlobMode,&image->exception);
11003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
11013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(status);
11023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->colorspace != RGBColorspace)
11033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) TransformImageColorspace(pcd_image,RGBColorspace);
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  */
11403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=WritePCDTile(pcd_image,"768x512>","192x128");
11413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=WritePCDTile(pcd_image,"768x512>","384x256");
11423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=WritePCDTile(pcd_image,"768x512>","768x512");
11433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(pcd_image);
11443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (pcd_image != image)
11453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pcd_image=DestroyImage(pcd_image);
11463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(status);
11473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1148