pcd.c revision ed2315769b26818ed9d0c1291dc0457f0d8da0a4
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%                                                                             %
207e41fe84a841d7b9d7b36b245b65e9dcb3314943cristy%  Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization      %
213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  dedicated to making software imaging solutions freely available.           %
223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  You may not use this file except in compliance with the License.  You may  %
243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  obtain a copy of the License at                                            %
253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    http://www.imagemagick.org/script/license.php                            %
273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Unless required by applicable law or agreed to in writing, software        %
293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  distributed under the License is distributed on an "AS IS" BASIS,          %
303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  See the License for the specific language governing permissions and        %
323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  limitations under the License.                                             %
333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Include declarations.
413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
424c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/studio.h"
434c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/property.h"
444c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/blob.h"
454c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/blob-private.h"
464c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/cache.h"
474c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/client.h"
484c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/colorspace.h"
49510d06a3f7063e91993e13d546d5685048248074cristy#include "MagickCore/colorspace-private.h"
504c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/constitute.h"
514c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/decorate.h"
524c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception.h"
534c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception-private.h"
544c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/gem.h"
554c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/geometry.h"
564c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image.h"
574c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image-private.h"
584c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/list.h"
594c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/magick.h"
604c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/memory_.h"
614c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/monitor.h"
624c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/monitor-private.h"
634c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/montage.h"
644c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/pixel-accessor.h"
654c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/resize.h"
664c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/shear.h"
674c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/quantum-private.h"
684c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/static.h"
694c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/string_.h"
704c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/module.h"
714c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/transform.h"
724c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/utility.h"
733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Forward declarations.
763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
773ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType
783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  WritePCDImage(const ImageInfo *,Image *);
793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   D e c o d e I m a g e                                                     %
863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  DecodeImage recovers the Huffman encoded luminance and chrominance
923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  deltas.
933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the DecodeImage method is:
953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType DecodeImage(Image *image,unsigned char *luma,
973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        unsigned char *chroma1,unsigned char *chroma2)
983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
1003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image: the address of a structure of type Image.
1023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o luma: the address of a character buffer that contains the
1043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      luminance information.
1053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o chroma1: the address of a character buffer that contains the
1073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      chrominance information.
1083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o chroma2: the address of a character buffer that contains the
1103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      chrominance information.
1113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
1133ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType DecodeImage(Image *image,unsigned char *luma,
1143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned char *chroma1,unsigned char *chroma2)
1153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
1163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define IsSync  ((sum & 0xffffff00UL) == 0xfffffe00UL)
1173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define PCDGetBits(n) \
1183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{  \
1193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  sum=(sum << n) & 0xffffffff; \
1203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  bits-=n; \
1213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  while (bits <= 24) \
1223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  { \
1233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (p >= (buffer+0x800)) \
1243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      { \
1253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        count=ReadBlob(image,0x800,buffer); \
1263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        p=buffer; \
1273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      } \
1283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sum|=((unsigned int) (*p) << (24-bits)); \
1293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    bits+=8; \
1303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    p++; \
1313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  } \
1323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (EOFBlob(image) != MagickFalse) \
1333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    break; \
1343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  typedef struct PCDTable
1373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
1383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    unsigned int
1393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      length,
1403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      sequence;
1413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    MagickStatusType
1433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mask;
1443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    unsigned char
1463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      key;
1473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  } PCDTable;
1483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  PCDTable
1503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *pcd_table[3];
1513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
152bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
1533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
1543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    j;
1553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register PCDTable
1573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *r;
1583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register unsigned char
1603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p,
1613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
1623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  size_t
1643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    bits,
165aff6d807f839a998fff6e87198f2418868ab508ecristy    length,
1663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    plane,
1673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pcd_length[3],
1683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    row,
1693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sum;
1703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
171aff6d807f839a998fff6e87198f2418868ab508ecristy  ssize_t
172aff6d807f839a998fff6e87198f2418868ab508ecristy    count,
173aff6d807f839a998fff6e87198f2418868ab508ecristy    quantum;
174aff6d807f839a998fff6e87198f2418868ab508ecristy
175aff6d807f839a998fff6e87198f2418868ab508ecristy  unsigned char
176aff6d807f839a998fff6e87198f2418868ab508ecristy    *buffer;
177aff6d807f839a998fff6e87198f2418868ab508ecristy
1783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
1793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Initialize Huffman tables.
1803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
1813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (const Image *) NULL);
1823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image->signature == MagickSignature);
1833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
1843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(luma != (unsigned char *) NULL);
1863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(chroma1 != (unsigned char *) NULL);
1873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(chroma2 != (unsigned char *) NULL);
1883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  buffer=(unsigned char *) AcquireQuantumMemory(0x800,sizeof(*buffer));
1893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (buffer == (unsigned char *) NULL)
1903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->filename);
1923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  sum=0;
1933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  bits=32;
1943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  p=buffer+0x800;
1953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < (image->columns > 1536 ? 3 : 1); i++)
1963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
1973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PCDGetBits(8);
1983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    length=(sum & 0xff)+1;
1993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pcd_table[i]=(PCDTable *) AcquireQuantumMemory(length,
2003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      sizeof(*pcd_table[i]));
2013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (pcd_table[i] == (PCDTable *) NULL)
2023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
2033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->filename);
2063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
2073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    r=pcd_table[i];
208bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (j=0; j < (ssize_t) length; j++)
2093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
2103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      PCDGetBits(8);
2113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r->length=(unsigned int) (sum & 0xff)+1;
2123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (r->length > 16)
2133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
2143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          return(MagickFalse);
2163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
2173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      PCDGetBits(16);
2183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r->sequence=(unsigned int) (sum & 0xffff) << 16;
2193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      PCDGetBits(8);
2203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r->key=(unsigned char) (sum & 0xff);
2213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r->mask=(~((1U << (32-r->length))-1));
2223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r++;
2233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
224bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    pcd_length[i]=(size_t) length;
2253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
2263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
2273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Search for Sync byte.
2283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
2293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 1; i++)
2303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PCDGetBits(16);
2313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 1; i++)
2323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PCDGetBits(16);
2333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  while ((sum & 0x00fff000UL) != 0x00fff000UL)
2343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PCDGetBits(8);
2353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  while (IsSync == 0)
2363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PCDGetBits(1);
2373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
2383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Recover the Huffman encoded luminance and chrominance deltas.
2393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
2403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  count=0;
2413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  length=0;
2423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  plane=0;
2433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  row=0;
2443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  q=luma;
2453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for ( ; ; )
2463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
2473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (IsSync != 0)
2483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
2493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
2503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Determine plane and row number.
2513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
2523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        PCDGetBits(16);
2533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        row=((sum >> 9) & 0x1fff);
2543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (row == image->rows)
2553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
2563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        PCDGetBits(8);
2573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        plane=sum >> 30;
2583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        PCDGetBits(16);
2593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        switch (plane)
2603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
2613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 0:
2623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
2633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q=luma+row*image->columns;
2643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            count=(ssize_t) image->columns;
2653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
2663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
2673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 2:
2683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
2693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q=chroma1+(row >> 1)*image->columns;
2703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            count=(ssize_t) (image->columns >> 1);
2713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            plane--;
2723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
2733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
2743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 3:
2753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
2763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q=chroma2+(row >> 1)*image->columns;
2773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            count=(ssize_t) (image->columns >> 1);
2783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            plane--;
2793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
2803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
2813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          default:
2823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
2833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            ThrowBinaryException(CorruptImageError,"CorruptImage",
2843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              image->filename);
2853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
2863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
2873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        length=pcd_length[plane];
2883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
2893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
2903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
2913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Decode luminance or chrominance deltas.
2923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
2933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    r=pcd_table[plane];
294bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (i=0; ((i < (ssize_t) length) && ((sum & r->mask) != r->sequence)); i++)
2953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r++;
2965d41880f52dcb79d3681d0841cb8882ee614a8f0cristy    if ((row > image->rows) || (r == (PCDTable *) NULL))
2973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
2983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) ThrowMagickException(&image->exception,GetMagickModule(),
2993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          CorruptImageWarning,"SkipToSyncByte","`%s'",image->filename);
3003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        while ((sum & 0x00fff000) != 0x00fff000)
3013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PCDGetBits(8);
3023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        while (IsSync == 0)
3033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PCDGetBits(1);
3043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
3053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
3063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (r->key < 128)
307bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      quantum=(ssize_t) (*q)+r->key;
3083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
309bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      quantum=(ssize_t) (*q)+r->key-256;
3103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q=(unsigned char) ((quantum < 0) ? 0 : (quantum > 255) ? 255 : quantum);
3113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q++;
3123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PCDGetBits(r->length);
3133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count--;
3143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
3153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
3163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Relinquish resources.
3173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
3183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < (image->columns > 1536 ? 3 : 1); i++)
3193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pcd_table[i]=(PCDTable *) RelinquishMagickMemory(pcd_table[i]);
3203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  buffer=(unsigned char *) RelinquishMagickMemory(buffer);
3213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
3223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
3253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   I s P C D                                                                 %
3303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  IsPCD() returns MagickTrue if the image format type, identified by the
3363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  magick string, is PCD.
3373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the IsPCD method is:
3393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType IsPCD(const unsigned char *magick,const size_t length)
3413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
3433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o magick: compare image format pattern against these bytes.
3453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o length: Specifies the length of the magick string.
3473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
3493ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType IsPCD(const unsigned char *magick,const size_t length)
3503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
3513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (length < 2052)
3523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
3533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (LocaleNCompare((const char *) magick+2048,"PCD_",4) == 0)
3543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickTrue);
3553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickFalse);
3563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
3593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e a d P C D I m a g e                                                   %
3643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ReadPCDImage() reads a Photo CD image file and returns it.  It
3703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  allocates the memory necessary for the new Image structure and returns a
3713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  pointer to the new image.  Much of the PCD decoder was derived from
3723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  the program hpcdtoppm(1) by Hadmut Danisch.
3733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the ReadPCDImage method is:
3753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      image=ReadPCDImage(image_info)
3773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
3793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
3813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o exception: return any errors or warnings in this structure.
3833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
3853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3863ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic inline size_t MagickMin(const size_t x,const size_t y)
3873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
3883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (x < y)
3893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(x);
3903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(y);
3913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3933ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic Image *OverviewImage(const ImageInfo *image_info,Image *image,
3943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ExceptionInfo *exception)
3953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
3963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
3973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *montage_image;
3983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MontageInfo
4003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *montage_info;
4013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register Image
4033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
4043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
4063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Create the PCD Overview image.
4073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
4083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (p=image; p != (Image *) NULL; p=p->next)
4093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
4103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) DeleteImageProperty(p,"label");
4113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) SetImageProperty(p,"label",DefaultTileLabel);
4123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
4133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  montage_info=CloneMontageInfo(image_info,(MontageInfo *) NULL);
4143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CopyMagickString(montage_info->filename,image_info->filename,
4153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    MaxTextExtent);
4163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  montage_image=MontageImageList(image_info,montage_info,image,exception);
4173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  montage_info=DestroyMontageInfo(montage_info);
4183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (montage_image == (Image *) NULL)
4193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
4203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image=DestroyImage(image);
4213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(montage_image);
4223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
4233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
424bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristystatic void Upsample(const size_t width,const size_t height,
425bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  const size_t scaled_width,unsigned char *pixels)
4263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
427bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
4283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x,
4293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    y;
4303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register unsigned char
4323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p,
4333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q,
4343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *r;
4353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
4373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Create a new image that is a integral size greater than an existing one.
4383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
4393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(pixels != (unsigned char *) NULL);
440bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) height; y++)
4413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
4423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    p=pixels+(height-1-y)*scaled_width+(width-1);
4433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q=pixels+((height-1-y) << 1)*scaled_width+((width-1) << 1);
4443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q=(*p);
4453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *(q+1)=(*(p));
446bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=1; x < (ssize_t) width; x++)
4473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
4483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      p--;
4493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q-=2;
4503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *q=(*p);
451aff6d807f839a998fff6e87198f2418868ab508ecristy      *(q+1)=(unsigned char) ((((size_t) *p)+((size_t) *(p+1))+1) >> 1);
4523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
4533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
454bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) (height-1); y++)
4553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
456bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    p=pixels+((size_t) y << 1)*scaled_width;
4573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q=p+scaled_width;
4583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    r=q+scaled_width;
459bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) (width-1); x++)
4603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
461bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      *q=(unsigned char) ((((size_t) *p)+((size_t) *r)+1) >> 1);
462bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      *(q+1)=(unsigned char) ((((size_t) *p)+((size_t) *(p+2))+
463bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        ((size_t) *r)+((size_t) *(r+2))+2) >> 2);
4643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q+=2;
4653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      p+=2;
4663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r+=2;
4673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
468aff6d807f839a998fff6e87198f2418868ab508ecristy    *q++=(unsigned char) ((((size_t) *p++)+((size_t) *r++)+1) >> 1);
469aff6d807f839a998fff6e87198f2418868ab508ecristy    *q++=(unsigned char) ((((size_t) *p++)+((size_t) *r++)+1) >> 1);
4703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
4713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  p=pixels+(2*height-2)*scaled_width;
4723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  q=pixels+(2*height-1)*scaled_width;
4733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CopyMagickMemory(q,p,(size_t) (2*width));
4743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
4753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4763ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic Image *ReadPCDImage(const ImageInfo *image_info,ExceptionInfo *exception)
4773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
4783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
4793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *image;
4803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
4823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
4833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickOffsetType
4853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    offset;
4863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickSizeType
4883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    number_pixels;
4893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
490bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
4913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
4923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    y;
4933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4944c08aed51c5899665ade97263692328eea4af106cristy  register Quantum
4953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
4963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register unsigned char
4983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *c1,
4993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *c2,
5003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *yy;
5013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
502aff6d807f839a998fff6e87198f2418868ab508ecristy  size_t
503aff6d807f839a998fff6e87198f2418868ab508ecristy    height,
504aff6d807f839a998fff6e87198f2418868ab508ecristy    number_images,
505aff6d807f839a998fff6e87198f2418868ab508ecristy    rotate,
506aff6d807f839a998fff6e87198f2418868ab508ecristy    scene,
507aff6d807f839a998fff6e87198f2418868ab508ecristy    width;
508aff6d807f839a998fff6e87198f2418868ab508ecristy
5093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ssize_t
510aff6d807f839a998fff6e87198f2418868ab508ecristy    count,
511aff6d807f839a998fff6e87198f2418868ab508ecristy    x;
5123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned char
5143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *chroma1,
5153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *chroma2,
5163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *header,
5173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *luma;
5183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned int
5203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    overview;
5213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
5233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open image file.
5243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
5253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
5263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info->signature == MagickSignature);
5273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->debug != MagickFalse)
5283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
5293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image_info->filename);
5303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception != (ExceptionInfo *) NULL);
5313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception->signature == MagickSignature);
5323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image=AcquireImage(image_info);
5333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
5343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
5353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
5363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image=DestroyImageList(image);
5373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return((Image *) NULL);
5383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
5393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
5403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Determine if this a PCD file.
5413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
5423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  header=(unsigned char *) AcquireQuantumMemory(0x800,3UL*sizeof(*header));
5433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (header == (unsigned char *) NULL)
5443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
5453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  count=ReadBlob(image,3*0x800,header);
5463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  overview=LocaleNCompare((char *) header,"PCD_OPA",7) == 0;
5473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((count == 0) ||
5483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ((LocaleNCompare((char *) header+0x800,"PCD",3) != 0) && !overview))
5493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
5503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  rotate=header[0x0e02] & 0x03;
5513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  number_images=(header[10] << 8) | header[11];
5523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  header=(unsigned char *) RelinquishMagickMemory(header);
5533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
5543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Determine resolution by scene specification.
5553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
5563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((image->columns == 0) || (image->rows == 0))
5573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    scene=3;
5583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
5593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
5603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      width=192;
5613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      height=128;
5623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (scene=1; scene < 6; scene++)
5633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
5643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if ((width >= image->columns) && (height >= image->rows))
5653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
5663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        width<<=1;
5673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        height<<=1;
5683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
5693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
5703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->number_scenes != 0)
571bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    scene=(size_t) MagickMin(image_info->scene,6);
5723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (overview)
5733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    scene=1;
5743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
5753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Initialize image structure.
5763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
5773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  width=192;
5783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  height=128;
579bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (i=1; i < (ssize_t) MagickMin(scene,3); i++)
5803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
5813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    width<<=1;
5823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    height<<=1;
5833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
5843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->columns=width;
5853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->rows=height;
5863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->depth=8;
587bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for ( ; i < (ssize_t) scene; i++)
5883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
5893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image->columns<<=1;
5903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image->rows<<=1;
5913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
5923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
5935d41880f52dcb79d3681d0841cb8882ee614a8f0cristy    Allocate luma and chroma memory.
5943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
5953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  number_pixels=(MagickSizeType) image->columns*image->rows;
5963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (number_pixels != (size_t) number_pixels)
5973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
5983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chroma1=(unsigned char *) AcquireQuantumMemory(image->columns+1UL,image->rows*
5993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sizeof(*chroma1));
6003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chroma2=(unsigned char *) AcquireQuantumMemory(image->columns+1UL,image->rows*
6013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sizeof(*chroma2));
6023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  luma=(unsigned char *) AcquireQuantumMemory(image->columns+1UL,image->rows*
6033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sizeof(*luma));
6043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((chroma1 == (unsigned char *) NULL) ||
6053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (chroma2 == (unsigned char *) NULL) || (luma == (unsigned char *) NULL))
6063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
6073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
6083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Advance to image data.
6093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
6103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  offset=93;
6113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (overview)
6123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    offset=2;
6133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
6143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (scene == 2)
6153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      offset=20;
6163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
6173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (scene <= 1)
6183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset=1;
619bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (i=0; i < (ssize_t) (offset*0x800); i++)
6203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) ReadBlobByte(image);
6213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (overview)
6223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
6233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Image
6243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *overview_image;
6253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      MagickProgressMonitor
6273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        progress_monitor;
6283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
629bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      register ssize_t
6303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        j;
6313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
6333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Read thumbnails from overview image.
6343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
635bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      for (j=1; j <= (ssize_t) number_images; j++)
6363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
6373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        progress_monitor=SetImageProgressMonitor(image,
6383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (MagickProgressMonitor) NULL,image->client_data);
639b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy        (void) FormatLocaleString(image->filename,MaxTextExtent,
640f2faecf9facdbbb14fcba373365f9f691a9658e0cristy          "images/img%04ld.pcd",(long) j);
641b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy        (void) FormatLocaleString(image->magick_filename,MaxTextExtent,
642f2faecf9facdbbb14fcba373365f9f691a9658e0cristy          "images/img%04ld.pcd",(long) j);
643bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        image->scene=(size_t) j;
6443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->columns=width;
6453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->rows=height;
6463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->depth=8;
6473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        yy=luma;
6483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        c1=chroma1;
6493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        c2=chroma2;
650bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        for (y=0; y < (ssize_t) height; y+=2)
6513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
6523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          count=ReadBlob(image,width,yy);
6533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          yy+=image->columns;
6543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          count=ReadBlob(image,width,yy);
6553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          yy+=image->columns;
6563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          count=ReadBlob(image,width >> 1,c1);
6573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          c1+=image->columns;
6583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          count=ReadBlob(image,width >> 1,c2);
6593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          c2+=image->columns;
6603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
6613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Upsample(image->columns >> 1,image->rows >> 1,image->columns,chroma1);
6623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Upsample(image->columns >> 1,image->rows >> 1,image->columns,chroma2);
6633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
6643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Transfer luminance and chrominance channels.
6653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
6663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        yy=luma;
6673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        c1=chroma1;
6683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        c2=chroma2;
669bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        for (y=0; y < (ssize_t) image->rows; y++)
6703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
6713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
6724c08aed51c5899665ade97263692328eea4af106cristy          if (q == (const Quantum *) NULL)
6733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
674bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy          for (x=0; x < (ssize_t) image->columns; x++)
6753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
6764c08aed51c5899665ade97263692328eea4af106cristy            SetPixelRed(image,ScaleCharToQuantum(*yy++),q);
6774c08aed51c5899665ade97263692328eea4af106cristy            SetPixelGreen(image,ScaleCharToQuantum(*c1++),q);
6784c08aed51c5899665ade97263692328eea4af106cristy            SetPixelBlue(image,ScaleCharToQuantum(*c2++),q);
679ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy            q+=GetPixelChannels(image);
6803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
6813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (SyncAuthenticPixels(image,exception) == MagickFalse)
6823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
6833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
6843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->colorspace=YCCColorspace;
6853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (LocaleCompare(image_info->magick,"PCDS") == 0)
6863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->colorspace=sRGBColorspace;
687bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        if (j < (ssize_t) number_images)
6883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
6893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
6903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Allocate next image structure.
6913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
6923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            AcquireNextImage(image_info,image);
6933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (GetNextImageInList(image) == (Image *) NULL)
6943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
6953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image=DestroyImageList(image);
6963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                return((Image *) NULL);
6973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
6983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image=SyncNextImageInList(image);
6993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
7003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) SetImageProgressMonitor(image,progress_monitor,
7013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->client_data);
7023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (image->previous == (Image *) NULL)
7033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
7043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            status=SetImageProgress(image,LoadImageTag,j-1,number_images);
7053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (status == MagickFalse)
7063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              break;
7073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
7083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
7093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      chroma2=(unsigned char *) RelinquishMagickMemory(chroma2);
7103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      chroma1=(unsigned char *) RelinquishMagickMemory(chroma1);
7113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      luma=(unsigned char *) RelinquishMagickMemory(luma);
7123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image=GetFirstImageInList(image);
7133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      overview_image=OverviewImage(image_info,image,exception);
7143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return(overview_image);
7153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
7173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Read interleaved image.
7183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
7193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  yy=luma;
7203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  c1=chroma1;
7213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  c2=chroma2;
722bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) height; y+=2)
7233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
7243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count=ReadBlob(image,width,yy);
7253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    yy+=image->columns;
7263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count=ReadBlob(image,width,yy);
7273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    yy+=image->columns;
7283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count=ReadBlob(image,width >> 1,c1);
7293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    c1+=image->columns;
7303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count=ReadBlob(image,width >> 1,c2);
7313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    c2+=image->columns;
7323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
7333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (scene >= 4)
7343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
7353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
7363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Recover luminance deltas for 1536x1024 image.
7373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
7383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Upsample(768,512,image->columns,luma);
7393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Upsample(384,256,image->columns,chroma1);
7403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Upsample(384,256,image->columns,chroma2);
7413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->rows=1024;
7423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (i=0; i < (4*0x800); i++)
7433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) ReadBlobByte(image);
7443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      status=DecodeImage(image,luma,chroma1,chroma2);
7453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((scene >= 5) && status)
7463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
7473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /*
7483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            Recover luminance deltas for 3072x2048 image.
7493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          */
7503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Upsample(1536,1024,image->columns,luma);
7513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Upsample(768,512,image->columns,chroma1);
7523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Upsample(768,512,image->columns,chroma2);
7533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->rows=2048;
7543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          offset=TellBlob(image)/0x800+12;
7553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          offset=SeekBlob(image,offset*0x800,SEEK_SET);
7563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          status=DecodeImage(image,luma,chroma1,chroma2);
7573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if ((scene >= 6) && (status != MagickFalse))
7583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
7593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              /*
7603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                Recover luminance deltas for 6144x4096 image (vaporware).
7613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              */
7623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Upsample(3072,2048,image->columns,luma);
7633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Upsample(1536,1024,image->columns,chroma1);
7643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Upsample(1536,1024,image->columns,chroma2);
7653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              image->rows=4096;
7663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
7673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
7683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Upsample(image->columns >> 1,image->rows >> 1,image->columns,chroma1);
7703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Upsample(image->columns >> 1,image->rows >> 1,image->columns,chroma2);
7713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
7723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Transfer luminance and chrominance channels.
7733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
7743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  yy=luma;
7753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  c1=chroma1;
7763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  c2=chroma2;
777bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) image->rows; y++)
7783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
7793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
7804c08aed51c5899665ade97263692328eea4af106cristy    if (q == (const Quantum *) NULL)
7813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
782bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) image->columns; x++)
7833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
7844c08aed51c5899665ade97263692328eea4af106cristy      SetPixelRed(image,ScaleCharToQuantum(*yy++),q);
7854c08aed51c5899665ade97263692328eea4af106cristy      SetPixelGreen(image,ScaleCharToQuantum(*c1++),q);
7864c08aed51c5899665ade97263692328eea4af106cristy      SetPixelBlue(image,ScaleCharToQuantum(*c2++),q);
787ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy      q+=GetPixelChannels(image);
7883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (SyncAuthenticPixels(image,exception) == MagickFalse)
7903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
7913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (image->previous == (Image *) NULL)
7923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
793cee9711bbc334b5677d5ec4ea1cc70340d35ee35cristy        status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
794cee9711bbc334b5677d5ec4ea1cc70340d35ee35cristy                image->rows);
7953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (status == MagickFalse)
7963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
7973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
7983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
7993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chroma2=(unsigned char *) RelinquishMagickMemory(chroma2);
8003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chroma1=(unsigned char *) RelinquishMagickMemory(chroma1);
8013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  luma=(unsigned char *) RelinquishMagickMemory(luma);
8023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (EOFBlob(image) != MagickFalse)
8033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
8043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->filename);
8053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(image);
8063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->ping == MagickFalse)
8073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if ((rotate == 1) || (rotate == 3))
8083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
8093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        double
8103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          degrees;
8113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Image
8133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          *rotate_image;
8143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
8163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Rotate image.
8173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
8183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        degrees=rotate == 1 ? -90.0 : 90.0;
8193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        rotate_image=RotateImage(image,degrees,exception);
8203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (rotate_image != (Image *) NULL)
8213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
8223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image=DestroyImage(image);
8233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image=rotate_image;
8243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
8253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
8263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
8273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Set CCIR 709 primaries with a D65 white point.
8283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
8293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.red_primary.x=0.6400f;
8303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.red_primary.y=0.3300f;
8313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.green_primary.x=0.3000f;
8323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.green_primary.y=0.6000f;
8333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.blue_primary.x=0.1500f;
8343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.blue_primary.y=0.0600f;
8353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.white_point.x=0.3127f;
8363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.white_point.y=0.3290f;
8373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->gamma=1.000f/2.200f;
8383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->colorspace=YCCColorspace;
8393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (LocaleCompare(image_info->magick,"PCDS") == 0)
8403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image->colorspace=sRGBColorspace;
8413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(GetFirstImageInList(image));
8423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
8433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
8453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e g i s t e r P C D I m a g e                                           %
8503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  RegisterPCDImage() adds attributes for the PCD image format to
8563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  the list of supported formats.  The attributes include the image format
8573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  tag, a method to read and/or write the format, whether the format
8583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  supports the saving of more than one frame to the same file or blob,
8593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  whether the format supports native in-memory I/O, and a brief
8603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  description of the format.
8613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the RegisterPCDImage method is:
8633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
864bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy%      size_t RegisterPCDImage(void)
8653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
867bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristyModuleExport size_t RegisterPCDImage(void)
8683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
8693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickInfo
8703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *entry;
8713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry=SetMagickInfo("PCD");
8733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadPCDImage;
8743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WritePCDImage;
8753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->magick=(IsImageFormatHandler *) IsPCD;
8763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->adjoin=MagickFalse;
877ffaf9781fa632998c711fd43f305a737df94b50ccristy  entry->seekable_stream=MagickTrue;
8783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->description=ConstantString("Photo CD");
8793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->module=ConstantString("PCD");
8803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
8813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry=SetMagickInfo("PCDS");
8823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadPCDImage;
8833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WritePCDImage;
8843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->adjoin=MagickFalse;
885ffaf9781fa632998c711fd43f305a737df94b50ccristy  entry->seekable_stream=MagickTrue;
8863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->description=ConstantString("Photo CD");
8873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->module=ConstantString("PCD");
8883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
8893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickImageCoderSignature);
8903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
8913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
8933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   U n r e g i s t e r P C D I m a g e                                       %
8983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  UnregisterPCDImage() removes format registrations made by the
9043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  PCD module from the list of supported formats.
9053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the UnregisterPCDImage method is:
9073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      UnregisterPCDImage(void)
9093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
9113ed852eea50f9d4cd633efb8c2b054b8e33c253cristyModuleExport void UnregisterPCDImage(void)
9123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
9133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("PCD");
9143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("PCDS");
9153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
9163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
9183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   W r i t e P C D I m a g e                                                 %
9233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  WritePCDImage() writes an image in the Photo CD encoded image format.
9293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the WritePCDImage method is:
9313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType WritePCDImage(const ImageInfo *image_info,Image *image)
9333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows.
9353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
9373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image:  The image.
9393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
9413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9423ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType WritePCDTile(Image *image,const char *page_geometry,
9433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const char *tile_geometry)
9443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
9453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  GeometryInfo
9463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry_info;
9473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
9493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *downsample_image,
9503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *tile_image;
9513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
9533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
9543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickStatusType
9563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    flags;
9573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  RectangleInfo
9593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry;
9603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9614c08aed51c5899665ade97263692328eea4af106cristy  register const Quantum
9623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p,
9633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
9643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
965bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
9663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
9673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x;
9683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
969aff6d807f839a998fff6e87198f2418868ab508ecristy  ssize_t
970aff6d807f839a998fff6e87198f2418868ab508ecristy    y;
971aff6d807f839a998fff6e87198f2418868ab508ecristy
9723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
9733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Scale image to tile size.
9743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
9753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  SetGeometry(image,&geometry);
9763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ParseMetaGeometry(page_geometry,&geometry.x,&geometry.y,
9773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    &geometry.width,&geometry.height);
9783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((geometry.width % 2) != 0)
9793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry.width--;
9803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((geometry.height % 2) != 0)
9813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry.height--;
9823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  tile_image=ResizeImage(image,geometry.width,geometry.height,TriangleFilter,
9833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    1.0,&image->exception);
9843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (tile_image == (Image *) NULL)
9853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
9863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  flags=ParseGeometry(page_geometry,&geometry_info);
987bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  geometry.width=(size_t) geometry_info.rho;
988bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  geometry.height=(size_t) geometry_info.sigma;
9893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((flags & SigmaValue) == 0)
9903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry.height=geometry.width;
9913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((tile_image->columns != geometry.width) ||
9923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (tile_image->rows != geometry.height))
9933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
9943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Image
9953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *bordered_image;
9963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      RectangleInfo
9983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        border_info;
9993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
10013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Put a border around the image.
10023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
10033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      border_info.width=(geometry.width-tile_image->columns+1) >> 1;
10043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      border_info.height=(geometry.height-tile_image->rows+1) >> 1;
10053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      bordered_image=BorderImage(tile_image,&border_info,&image->exception);
10063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (bordered_image == (Image *) NULL)
10073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        return(MagickFalse);
10083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      tile_image=DestroyImage(tile_image);
10093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      tile_image=bordered_image;
10103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
10113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) TransformImage(&tile_image,(char *) NULL,tile_geometry);
1012510d06a3f7063e91993e13d546d5685048248074cristy  if (IsRGBColorspace(image->colorspace) == MagickFalse)
10133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) TransformImageColorspace(tile_image,YCCColorspace);
10143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  downsample_image=ResizeImage(tile_image,tile_image->columns/2,
10153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    tile_image->rows/2,TriangleFilter,1.0,&image->exception);
10163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (downsample_image == (Image *) NULL)
10173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
10183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
10193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Write tile to PCD file.
10203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
1021bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) tile_image->rows; y+=2)
10223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
10233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    p=GetVirtualPixels(tile_image,0,y,tile_image->columns,2,
10243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      &tile_image->exception);
10254c08aed51c5899665ade97263692328eea4af106cristy    if (p == (const Quantum *) NULL)
10263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
1027bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) (tile_image->columns << 1); x++)
10283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
10294c08aed51c5899665ade97263692328eea4af106cristy      (void) WriteBlobByte(image,ScaleQuantumToChar(GetPixelRed(tile_image,p)));
1030ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy      p+=GetPixelChannels(tile_image);
10313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
10323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q=GetVirtualPixels(downsample_image,0,y >> 1,downsample_image->columns,
10333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      1,&downsample_image->exception);
10344c08aed51c5899665ade97263692328eea4af106cristy    if (q == (const Quantum *) NULL)
10353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
1036bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) downsample_image->columns; x++)
10373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
10384c08aed51c5899665ade97263692328eea4af106cristy      (void) WriteBlobByte(image,ScaleQuantumToChar(
10394c08aed51c5899665ade97263692328eea4af106cristy        GetPixelGreen(tile_image,q)));
10403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q++;
10413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
10423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q=GetVirtualPixels(downsample_image,0,y >> 1,downsample_image->columns,
10433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      1,&downsample_image->exception);
10444c08aed51c5899665ade97263692328eea4af106cristy    if (q == (const Quantum *) NULL)
10453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
1046bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) downsample_image->columns; x++)
10473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
10484c08aed51c5899665ade97263692328eea4af106cristy      (void) WriteBlobByte(image,ScaleQuantumToChar(
10494c08aed51c5899665ade97263692328eea4af106cristy        GetPixelBlue(tile_image,q)));
10503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q++;
10513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
10523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status=SetImageProgress(image,SaveImageTag,y,tile_image->rows);
10533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (status == MagickFalse)
10543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
10553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
10563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 0x800; i++)
10573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(image,'\0');
10583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  downsample_image=DestroyImage(downsample_image);
10593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  tile_image=DestroyImage(tile_image);
10603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
10613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
10623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10633ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType WritePCDImage(const ImageInfo *image_info,Image *image)
10643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
10653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
10663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *pcd_image;
10673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
10693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
10703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1071bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
10723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i;
10733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
10753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info->signature == MagickSignature);
10763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
10773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image->signature == MagickSignature);
10783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
10793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
10803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  pcd_image=image;
10813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->columns < image->rows)
10823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
10833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Image
10843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *rotate_image;
10853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
10873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Rotate portrait to landscape.
10883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
10893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      rotate_image=RotateImage(image,90.0,&image->exception);
10903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (rotate_image == (Image *) NULL)
10913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        return(MagickFalse);
10923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      pcd_image=rotate_image;
10933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
10943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
10953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open output image file.
10963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
10973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=OpenBlob(image_info,pcd_image,WriteBinaryBlobMode,&image->exception);
10983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
10993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(status);
1100510d06a3f7063e91993e13d546d5685048248074cristy  if (IsRGBColorspace(image->colorspace) == MagickFalse)
11013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) TransformImageColorspace(pcd_image,RGBColorspace);
11023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
11033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Write PCD image header.
11043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
11053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 32; i++)
11063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,0xff);
11073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 4; i++)
11083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,0x0e);
11093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 8; i++)
11103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\0');
11113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 4; i++)
11123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,0x01);
11133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 4; i++)
11143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,0x05);
11153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 8; i++)
11163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\0');
11173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 4; i++)
11183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,0x0A);
11193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 36; i++)
11203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\0');
11213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 4; i++)
11223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,0x01);
11233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 1944; i++)
11243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\0');
11253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlob(pcd_image,7,(const unsigned char *) "PCD_IPI");
11263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobByte(pcd_image,0x06);
11273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 1530; i++)
11283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\0');
11293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->columns < image->rows)
11303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\1');
11313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
11323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\0');
11333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < (3*0x800-1539); i++)
11343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\0');
11353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
11363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Write PCD tiles.
11373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
11383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=WritePCDTile(pcd_image,"768x512>","192x128");
11393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=WritePCDTile(pcd_image,"768x512>","384x256");
11403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=WritePCDTile(pcd_image,"768x512>","768x512");
11413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(pcd_image);
11423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (pcd_image != image)
11433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pcd_image=DestroyImage(pcd_image);
11443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(status);
11453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1146