pcd.c revision 3ed852eea50f9d4cd633efb8c2b054b8e33c253
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%                                                                             %
203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Copyright 1999-2009 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
1473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  long
1483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    quantum;
1493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  PCDTable
1513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *pcd_table[3];
1523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register long
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
1733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned long
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];
2103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for (j=0; j < (long) 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    }
2263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pcd_length[i]=(unsigned long) 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];
2963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for (i=0; ((i < (long) length) && ((sum & r->mask) != r->sequence)); i++)
2973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r++;
2983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if ((row > image->rows) || (r == (PCDTable *) NULL) ||
2993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ((size_t) (q-luma) > (image->columns*image->rows)))
3003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
3013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) ThrowMagickException(&image->exception,GetMagickModule(),
3023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          CorruptImageWarning,"SkipToSyncByte","`%s'",image->filename);
3033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        while ((sum & 0x00fff000) != 0x00fff000)
3043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PCDGetBits(8);
3053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        while (IsSync == 0)
3063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PCDGetBits(1);
3073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
3083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
3093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (r->key < 128)
3103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      quantum=(long) (*q)+r->key;
3113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
3123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      quantum=(long) (*q)+r->key-256;
3133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q=(unsigned char) ((quantum < 0) ? 0 : (quantum > 255) ? 255 : quantum);
3143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q++;
3153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PCDGetBits(r->length);
3163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count--;
3173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
3183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
3193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Relinquish resources.
3203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
3213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < (image->columns > 1536 ? 3 : 1); i++)
3223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pcd_table[i]=(PCDTable *) RelinquishMagickMemory(pcd_table[i]);
3233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  buffer=(unsigned char *) RelinquishMagickMemory(buffer);
3243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
3253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
3283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   I s P C D                                                                 %
3333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  IsPCD() returns MagickTrue if the image format type, identified by the
3393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  magick string, is PCD.
3403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the IsPCD method is:
3423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType IsPCD(const unsigned char *magick,const size_t length)
3443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
3463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o magick: compare image format pattern against these bytes.
3483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o length: Specifies the length of the magick string.
3503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
3523ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType IsPCD(const unsigned char *magick,const size_t length)
3533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
3543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (length < 2052)
3553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
3563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (LocaleNCompare((const char *) magick+2048,"PCD_",4) == 0)
3573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickTrue);
3583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickFalse);
3593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
3623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e a d P C D I m a g e                                                   %
3673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ReadPCDImage() reads a Photo CD image file and returns it.  It
3733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  allocates the memory necessary for the new Image structure and returns a
3743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  pointer to the new image.  Much of the PCD decoder was derived from
3753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  the program hpcdtoppm(1) by Hadmut Danisch.
3763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the ReadPCDImage method is:
3783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      image=ReadPCDImage(image_info)
3803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
3823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
3843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o exception: return any errors or warnings in this structure.
3863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
3883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3893ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic inline size_t MagickMin(const size_t x,const size_t y)
3903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
3913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (x < y)
3923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(x);
3933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(y);
3943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3963ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic Image *OverviewImage(const ImageInfo *image_info,Image *image,
3973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ExceptionInfo *exception)
3983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
3993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
4003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *montage_image;
4013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MontageInfo
4033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *montage_info;
4043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register Image
4063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
4073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
4093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Create the PCD Overview image.
4103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
4113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (p=image; p != (Image *) NULL; p=p->next)
4123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
4133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) DeleteImageProperty(p,"label");
4143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) SetImageProperty(p,"label",DefaultTileLabel);
4153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
4163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  montage_info=CloneMontageInfo(image_info,(MontageInfo *) NULL);
4173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CopyMagickString(montage_info->filename,image_info->filename,
4183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    MaxTextExtent);
4193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  montage_image=MontageImageList(image_info,montage_info,image,exception);
4203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  montage_info=DestroyMontageInfo(montage_info);
4213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (montage_image == (Image *) NULL)
4223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
4233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image=DestroyImage(image);
4243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(montage_image);
4253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
4263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4273ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic void Upsample(const unsigned long width,const unsigned long height,
4283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const unsigned long scaled_width,unsigned char *pixels)
4293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
4303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register long
4313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x,
4323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    y;
4333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register unsigned char
4353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p,
4363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q,
4373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *r;
4383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
4403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Create a new image that is a integral size greater than an existing one.
4413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
4423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(pixels != (unsigned char *) NULL);
4433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (y=0; y < (long) height; y++)
4443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
4453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    p=pixels+(height-1-y)*scaled_width+(width-1);
4463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q=pixels+((height-1-y) << 1)*scaled_width+((width-1) << 1);
4473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q=(*p);
4483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *(q+1)=(*(p));
4493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for (x=1; x < (long) width; x++)
4503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
4513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      p--;
4523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q-=2;
4533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *q=(*p);
4543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *(q+1)=(unsigned char) ((((unsigned long) *p)+
4553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ((unsigned long) *(p+1))+1) >> 1);
4563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
4573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
4583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (y=0; y < (long) (height-1); y++)
4593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
4603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    p=pixels+((unsigned long) y << 1)*scaled_width;
4613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q=p+scaled_width;
4623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    r=q+scaled_width;
4633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for (x=0; x < (long) (width-1); x++)
4643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
4653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *q=(unsigned char) ((((unsigned long) *p)+((unsigned long) *r)+1) >> 1);
4663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *(q+1)=(unsigned char) ((((unsigned long) *p)+((unsigned long) *(p+2))+
4673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ((unsigned long) *r)+((unsigned long) *(r+2))+2) >> 2);
4683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q+=2;
4693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      p+=2;
4703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r+=2;
4713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
4723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q++=(unsigned char) ((((unsigned long) *p++)+
4733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ((unsigned long) *r++)+1) >> 1);
4743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q++=(unsigned char) ((((unsigned long) *p++)+
4753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ((unsigned long) *r++)+1) >> 1);
4763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
4773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  p=pixels+(2*height-2)*scaled_width;
4783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  q=pixels+(2*height-1)*scaled_width;
4793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CopyMagickMemory(q,p,(size_t) (2*width));
4803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
4813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4823ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic Image *ReadPCDImage(const ImageInfo *image_info,ExceptionInfo *exception)
4833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
4843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
4853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *image;
4863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  long
4883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x;
4893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
4913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
4923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickOffsetType
4943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    offset;
4953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickSizeType
4973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    number_pixels;
4983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register long
5003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
5013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    y;
5023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register PixelPacket
5043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
5053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register unsigned char
5073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *c1,
5083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *c2,
5093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *yy;
5103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ssize_t
5123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count;
5133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned char
5153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *chroma1,
5163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *chroma2,
5173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *header,
5183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *luma;
5193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned int
5213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    overview;
5223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned long
5243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    height,
5253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    number_images,
5263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    rotate,
5273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    scene,
5283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    width;
5293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
5313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open image file.
5323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
5333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
5343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info->signature == MagickSignature);
5353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->debug != MagickFalse)
5363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
5373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image_info->filename);
5383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception != (ExceptionInfo *) NULL);
5393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception->signature == MagickSignature);
5403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image=AcquireImage(image_info);
5413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
5423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
5433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
5443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image=DestroyImageList(image);
5453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return((Image *) NULL);
5463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
5473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
5483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Determine if this a PCD file.
5493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
5503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  header=(unsigned char *) AcquireQuantumMemory(0x800,3UL*sizeof(*header));
5513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (header == (unsigned char *) NULL)
5523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
5533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  count=ReadBlob(image,3*0x800,header);
5543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  overview=LocaleNCompare((char *) header,"PCD_OPA",7) == 0;
5553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((count == 0) ||
5563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ((LocaleNCompare((char *) header+0x800,"PCD",3) != 0) && !overview))
5573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
5583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  rotate=header[0x0e02] & 0x03;
5593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  number_images=(header[10] << 8) | header[11];
5603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  header=(unsigned char *) RelinquishMagickMemory(header);
5613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
5623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Determine resolution by scene specification.
5633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
5643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((image->columns == 0) || (image->rows == 0))
5653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    scene=3;
5663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
5673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
5683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      width=192;
5693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      height=128;
5703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (scene=1; scene < 6; scene++)
5713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
5723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if ((width >= image->columns) && (height >= image->rows))
5733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
5743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        width<<=1;
5753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        height<<=1;
5763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
5773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
5783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->number_scenes != 0)
5793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    scene=(unsigned long) MagickMin(image_info->scene,6);
5803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (overview)
5813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    scene=1;
5823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
5833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Initialize image structure.
5843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
5853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  width=192;
5863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  height=128;
5873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=1; i < (long) MagickMin(scene,3); i++)
5883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
5893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    width<<=1;
5903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    height<<=1;
5913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
5923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->columns=width;
5933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->rows=height;
5943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->depth=8;
5953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for ( ; i < (long) scene; i++)
5963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
5973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image->columns<<=1;
5983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image->rows<<=1;
5993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
6003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
6013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Allocate lumand chroma memory.
6023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
6033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  number_pixels=(MagickSizeType) image->columns*image->rows;
6043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (number_pixels != (size_t) number_pixels)
6053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
6063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chroma1=(unsigned char *) AcquireQuantumMemory(image->columns+1UL,image->rows*
6073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sizeof(*chroma1));
6083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chroma2=(unsigned char *) AcquireQuantumMemory(image->columns+1UL,image->rows*
6093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sizeof(*chroma2));
6103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  luma=(unsigned char *) AcquireQuantumMemory(image->columns+1UL,image->rows*
6113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sizeof(*luma));
6123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((chroma1 == (unsigned char *) NULL) ||
6133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (chroma2 == (unsigned char *) NULL) || (luma == (unsigned char *) NULL))
6143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
6153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
6163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Advance to image data.
6173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
6183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  offset=93;
6193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (overview)
6203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    offset=2;
6213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
6223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (scene == 2)
6233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      offset=20;
6243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
6253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (scene <= 1)
6263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset=1;
6273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < (long) (offset*0x800); i++)
6283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) ReadBlobByte(image);
6293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (overview)
6303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
6313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Image
6323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *overview_image;
6333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      MagickProgressMonitor
6353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        progress_monitor;
6363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      register long
6383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        j;
6393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
6413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Read thumbnails from overview image.
6423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
6433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (j=1; j <= (long) number_images; j++)
6443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
6453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        progress_monitor=SetImageProgressMonitor(image,
6463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (MagickProgressMonitor) NULL,image->client_data);
6473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) FormatMagickString(image->filename,MaxTextExtent,
6483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "images/img%04ld.pcd",j);
6493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) FormatMagickString(image->magick_filename,MaxTextExtent,
6503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          "images/img%04ld.pcd",j);
6513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->scene=(unsigned long) j;
6523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->columns=width;
6533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->rows=height;
6543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->depth=8;
6553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        yy=luma;
6563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        c1=chroma1;
6573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        c2=chroma2;
6583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        for (y=0; y < (long) height; y+=2)
6593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
6603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          count=ReadBlob(image,width,yy);
6613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          yy+=image->columns;
6623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          count=ReadBlob(image,width,yy);
6633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          yy+=image->columns;
6643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          count=ReadBlob(image,width >> 1,c1);
6653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          c1+=image->columns;
6663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          count=ReadBlob(image,width >> 1,c2);
6673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          c2+=image->columns;
6683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
6693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Upsample(image->columns >> 1,image->rows >> 1,image->columns,chroma1);
6703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Upsample(image->columns >> 1,image->rows >> 1,image->columns,chroma2);
6713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
6723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Transfer luminance and chrominance channels.
6733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
6743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        yy=luma;
6753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        c1=chroma1;
6763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        c2=chroma2;
6773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        for (y=0; y < (long) image->rows; y++)
6783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
6793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
6803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (q == (PixelPacket *) NULL)
6813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
6823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          for (x=0; x < (long) image->columns; x++)
6833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
6843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q->red=ScaleCharToQuantum(*yy++);
6853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q->green=ScaleCharToQuantum(*c1++);
6863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q->blue=ScaleCharToQuantum(*c2++);
6873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q++;
6883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
6893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (SyncAuthenticPixels(image,exception) == MagickFalse)
6903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
6913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
6923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->colorspace=YCCColorspace;
6933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (LocaleCompare(image_info->magick,"PCDS") == 0)
6943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->colorspace=sRGBColorspace;
6953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (j < (long) number_images)
6963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
6973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
6983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Allocate next image structure.
6993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
7003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            AcquireNextImage(image_info,image);
7013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (GetNextImageInList(image) == (Image *) NULL)
7023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
7033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image=DestroyImageList(image);
7043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                return((Image *) NULL);
7053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
7063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image=SyncNextImageInList(image);
7073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
7083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) SetImageProgressMonitor(image,progress_monitor,
7093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->client_data);
7103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (image->previous == (Image *) NULL)
7113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
7123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            status=SetImageProgress(image,LoadImageTag,j-1,number_images);
7133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (status == MagickFalse)
7143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              break;
7153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
7163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
7173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      chroma2=(unsigned char *) RelinquishMagickMemory(chroma2);
7183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      chroma1=(unsigned char *) RelinquishMagickMemory(chroma1);
7193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      luma=(unsigned char *) RelinquishMagickMemory(luma);
7203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image=GetFirstImageInList(image);
7213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      overview_image=OverviewImage(image_info,image,exception);
7223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return(overview_image);
7233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
7253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Read interleaved image.
7263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
7273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  yy=luma;
7283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  c1=chroma1;
7293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  c2=chroma2;
7303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (y=0; y < (long) height; y+=2)
7313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
7323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count=ReadBlob(image,width,yy);
7333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    yy+=image->columns;
7343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count=ReadBlob(image,width,yy);
7353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    yy+=image->columns;
7363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count=ReadBlob(image,width >> 1,c1);
7373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    c1+=image->columns;
7383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count=ReadBlob(image,width >> 1,c2);
7393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    c2+=image->columns;
7403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
7413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (scene >= 4)
7423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
7433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
7443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Recover luminance deltas for 1536x1024 image.
7453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
7463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Upsample(768,512,image->columns,luma);
7473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Upsample(384,256,image->columns,chroma1);
7483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Upsample(384,256,image->columns,chroma2);
7493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->rows=1024;
7503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (i=0; i < (4*0x800); i++)
7513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) ReadBlobByte(image);
7523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      status=DecodeImage(image,luma,chroma1,chroma2);
7533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((scene >= 5) && status)
7543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
7553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /*
7563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            Recover luminance deltas for 3072x2048 image.
7573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          */
7583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Upsample(1536,1024,image->columns,luma);
7593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Upsample(768,512,image->columns,chroma1);
7603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Upsample(768,512,image->columns,chroma2);
7613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->rows=2048;
7623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          offset=TellBlob(image)/0x800+12;
7633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          offset=SeekBlob(image,offset*0x800,SEEK_SET);
7643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          status=DecodeImage(image,luma,chroma1,chroma2);
7653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if ((scene >= 6) && (status != MagickFalse))
7663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
7673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              /*
7683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                Recover luminance deltas for 6144x4096 image (vaporware).
7693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              */
7703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Upsample(3072,2048,image->columns,luma);
7713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Upsample(1536,1024,image->columns,chroma1);
7723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Upsample(1536,1024,image->columns,chroma2);
7733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              image->rows=4096;
7743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
7753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
7763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Upsample(image->columns >> 1,image->rows >> 1,image->columns,chroma1);
7783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Upsample(image->columns >> 1,image->rows >> 1,image->columns,chroma2);
7793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
7803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Transfer luminance and chrominance channels.
7813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
7823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  yy=luma;
7833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  c1=chroma1;
7843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  c2=chroma2;
7853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (y=0; y < (long) image->rows; y++)
7863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
7873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
7883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (q == (PixelPacket *) NULL)
7893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
7903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for (x=0; x < (long) image->columns; x++)
7913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
7923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q->red=ScaleCharToQuantum(*yy++);
7933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q->green=ScaleCharToQuantum(*c1++);
7943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q->blue=ScaleCharToQuantum(*c2++);
7953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q++;
7963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (SyncAuthenticPixels(image,exception) == MagickFalse)
7983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
7993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (image->previous == (Image *) NULL)
8003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
8013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        status=SetImageProgress(image,LoadImageTag,y,image->rows);
8023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (status == MagickFalse)
8033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
8043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
8053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
8063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chroma2=(unsigned char *) RelinquishMagickMemory(chroma2);
8073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chroma1=(unsigned char *) RelinquishMagickMemory(chroma1);
8083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  luma=(unsigned char *) RelinquishMagickMemory(luma);
8093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (EOFBlob(image) != MagickFalse)
8103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
8113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->filename);
8123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(image);
8133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->ping == MagickFalse)
8143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if ((rotate == 1) || (rotate == 3))
8153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
8163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        double
8173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          degrees;
8183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Image
8203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          *rotate_image;
8213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
8233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Rotate image.
8243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
8253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        degrees=rotate == 1 ? -90.0 : 90.0;
8263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        rotate_image=RotateImage(image,degrees,exception);
8273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (rotate_image != (Image *) NULL)
8283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
8293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image=DestroyImage(image);
8303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image=rotate_image;
8313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
8323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
8333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
8343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Set CCIR 709 primaries with a D65 white point.
8353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
8363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.red_primary.x=0.6400f;
8373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.red_primary.y=0.3300f;
8383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.green_primary.x=0.3000f;
8393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.green_primary.y=0.6000f;
8403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.blue_primary.x=0.1500f;
8413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.blue_primary.y=0.0600f;
8423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.white_point.x=0.3127f;
8433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.white_point.y=0.3290f;
8443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->gamma=1.000f/2.200f;
8453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->colorspace=YCCColorspace;
8463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (LocaleCompare(image_info->magick,"PCDS") == 0)
8473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image->colorspace=sRGBColorspace;
8483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(GetFirstImageInList(image));
8493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
8503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
8523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e g i s t e r P C D I m a g e                                           %
8573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  RegisterPCDImage() adds attributes for the PCD image format to
8633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  the list of supported formats.  The attributes include the image format
8643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  tag, a method to read and/or write the format, whether the format
8653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  supports the saving of more than one frame to the same file or blob,
8663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  whether the format supports native in-memory I/O, and a brief
8673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  description of the format.
8683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the RegisterPCDImage method is:
8703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      unsigned long RegisterPCDImage(void)
8723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
8743ed852eea50f9d4cd633efb8c2b054b8e33c253cristyModuleExport unsigned long RegisterPCDImage(void)
8753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
8763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickInfo
8773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *entry;
8783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry=SetMagickInfo("PCD");
8803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadPCDImage;
8813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WritePCDImage;
8823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->magick=(IsImageFormatHandler *) IsPCD;
8833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->adjoin=MagickFalse;
8843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->description=ConstantString("Photo CD");
8853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->module=ConstantString("PCD");
8863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
8873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry=SetMagickInfo("PCDS");
8883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadPCDImage;
8893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WritePCDImage;
8903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->adjoin=MagickFalse;
8913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->description=ConstantString("Photo CD");
8923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->module=ConstantString("PCD");
8933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
8943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickImageCoderSignature);
8953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
8963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
8983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   U n r e g i s t e r P C D I m a g e                                       %
9033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  UnregisterPCDImage() removes format registrations made by the
9093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  PCD module from the list of supported formats.
9103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the UnregisterPCDImage method is:
9123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      UnregisterPCDImage(void)
9143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
9163ed852eea50f9d4cd633efb8c2b054b8e33c253cristyModuleExport void UnregisterPCDImage(void)
9173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
9183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("PCD");
9193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("PCDS");
9203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
9213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
9233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   W r i t e P C D I m a g e                                                 %
9283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  WritePCDImage() writes an image in the Photo CD encoded image format.
9343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the WritePCDImage method is:
9363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType WritePCDImage(const ImageInfo *image_info,Image *image)
9383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows.
9403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
9423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image:  The image.
9443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
9463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9473ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType WritePCDTile(Image *image,const char *page_geometry,
9483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const char *tile_geometry)
9493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
9503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  GeometryInfo
9513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry_info;
9523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
9543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *downsample_image,
9553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *tile_image;
9563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  long
9583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    y;
9593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
9613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
9623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickStatusType
9643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    flags;
9653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  RectangleInfo
9673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry;
9683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register const PixelPacket
9703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p,
9713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
9723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register long
9743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
9753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x;
9763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
9783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Scale image to tile size.
9793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
9803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  SetGeometry(image,&geometry);
9813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ParseMetaGeometry(page_geometry,&geometry.x,&geometry.y,
9823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    &geometry.width,&geometry.height);
9833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((geometry.width % 2) != 0)
9843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry.width--;
9853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((geometry.height % 2) != 0)
9863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry.height--;
9873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  tile_image=ResizeImage(image,geometry.width,geometry.height,TriangleFilter,
9883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    1.0,&image->exception);
9893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (tile_image == (Image *) NULL)
9903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
9913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  flags=ParseGeometry(page_geometry,&geometry_info);
9923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  geometry.width=(unsigned long) geometry_info.rho;
9933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  geometry.height=(unsigned long) geometry_info.sigma;
9943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((flags & SigmaValue) == 0)
9953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry.height=geometry.width;
9963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((tile_image->columns != geometry.width) ||
9973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (tile_image->rows != geometry.height))
9983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
9993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Image
10003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *bordered_image;
10013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      RectangleInfo
10033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        border_info;
10043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
10063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Put a border around the image.
10073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
10083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      border_info.width=(geometry.width-tile_image->columns+1) >> 1;
10093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      border_info.height=(geometry.height-tile_image->rows+1) >> 1;
10103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      bordered_image=BorderImage(tile_image,&border_info,&image->exception);
10113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (bordered_image == (Image *) NULL)
10123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        return(MagickFalse);
10133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      tile_image=DestroyImage(tile_image);
10143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      tile_image=bordered_image;
10153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
10163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) TransformImage(&tile_image,(char *) NULL,tile_geometry);
10173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->colorspace != RGBColorspace)
10183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) TransformImageColorspace(tile_image,YCCColorspace);
10193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  downsample_image=ResizeImage(tile_image,tile_image->columns/2,
10203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    tile_image->rows/2,TriangleFilter,1.0,&image->exception);
10213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (downsample_image == (Image *) NULL)
10223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
10233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
10243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Write tile to PCD file.
10253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
10263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (y=0; y < (long) tile_image->rows; y+=2)
10273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
10283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    p=GetVirtualPixels(tile_image,0,y,tile_image->columns,2,
10293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      &tile_image->exception);
10303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (p == (const PixelPacket *) NULL)
10313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
10323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for (x=0; x < (long) (tile_image->columns << 1); x++)
10333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
10343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) WriteBlobByte(image,ScaleQuantumToChar(p->red));
10353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      p++;
10363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
10373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q=GetVirtualPixels(downsample_image,0,y >> 1,downsample_image->columns,
10383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      1,&downsample_image->exception);
10393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (q == (const PixelPacket *) NULL)
10403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
10413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for (x=0; x < (long) downsample_image->columns; x++)
10423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
10433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) WriteBlobByte(image,ScaleQuantumToChar(q->green));
10443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q++;
10453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
10463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q=GetVirtualPixels(downsample_image,0,y >> 1,downsample_image->columns,
10473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      1,&downsample_image->exception);
10483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (q == (const PixelPacket *) NULL)
10493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
10503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for (x=0; x < (long) downsample_image->columns; x++)
10513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
10523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) WriteBlobByte(image,ScaleQuantumToChar(q->blue));
10533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q++;
10543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
10553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status=SetImageProgress(image,SaveImageTag,y,tile_image->rows);
10563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (status == MagickFalse)
10573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
10583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
10593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 0x800; i++)
10603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(image,'\0');
10613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  downsample_image=DestroyImage(downsample_image);
10623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  tile_image=DestroyImage(tile_image);
10633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
10643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
10653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10663ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType WritePCDImage(const ImageInfo *image_info,Image *image)
10673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
10683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
10693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *pcd_image;
10703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
10723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
10733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register long
10753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i;
10763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
10783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info->signature == MagickSignature);
10793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
10803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image->signature == MagickSignature);
10813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
10823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
10833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  pcd_image=image;
10843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->columns < image->rows)
10853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
10863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Image
10873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *rotate_image;
10883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
10903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Rotate portrait to landscape.
10913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
10923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      rotate_image=RotateImage(image,90.0,&image->exception);
10933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (rotate_image == (Image *) NULL)
10943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        return(MagickFalse);
10953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      pcd_image=rotate_image;
10963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
10973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
10983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open output image file.
10993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
11003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=OpenBlob(image_info,pcd_image,WriteBinaryBlobMode,&image->exception);
11013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
11023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(status);
11033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->colorspace != RGBColorspace)
11043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) TransformImageColorspace(pcd_image,RGBColorspace);
11053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
11063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Write PCD image header.
11073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
11083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 32; i++)
11093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,0xff);
11103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 4; i++)
11113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,0x0e);
11123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 8; i++)
11133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\0');
11143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 4; i++)
11153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,0x01);
11163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 4; i++)
11173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,0x05);
11183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 8; i++)
11193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\0');
11203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 4; i++)
11213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,0x0A);
11223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 36; i++)
11233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\0');
11243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 4; i++)
11253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,0x01);
11263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 1944; i++)
11273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\0');
11283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlob(pcd_image,7,(const unsigned char *) "PCD_IPI");
11293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobByte(pcd_image,0x06);
11303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 1530; i++)
11313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\0');
11323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->columns < image->rows)
11333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\1');
11343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
11353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\0');
11363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < (3*0x800-1539); i++)
11373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\0');
11383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
11393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Write PCD tiles.
11403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
11413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=WritePCDTile(pcd_image,"768x512>","192x128");
11423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=WritePCDTile(pcd_image,"768x512>","384x256");
11433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=WritePCDTile(pcd_image,"768x512>","768x512");
11443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(pcd_image);
11453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (pcd_image != image)
11463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pcd_image=DestroyImage(pcd_image);
11473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(status);
11483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1149