13ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
23ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
43ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
53ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
63ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                            PPPP    CCCC  DDDD                               %
73ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                            P   P  C      D   D                              %
83ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                            PPPP   C      D   D                              %
93ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                            P      C      D   D                              %
103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                            P       CCCC  DDDD                               %
113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                     Read/Write Photo CD Image Format                        %
143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                              Software Design                                %
16de984cdc3631106b1cbbb8d3972b76a0fc27e8e8cristy%                                   Cristy                                    %
173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                 July 1992                                   %
183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
207ce65e7125a4e1df1a274ce373c537a9df9c16cdCristy%  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  dedicated to making software imaging solutions freely available.           %
223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  You may not use this file except in compliance with the License.  You may  %
243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  obtain a copy of the License at                                            %
253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    http://www.imagemagick.org/script/license.php                            %
273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Unless required by applicable law or agreed to in writing, software        %
293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  distributed under the License is distributed on an "AS IS" BASIS,          %
303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  See the License for the specific language governing permissions and        %
323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  limitations under the License.                                             %
333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Include declarations.
413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
424c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/studio.h"
434c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/property.h"
444c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/blob.h"
454c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/blob-private.h"
464c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/cache.h"
474c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/client.h"
484c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/colorspace.h"
49510d06a3f7063e91993e13d546d5685048248074cristy#include "MagickCore/colorspace-private.h"
504c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/constitute.h"
514c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/decorate.h"
52c53413df5789700e14e1a67e6cc2716d1716a387cristy#include "MagickCore/distort.h"
534c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception.h"
544c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception-private.h"
554c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/gem.h"
564c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/geometry.h"
574c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image.h"
584c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image-private.h"
594c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/list.h"
604c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/magick.h"
614c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/memory_.h"
624c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/monitor.h"
634c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/monitor-private.h"
644c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/montage.h"
654c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/pixel-accessor.h"
664c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/resize.h"
674c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/quantum-private.h"
684c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/static.h"
694c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/string_.h"
704c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/module.h"
714c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/utility.h"
723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Forward declarations.
753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
763ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType
771e178e70fb3c956f9fc1e30c3ba863e882666465cristy  WritePCDImage(const ImageInfo *,Image *,ExceptionInfo *);
783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   D e c o d e I m a g e                                                     %
853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  DecodeImage recovers the Huffman encoded luminance and chrominance
913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  deltas.
923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the DecodeImage method is:
943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType DecodeImage(Image *image,unsigned char *luma,
963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        unsigned char *chroma1,unsigned char *chroma2)
973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image: the address of a structure of type Image.
1013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o luma: the address of a character buffer that contains the
1033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      luminance information.
1043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o chroma1: the address of a character buffer that contains the
1063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      chrominance information.
1073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o chroma2: the address of a character buffer that contains the
1093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      chrominance information.
1103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
1123ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType DecodeImage(Image *image,unsigned char *luma,
113018f07f7333b25743d0afff892450cebdb905c1acristy  unsigned char *chroma1,unsigned char *chroma2,ExceptionInfo *exception)
1143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
115c31f22eed93546cfdcc39b64cd2e7543e9f94e38cristy#define IsSync(sum)  ((sum & 0xffffff00UL) == 0xfffffe00UL)
1163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define PCDGetBits(n) \
1173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{  \
1183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  sum=(sum << n) & 0xffffffff; \
1193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  bits-=n; \
1203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  while (bits <= 24) \
1213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  { \
1223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (p >= (buffer+0x800)) \
1233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      { \
1243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        count=ReadBlob(image,0x800,buffer); \
1253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        p=buffer; \
1263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      } \
1273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sum|=((unsigned int) (*p) << (24-bits)); \
1283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    bits+=8; \
1293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    p++; \
1303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  } \
1313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  typedef struct PCDTable
1343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
1353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    unsigned int
1363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      length,
1373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      sequence;
1383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    MagickStatusType
1403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      mask;
1413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    unsigned char
1433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      key;
1443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  } PCDTable;
1453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  PCDTable
1473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *pcd_table[3];
1483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
149bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
1503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
1513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    j;
1523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register PCDTable
1543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *r;
1553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register unsigned char
1573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p,
1583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
1593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  size_t
1613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    bits,
162aff6d807f839a998fff6e87198f2418868ab508ecristy    length,
1633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    plane,
1643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pcd_length[3],
1653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    row,
1663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sum;
1673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
168aff6d807f839a998fff6e87198f2418868ab508ecristy  ssize_t
169aff6d807f839a998fff6e87198f2418868ab508ecristy    count,
170aff6d807f839a998fff6e87198f2418868ab508ecristy    quantum;
171aff6d807f839a998fff6e87198f2418868ab508ecristy
172aff6d807f839a998fff6e87198f2418868ab508ecristy  unsigned char
173aff6d807f839a998fff6e87198f2418868ab508ecristy    *buffer;
174aff6d807f839a998fff6e87198f2418868ab508ecristy
1753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
1763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Initialize Huffman tables.
1773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
1783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (const Image *) NULL);
179e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image->signature == MagickCoreSignature);
1803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
1813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(luma != (unsigned char *) NULL);
1833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(chroma1 != (unsigned char *) NULL);
1843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(chroma2 != (unsigned char *) NULL);
1853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  buffer=(unsigned char *) AcquireQuantumMemory(0x800,sizeof(*buffer));
1863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (buffer == (unsigned char *) NULL)
1873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->filename);
1893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  sum=0;
1903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  bits=32;
1913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  p=buffer+0x800;
19254ebd8d7629c2faa0c8fb0dc97967f31c759d2d2cristy  for (i=0; i < 3; i++)
193e47080a0c3fea8233d0ade908981b3c09cca422ecristy  {
19454ebd8d7629c2faa0c8fb0dc97967f31c759d2d2cristy    pcd_table[i]=(PCDTable *) NULL;
195f676ac57c8fce95324a5ef2ff94bf5687f892c72cristy    pcd_length[i]=0;
196e47080a0c3fea8233d0ade908981b3c09cca422ecristy  }
1973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < (image->columns > 1536 ? 3 : 1); i++)
1983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
1993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PCDGetBits(8);
2003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    length=(sum & 0xff)+1;
2013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pcd_table[i]=(PCDTable *) AcquireQuantumMemory(length,
2023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      sizeof(*pcd_table[i]));
2033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (pcd_table[i] == (PCDTable *) NULL)
2043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
2053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->filename);
2083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
2093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    r=pcd_table[i];
210bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (j=0; j < (ssize_t) length; j++)
2113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
2123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      PCDGetBits(8);
2133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r->length=(unsigned int) (sum & 0xff)+1;
2143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (r->length > 16)
2153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
2163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          return(MagickFalse);
2183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
2193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      PCDGetBits(16);
2203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r->sequence=(unsigned int) (sum & 0xffff) << 16;
2213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      PCDGetBits(8);
2223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r->key=(unsigned char) (sum & 0xff);
2233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r->mask=(~((1U << (32-r->length))-1));
2243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r++;
2253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
226bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    pcd_length[i]=(size_t) length;
2273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
2283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
2293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Search for Sync byte.
2303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
2313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 1; i++)
2323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PCDGetBits(16);
2333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 1; i++)
2343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PCDGetBits(16);
2353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  while ((sum & 0x00fff000UL) != 0x00fff000UL)
2363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PCDGetBits(8);
237c31f22eed93546cfdcc39b64cd2e7543e9f94e38cristy  while (IsSync(sum) == 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  {
249c31f22eed93546cfdcc39b64cd2e7543e9f94e38cristy    if (IsSync(sum) != 0)
2503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
2513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
2523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Determine plane and row number.
2533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
2543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        PCDGetBits(16);
2553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        row=((sum >> 9) & 0x1fff);
2563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (row == image->rows)
2573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
2583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        PCDGetBits(8);
2593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        plane=sum >> 30;
2603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        PCDGetBits(16);
2613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        switch (plane)
2623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
2633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 0:
2643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
2653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q=luma+row*image->columns;
2663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            count=(ssize_t) image->columns;
2673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
2683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
2693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 2:
2703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
2713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q=chroma1+(row >> 1)*image->columns;
2723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            count=(ssize_t) (image->columns >> 1);
2733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            plane--;
2743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
2753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
2763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          case 3:
2773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
2783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q=chroma2+(row >> 1)*image->columns;
2793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            count=(ssize_t) (image->columns >> 1);
2803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            plane--;
2813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
2823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
2833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          default:
2843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
2853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            ThrowBinaryException(CorruptImageError,"CorruptImage",
2863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              image->filename);
2873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
2883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
2893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        length=pcd_length[plane];
2903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
2913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
2923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
2933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Decode luminance or chrominance deltas.
2943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
2953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    r=pcd_table[plane];
296bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (i=0; ((i < (ssize_t) length) && ((sum & r->mask) != r->sequence)); i++)
2973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r++;
2985d41880f52dcb79d3681d0841cb8882ee614a8f0cristy    if ((row > image->rows) || (r == (PCDTable *) NULL))
2993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
300c82a27bb8e3138ff9bbf0f696663bdf3e704cedecristy        (void) ThrowMagickException(exception,GetMagickModule(),
3013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          CorruptImageWarning,"SkipToSyncByte","`%s'",image->filename);
3023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        while ((sum & 0x00fff000) != 0x00fff000)
3033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PCDGetBits(8);
304c31f22eed93546cfdcc39b64cd2e7543e9f94e38cristy        while (IsSync(sum) == 0)
3053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          PCDGetBits(1);
3063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
3073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
3083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (r->key < 128)
309bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      quantum=(ssize_t) (*q)+r->key;
3103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
311bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      quantum=(ssize_t) (*q)+r->key-256;
3123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q=(unsigned char) ((quantum < 0) ? 0 : (quantum > 255) ? 255 : quantum);
3133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q++;
3143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    PCDGetBits(r->length);
3153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count--;
3163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
3173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
3183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Relinquish resources.
3193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
3203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < (image->columns > 1536 ? 3 : 1); i++)
3213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pcd_table[i]=(PCDTable *) RelinquishMagickMemory(pcd_table[i]);
3223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  buffer=(unsigned char *) RelinquishMagickMemory(buffer);
3233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
3243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
3273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   I s P C D                                                                 %
3323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  IsPCD() returns MagickTrue if the image format type, identified by the
3383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  magick string, is PCD.
3393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the IsPCD method is:
3413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType IsPCD(const unsigned char *magick,const size_t length)
3433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
3453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o magick: compare image format pattern against these bytes.
3473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o length: Specifies the length of the magick string.
3493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
3513ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType IsPCD(const unsigned char *magick,const size_t length)
3523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
3533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (length < 2052)
3543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
3553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (LocaleNCompare((const char *) magick+2048,"PCD_",4) == 0)
3563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickTrue);
3573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickFalse);
3583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
3613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e a d P C D I m a g e                                                   %
3663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ReadPCDImage() reads a Photo CD image file and returns it.  It
3723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  allocates the memory necessary for the new Image structure and returns a
3733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  pointer to the new image.  Much of the PCD decoder was derived from
3743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  the program hpcdtoppm(1) by Hadmut Danisch.
3753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the ReadPCDImage method is:
3773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      image=ReadPCDImage(image_info)
3793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
3813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
3833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o exception: return any errors or warnings in this structure.
3853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
3873ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic Image *OverviewImage(const ImageInfo *image_info,Image *image,
3883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ExceptionInfo *exception)
3893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
3903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
3913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *montage_image;
3923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MontageInfo
3943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *montage_info;
3953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register Image
3973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
3983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
4003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Create the PCD Overview image.
4013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
4023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (p=image; p != (Image *) NULL; p=p->next)
4033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
4043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) DeleteImageProperty(p,"label");
405d15e65928aec551b7388c2863de3e3e628e2e0ddcristy    (void) SetImageProperty(p,"label",DefaultTileLabel,exception);
4063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
4073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  montage_info=CloneMontageInfo(image_info,(MontageInfo *) NULL);
4083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CopyMagickString(montage_info->filename,image_info->filename,
409151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    MagickPathExtent);
4103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  montage_image=MontageImageList(image_info,montage_info,image,exception);
4113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  montage_info=DestroyMontageInfo(montage_info);
4123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (montage_image == (Image *) NULL)
4133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
4143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image=DestroyImage(image);
4153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(montage_image);
4163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
4173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
418bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristystatic void Upsample(const size_t width,const size_t height,
419bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  const size_t scaled_width,unsigned char *pixels)
4203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
421bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
4223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x,
4233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    y;
4243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register unsigned char
4263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p,
4273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q,
4283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *r;
4293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
4313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Create a new image that is a integral size greater than an existing one.
4323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
4333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(pixels != (unsigned char *) NULL);
434bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) height; y++)
4353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
4363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    p=pixels+(height-1-y)*scaled_width+(width-1);
4373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q=pixels+((height-1-y) << 1)*scaled_width+((width-1) << 1);
4383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q=(*p);
4393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *(q+1)=(*(p));
440bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=1; x < (ssize_t) width; x++)
4413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
4423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      p--;
4433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q-=2;
4443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *q=(*p);
445aff6d807f839a998fff6e87198f2418868ab508ecristy      *(q+1)=(unsigned char) ((((size_t) *p)+((size_t) *(p+1))+1) >> 1);
4463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
4473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
448bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) (height-1); y++)
4493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
450bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    p=pixels+((size_t) y << 1)*scaled_width;
4513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q=p+scaled_width;
4523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    r=q+scaled_width;
453bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) (width-1); x++)
4543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
455bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      *q=(unsigned char) ((((size_t) *p)+((size_t) *r)+1) >> 1);
456bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      *(q+1)=(unsigned char) ((((size_t) *p)+((size_t) *(p+2))+
457bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        ((size_t) *r)+((size_t) *(r+2))+2) >> 2);
4583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q+=2;
4593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      p+=2;
4603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r+=2;
4613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
462aff6d807f839a998fff6e87198f2418868ab508ecristy    *q++=(unsigned char) ((((size_t) *p++)+((size_t) *r++)+1) >> 1);
463aff6d807f839a998fff6e87198f2418868ab508ecristy    *q++=(unsigned char) ((((size_t) *p++)+((size_t) *r++)+1) >> 1);
4643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
4653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  p=pixels+(2*height-2)*scaled_width;
4663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  q=pixels+(2*height-1)*scaled_width;
4673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CopyMagickMemory(q,p,(size_t) (2*width));
4683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
4693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4703ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic Image *ReadPCDImage(const ImageInfo *image_info,ExceptionInfo *exception)
4713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
4723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
4733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *image;
4743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
4763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
4773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickOffsetType
4793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    offset;
4803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickSizeType
4823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    number_pixels;
4833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
484bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
4853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
4863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    y;
4873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4884c08aed51c5899665ade97263692328eea4af106cristy  register Quantum
4893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
4903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register unsigned char
4923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *c1,
4933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *c2,
4943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *yy;
4953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
496aff6d807f839a998fff6e87198f2418868ab508ecristy  size_t
497aff6d807f839a998fff6e87198f2418868ab508ecristy    height,
498aff6d807f839a998fff6e87198f2418868ab508ecristy    number_images,
499aff6d807f839a998fff6e87198f2418868ab508ecristy    rotate,
500aff6d807f839a998fff6e87198f2418868ab508ecristy    scene,
501aff6d807f839a998fff6e87198f2418868ab508ecristy    width;
502aff6d807f839a998fff6e87198f2418868ab508ecristy
5033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ssize_t
504aff6d807f839a998fff6e87198f2418868ab508ecristy    count,
505aff6d807f839a998fff6e87198f2418868ab508ecristy    x;
5063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned char
5083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *chroma1,
5093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *chroma2,
5103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *header,
5113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *luma;
5123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned int
5143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    overview;
5153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
5173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open image file.
5183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
5193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
520e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image_info->signature == MagickCoreSignature);
5213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->debug != MagickFalse)
5223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
5233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image_info->filename);
5243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception != (ExceptionInfo *) NULL);
525e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(exception->signature == MagickCoreSignature);
5269950d57e1124b73f684fb5946e206994cefda628cristy  image=AcquireImage(image_info,exception);
5273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
5283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
5293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
5303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image=DestroyImageList(image);
5313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return((Image *) NULL);
5323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
5333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
5343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Determine if this a PCD file.
5353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
5363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  header=(unsigned char *) AcquireQuantumMemory(0x800,3UL*sizeof(*header));
5373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (header == (unsigned char *) NULL)
5383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
5393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  count=ReadBlob(image,3*0x800,header);
5403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  overview=LocaleNCompare((char *) header,"PCD_OPA",7) == 0;
541771c884804218f352efd091f15328cebd1696079cristy  if ((count != (3*0x800)) ||
542c31f22eed93546cfdcc39b64cd2e7543e9f94e38cristy      ((LocaleNCompare((char *) header+0x800,"PCD",3) != 0) && (overview ==0)))
5433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
5443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  rotate=header[0x0e02] & 0x03;
5453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  number_images=(header[10] << 8) | header[11];
5462867b87b5c4f5d1ef966355436a1c149723dd6f5cristy  if (number_images > 65535)
5472867b87b5c4f5d1ef966355436a1c149723dd6f5cristy    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
5483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  header=(unsigned char *) RelinquishMagickMemory(header);
5493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
5503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Determine resolution by scene specification.
5513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
5523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((image->columns == 0) || (image->rows == 0))
5533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    scene=3;
5543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
5553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
5563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      width=192;
5573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      height=128;
5583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (scene=1; scene < 6; scene++)
5593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
5603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if ((width >= image->columns) && (height >= image->rows))
5613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
5623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        width<<=1;
5633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        height<<=1;
5643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
5653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
5663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->number_scenes != 0)
567bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    scene=(size_t) MagickMin(image_info->scene,6);
568c31f22eed93546cfdcc39b64cd2e7543e9f94e38cristy  if (overview != 0)
5693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    scene=1;
5703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
5713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Initialize image structure.
5723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
5733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  width=192;
5743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  height=128;
575bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (i=1; i < (ssize_t) MagickMin(scene,3); i++)
5763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
5773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    width<<=1;
5783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    height<<=1;
5793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
5803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->columns=width;
5813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->rows=height;
5823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->depth=8;
583bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for ( ; i < (ssize_t) scene; i++)
5843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
5853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image->columns<<=1;
5863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image->rows<<=1;
5873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
588acabb847a592ca5e430c1c0949d03acfc0b78bb9cristy  status=SetImageExtent(image,image->columns,image->rows,exception);
589acabb847a592ca5e430c1c0949d03acfc0b78bb9cristy  if (status == MagickFalse)
590acabb847a592ca5e430c1c0949d03acfc0b78bb9cristy    return(DestroyImageList(image));
5913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
5925d41880f52dcb79d3681d0841cb8882ee614a8f0cristy    Allocate luma and chroma memory.
5933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
5943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  number_pixels=(MagickSizeType) image->columns*image->rows;
5953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (number_pixels != (size_t) number_pixels)
5963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
5973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chroma1=(unsigned char *) AcquireQuantumMemory(image->columns+1UL,image->rows*
598c31f22eed93546cfdcc39b64cd2e7543e9f94e38cristy    10*sizeof(*chroma1));
5993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chroma2=(unsigned char *) AcquireQuantumMemory(image->columns+1UL,image->rows*
600c31f22eed93546cfdcc39b64cd2e7543e9f94e38cristy    10*sizeof(*chroma2));
6013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  luma=(unsigned char *) AcquireQuantumMemory(image->columns+1UL,image->rows*
602c31f22eed93546cfdcc39b64cd2e7543e9f94e38cristy    10*sizeof(*luma));
6033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((chroma1 == (unsigned char *) NULL) ||
6043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (chroma2 == (unsigned char *) NULL) || (luma == (unsigned char *) NULL))
6053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
6063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
6073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Advance to image data.
6083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
6093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  offset=93;
610c31f22eed93546cfdcc39b64cd2e7543e9f94e38cristy  if (overview != 0)
6113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    offset=2;
6123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
6133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (scene == 2)
6143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      offset=20;
6153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
6163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (scene <= 1)
6173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset=1;
618bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (i=0; i < (ssize_t) (offset*0x800); i++)
6193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) ReadBlobByte(image);
620c31f22eed93546cfdcc39b64cd2e7543e9f94e38cristy  if (overview != 0)
6213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
6223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Image
6233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *overview_image;
6243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      MagickProgressMonitor
6263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        progress_monitor;
6273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
628bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      register ssize_t
6293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        j;
6303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
6323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Read thumbnails from overview image.
6333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
634bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      for (j=1; j <= (ssize_t) number_images; j++)
6353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
6363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        progress_monitor=SetImageProgressMonitor(image,
6373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (MagickProgressMonitor) NULL,image->client_data);
638151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy        (void) FormatLocaleString(image->filename,MagickPathExtent,
639f2faecf9facdbbb14fcba373365f9f691a9658e0cristy          "images/img%04ld.pcd",(long) j);
640151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy        (void) FormatLocaleString(image->magick_filename,MagickPathExtent,
641f2faecf9facdbbb14fcba373365f9f691a9658e0cristy          "images/img%04ld.pcd",(long) j);
642bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        image->scene=(size_t) j;
6433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->columns=width;
6443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->rows=height;
6453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->depth=8;
6463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        yy=luma;
6473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        c1=chroma1;
6483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        c2=chroma2;
649bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        for (y=0; y < (ssize_t) height; y+=2)
6503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
6513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          count=ReadBlob(image,width,yy);
6523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          yy+=image->columns;
6533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          count=ReadBlob(image,width,yy);
6543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          yy+=image->columns;
6553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          count=ReadBlob(image,width >> 1,c1);
6563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          c1+=image->columns;
6573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          count=ReadBlob(image,width >> 1,c2);
6583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          c2+=image->columns;
6593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
6603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Upsample(image->columns >> 1,image->rows >> 1,image->columns,chroma1);
6613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Upsample(image->columns >> 1,image->rows >> 1,image->columns,chroma2);
6623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
6633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Transfer luminance and chrominance channels.
6643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
6653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        yy=luma;
6663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        c1=chroma1;
6673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        c2=chroma2;
668bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        for (y=0; y < (ssize_t) image->rows; y++)
6693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
6703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
671acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy          if (q == (Quantum *) NULL)
6723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
673bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy          for (x=0; x < (ssize_t) image->columns; x++)
6743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
6754c08aed51c5899665ade97263692328eea4af106cristy            SetPixelRed(image,ScaleCharToQuantum(*yy++),q);
6764c08aed51c5899665ade97263692328eea4af106cristy            SetPixelGreen(image,ScaleCharToQuantum(*c1++),q);
6774c08aed51c5899665ade97263692328eea4af106cristy            SetPixelBlue(image,ScaleCharToQuantum(*c2++),q);
678ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy            q+=GetPixelChannels(image);
6793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
6803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (SyncAuthenticPixels(image,exception) == MagickFalse)
6813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
6823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
6833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->colorspace=YCCColorspace;
6843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (LocaleCompare(image_info->magick,"PCDS") == 0)
685e2c4f18a7274c0c5c6231a2f3d73741a87d583facristy          SetImageColorspace(image,sRGBColorspace,exception);
686bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        if (j < (ssize_t) number_images)
6873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
6883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            /*
6893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Allocate next image structure.
6903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            */
6919950d57e1124b73f684fb5946e206994cefda628cristy            AcquireNextImage(image_info,image,exception);
6923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (GetNextImageInList(image) == (Image *) NULL)
6933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
6943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                image=DestroyImageList(image);
6953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                return((Image *) NULL);
6963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
6973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image=SyncNextImageInList(image);
6983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
6993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) SetImageProgressMonitor(image,progress_monitor,
7003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->client_data);
7013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (image->previous == (Image *) NULL)
7023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
7033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            status=SetImageProgress(image,LoadImageTag,j-1,number_images);
7043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (status == MagickFalse)
7053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              break;
7063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
7073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
7083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      chroma2=(unsigned char *) RelinquishMagickMemory(chroma2);
7093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      chroma1=(unsigned char *) RelinquishMagickMemory(chroma1);
7103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      luma=(unsigned char *) RelinquishMagickMemory(luma);
7113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image=GetFirstImageInList(image);
7123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      overview_image=OverviewImage(image_info,image,exception);
7133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return(overview_image);
7143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
7163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Read interleaved image.
7173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
7183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  yy=luma;
7193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  c1=chroma1;
7203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  c2=chroma2;
721bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) height; y+=2)
7223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
7233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count=ReadBlob(image,width,yy);
7243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    yy+=image->columns;
7253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count=ReadBlob(image,width,yy);
7263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    yy+=image->columns;
7273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count=ReadBlob(image,width >> 1,c1);
7283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    c1+=image->columns;
7293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    count=ReadBlob(image,width >> 1,c2);
7303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    c2+=image->columns;
7313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
7323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (scene >= 4)
7333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
7343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
7353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Recover luminance deltas for 1536x1024 image.
7363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
7373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Upsample(768,512,image->columns,luma);
7383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Upsample(384,256,image->columns,chroma1);
7393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Upsample(384,256,image->columns,chroma2);
7403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->rows=1024;
7413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (i=0; i < (4*0x800); i++)
7423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) ReadBlobByte(image);
743018f07f7333b25743d0afff892450cebdb905c1acristy      status=DecodeImage(image,luma,chroma1,chroma2,exception);
7443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((scene >= 5) && status)
7453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
7463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /*
7473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            Recover luminance deltas for 3072x2048 image.
7483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          */
7493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Upsample(1536,1024,image->columns,luma);
7503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Upsample(768,512,image->columns,chroma1);
7513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Upsample(768,512,image->columns,chroma2);
7523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->rows=2048;
7533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          offset=TellBlob(image)/0x800+12;
7543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          offset=SeekBlob(image,offset*0x800,SEEK_SET);
755018f07f7333b25743d0afff892450cebdb905c1acristy          status=DecodeImage(image,luma,chroma1,chroma2,exception);
7563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if ((scene >= 6) && (status != MagickFalse))
7573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
7583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              /*
7593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                Recover luminance deltas for 6144x4096 image (vaporware).
7603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              */
7613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Upsample(3072,2048,image->columns,luma);
7623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Upsample(1536,1024,image->columns,chroma1);
7633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              Upsample(1536,1024,image->columns,chroma2);
7643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              image->rows=4096;
7653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
7663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
7673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Upsample(image->columns >> 1,image->rows >> 1,image->columns,chroma1);
7693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Upsample(image->columns >> 1,image->rows >> 1,image->columns,chroma2);
7703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
7713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Transfer luminance and chrominance channels.
7723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
7733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  yy=luma;
7743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  c1=chroma1;
7753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  c2=chroma2;
776bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) image->rows; y++)
7773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
7783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
779acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy    if (q == (Quantum *) NULL)
7803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
781bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) image->columns; x++)
7823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
7834c08aed51c5899665ade97263692328eea4af106cristy      SetPixelRed(image,ScaleCharToQuantum(*yy++),q);
7844c08aed51c5899665ade97263692328eea4af106cristy      SetPixelGreen(image,ScaleCharToQuantum(*c1++),q);
7854c08aed51c5899665ade97263692328eea4af106cristy      SetPixelBlue(image,ScaleCharToQuantum(*c2++),q);
786ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy      q+=GetPixelChannels(image);
7873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (SyncAuthenticPixels(image,exception) == MagickFalse)
7893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
7903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (image->previous == (Image *) NULL)
7913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
792cee9711bbc334b5677d5ec4ea1cc70340d35ee35cristy        status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
793cee9711bbc334b5677d5ec4ea1cc70340d35ee35cristy                image->rows);
7943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (status == MagickFalse)
7953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
7963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
7973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
7983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chroma2=(unsigned char *) RelinquishMagickMemory(chroma2);
7993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  chroma1=(unsigned char *) RelinquishMagickMemory(chroma1);
8003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  luma=(unsigned char *) RelinquishMagickMemory(luma);
8013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (EOFBlob(image) != MagickFalse)
8023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
8033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->filename);
8043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(image);
8053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->ping == MagickFalse)
8063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if ((rotate == 1) || (rotate == 3))
8073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
8083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        double
8093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          degrees;
8103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Image
8123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          *rotate_image;
8133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
8153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Rotate image.
8163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
8173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        degrees=rotate == 1 ? -90.0 : 90.0;
8183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        rotate_image=RotateImage(image,degrees,exception);
8193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (rotate_image != (Image *) NULL)
8203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
8213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image=DestroyImage(image);
8223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image=rotate_image;
8233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
8243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
8253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
8263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Set CCIR 709 primaries with a D65 white point.
8273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
8283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.red_primary.x=0.6400f;
8293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.red_primary.y=0.3300f;
8303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.green_primary.x=0.3000f;
8313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.green_primary.y=0.6000f;
8323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.blue_primary.x=0.1500f;
8333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.blue_primary.y=0.0600f;
8343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.white_point.x=0.3127f;
8353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->chromaticity.white_point.y=0.3290f;
8363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->gamma=1.000f/2.200f;
8373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->colorspace=YCCColorspace;
8383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (LocaleCompare(image_info->magick,"PCDS") == 0)
839e2c4f18a7274c0c5c6231a2f3d73741a87d583facristy    SetImageColorspace(image,sRGBColorspace,exception);
8403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(GetFirstImageInList(image));
8413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
8423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
8443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e g i s t e r P C D I m a g e                                           %
8493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  RegisterPCDImage() adds attributes for the PCD image format to
8553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  the list of supported formats.  The attributes include the image format
8563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  tag, a method to read and/or write the format, whether the format
8573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  supports the saving of more than one frame to the same file or blob,
8583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  whether the format supports native in-memory I/O, and a brief
8593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  description of the format.
8603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the RegisterPCDImage method is:
8623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
863bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy%      size_t RegisterPCDImage(void)
8643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
866bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristyModuleExport size_t RegisterPCDImage(void)
8673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
8683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickInfo
8693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *entry;
8703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
87106b627a07ff44e1ff93ef1288c9f428066ded10ddirk  entry=AcquireMagickInfo("PCD","PCD","Photo CD");
8723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadPCDImage;
8733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WritePCDImage;
8743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->magick=(IsImageFormatHandler *) IsPCD;
87508e9a113db499034abb5ad8d59b42f8eca3c641cdirk  entry->flags^=CoderAdjoinFlag;
87608e9a113db499034abb5ad8d59b42f8eca3c641cdirk  entry->flags|=CoderSeekableStreamFlag;
8773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
87806b627a07ff44e1ff93ef1288c9f428066ded10ddirk  entry=AcquireMagickInfo("PCD","PCDS","Photo CD");
8793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadPCDImage;
8803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WritePCDImage;
88108e9a113db499034abb5ad8d59b42f8eca3c641cdirk  entry->flags^=CoderAdjoinFlag;
88208e9a113db499034abb5ad8d59b42f8eca3c641cdirk  entry->flags|=CoderSeekableStreamFlag;
8833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
8843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickImageCoderSignature);
8853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
8863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
8883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   U n r e g i s t e r P C D I m a g e                                       %
8933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  UnregisterPCDImage() removes format registrations made by the
8993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  PCD module from the list of supported formats.
9003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the UnregisterPCDImage method is:
9023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      UnregisterPCDImage(void)
9043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
9063ed852eea50f9d4cd633efb8c2b054b8e33c253cristyModuleExport void UnregisterPCDImage(void)
9073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
9083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("PCD");
9093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("PCDS");
9103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
9113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
9133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   W r i t e P C D I m a g e                                                 %
9183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  WritePCDImage() writes an image in the Photo CD encoded image format.
9243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the WritePCDImage method is:
9263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9271e178e70fb3c956f9fc1e30c3ba863e882666465cristy%      MagickBooleanType WritePCDImage(const ImageInfo *image_info,
9281e178e70fb3c956f9fc1e30c3ba863e882666465cristy%        Image *image,ExceptionInfo *exception)
9293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows.
9313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
9333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image:  The image.
9353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9361e178e70fb3c956f9fc1e30c3ba863e882666465cristy%    o exception: return any errors or warnings in this structure.
9371e178e70fb3c956f9fc1e30c3ba863e882666465cristy%
9383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
9393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9403ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType WritePCDTile(Image *image,const char *page_geometry,
94106f590165f0505d42005264893fe14a9e8a79986dirk  const size_t tile_columns,const size_t tile_rows,ExceptionInfo *exception)
9423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
9433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  GeometryInfo
9443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry_info;
9453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
9473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *downsample_image,
9483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *tile_image;
9493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
9513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
9523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickStatusType
9543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    flags;
9553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  RectangleInfo
9573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry;
9583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9594c08aed51c5899665ade97263692328eea4af106cristy  register const Quantum
9603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p,
9613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
9623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
963bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
9643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
9653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x;
9663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
967aff6d807f839a998fff6e87198f2418868ab508ecristy  ssize_t
968aff6d807f839a998fff6e87198f2418868ab508ecristy    y;
969aff6d807f839a998fff6e87198f2418868ab508ecristy
9703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
9713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Scale image to tile size.
9723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
9733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  SetGeometry(image,&geometry);
9743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ParseMetaGeometry(page_geometry,&geometry.x,&geometry.y,
9753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    &geometry.width,&geometry.height);
9763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((geometry.width % 2) != 0)
9773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry.width--;
9783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((geometry.height % 2) != 0)
9793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry.height--;
9803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  tile_image=ResizeImage(image,geometry.width,geometry.height,TriangleFilter,
981aa2c16cb5e695053aa78e40f66bc36fbef4b1ed1cristy    exception);
9823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (tile_image == (Image *) NULL)
9833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
9843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  flags=ParseGeometry(page_geometry,&geometry_info);
985bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  geometry.width=(size_t) geometry_info.rho;
986bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  geometry.height=(size_t) geometry_info.sigma;
9873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((flags & SigmaValue) == 0)
9883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry.height=geometry.width;
9893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((tile_image->columns != geometry.width) ||
9903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (tile_image->rows != geometry.height))
9913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
9923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Image
9933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *bordered_image;
9943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      RectangleInfo
9963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        border_info;
9973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
9993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Put a border around the image.
10003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
10013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      border_info.width=(geometry.width-tile_image->columns+1) >> 1;
10023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      border_info.height=(geometry.height-tile_image->rows+1) >> 1;
1003633f0c61bb0414b644dccf4f335576a10bca0329cristy      bordered_image=BorderImage(tile_image,&border_info,image->compose,
1004c82a27bb8e3138ff9bbf0f696663bdf3e704cedecristy        exception);
10053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (bordered_image == (Image *) NULL)
10063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        return(MagickFalse);
10073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      tile_image=DestroyImage(tile_image);
10083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      tile_image=bordered_image;
10093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
101006f590165f0505d42005264893fe14a9e8a79986dirk  if ((tile_image->columns != tile_columns) || (tile_image->rows != tile_rows))
101106f590165f0505d42005264893fe14a9e8a79986dirk    {
101206f590165f0505d42005264893fe14a9e8a79986dirk      Image
101306f590165f0505d42005264893fe14a9e8a79986dirk        *resize_image;
101406f590165f0505d42005264893fe14a9e8a79986dirk
101506f590165f0505d42005264893fe14a9e8a79986dirk      resize_image=ResizeImage(tile_image,tile_columns,tile_rows,
101606f590165f0505d42005264893fe14a9e8a79986dirk        tile_image->filter,exception);
101706f590165f0505d42005264893fe14a9e8a79986dirk      if (resize_image != (Image *) NULL)
101806f590165f0505d42005264893fe14a9e8a79986dirk        {
101906f590165f0505d42005264893fe14a9e8a79986dirk          tile_image=DestroyImage(tile_image);
102006f590165f0505d42005264893fe14a9e8a79986dirk          tile_image=resize_image;
102106f590165f0505d42005264893fe14a9e8a79986dirk        }
102206f590165f0505d42005264893fe14a9e8a79986dirk    }
1023af8d391906d11f0a1f2bbf4e2adbc4995c852d33cristy  (void) TransformImageColorspace(tile_image,YCCColorspace,exception);
10243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  downsample_image=ResizeImage(tile_image,tile_image->columns/2,
1025aa2c16cb5e695053aa78e40f66bc36fbef4b1ed1cristy    tile_image->rows/2,TriangleFilter,exception);
10263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (downsample_image == (Image *) NULL)
10273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
10283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
10293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Write tile to PCD file.
10303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
1031bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) tile_image->rows; y+=2)
10323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
1033c82a27bb8e3138ff9bbf0f696663bdf3e704cedecristy    p=GetVirtualPixels(tile_image,0,y,tile_image->columns,2,exception);
10344c08aed51c5899665ade97263692328eea4af106cristy    if (p == (const Quantum *) NULL)
10353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
1036bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) (tile_image->columns << 1); x++)
10373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
10384c08aed51c5899665ade97263692328eea4af106cristy      (void) WriteBlobByte(image,ScaleQuantumToChar(GetPixelRed(tile_image,p)));
1039ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy      p+=GetPixelChannels(tile_image);
10403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
1041c82a27bb8e3138ff9bbf0f696663bdf3e704cedecristy    q=GetVirtualPixels(downsample_image,0,y >> 1,downsample_image->columns,1,
1042c82a27bb8e3138ff9bbf0f696663bdf3e704cedecristy      exception);
1043acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy    if (q == (Quantum *) NULL)
10443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
1045bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) downsample_image->columns; x++)
10463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
10474c08aed51c5899665ade97263692328eea4af106cristy      (void) WriteBlobByte(image,ScaleQuantumToChar(
10484c08aed51c5899665ade97263692328eea4af106cristy        GetPixelGreen(tile_image,q)));
10493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q++;
10503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
1051c82a27bb8e3138ff9bbf0f696663bdf3e704cedecristy    q=GetVirtualPixels(downsample_image,0,y >> 1,downsample_image->columns,1,
1052c82a27bb8e3138ff9bbf0f696663bdf3e704cedecristy      exception);
1053acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy    if (q == (Quantum *) NULL)
10543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
1055bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) downsample_image->columns; x++)
10563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
10574c08aed51c5899665ade97263692328eea4af106cristy      (void) WriteBlobByte(image,ScaleQuantumToChar(
10584c08aed51c5899665ade97263692328eea4af106cristy        GetPixelBlue(tile_image,q)));
10593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q++;
10603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
10613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status=SetImageProgress(image,SaveImageTag,y,tile_image->rows);
10623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (status == MagickFalse)
10633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
10643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
10653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 0x800; i++)
10663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(image,'\0');
10673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  downsample_image=DestroyImage(downsample_image);
10683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  tile_image=DestroyImage(tile_image);
10693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
10703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
10713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10721e178e70fb3c956f9fc1e30c3ba863e882666465cristystatic MagickBooleanType WritePCDImage(const ImageInfo *image_info,Image *image,
10731e178e70fb3c956f9fc1e30c3ba863e882666465cristy  ExceptionInfo *exception)
10743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
10753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
10763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *pcd_image;
10773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
10793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
10803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1081bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
10823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i;
10833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
1085e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image_info->signature == MagickCoreSignature);
10863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
1087e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image->signature == MagickCoreSignature);
10883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
10893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
10903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  pcd_image=image;
10913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->columns < image->rows)
10923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
10933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Image
10943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *rotate_image;
10953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
10973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Rotate portrait to landscape.
10983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
10991e178e70fb3c956f9fc1e30c3ba863e882666465cristy      rotate_image=RotateImage(image,90.0,exception);
11003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (rotate_image == (Image *) NULL)
11013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        return(MagickFalse);
11023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      pcd_image=rotate_image;
11033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
11043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
11053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open output image file.
11063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
11071e178e70fb3c956f9fc1e30c3ba863e882666465cristy  status=OpenBlob(image_info,pcd_image,WriteBinaryBlobMode,exception);
11083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
11093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(status);
11103d9f5ba107b160e1819bb6baeeb3a9f521e9f450cristy  if (IssRGBCompatibleColorspace(pcd_image->colorspace) == MagickFalse)
1111c511e881bdb2adc9c87173f8c3a6a747a96dbabdcristy    (void) TransformImageColorspace(pcd_image,sRGBColorspace,exception);
11123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
11133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Write PCD image header.
11143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
11153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 32; i++)
11163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,0xff);
11173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 4; i++)
11183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,0x0e);
11193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 8; 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 < 4; i++)
11243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,0x05);
11253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 8; i++)
11263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\0');
11273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 4; i++)
11283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,0x0A);
11293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 36; i++)
11303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\0');
11313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 4; i++)
11323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,0x01);
11333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 1944; i++)
11343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\0');
11353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlob(pcd_image,7,(const unsigned char *) "PCD_IPI");
11363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobByte(pcd_image,0x06);
11373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < 1530; i++)
11383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\0');
11393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->columns < image->rows)
11403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\1');
11413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
11423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\0');
11433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < (3*0x800-1539); i++)
11443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobByte(pcd_image,'\0');
11453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
11463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Write PCD tiles.
11473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
114806f590165f0505d42005264893fe14a9e8a79986dirk  status=WritePCDTile(pcd_image,"768x512>",192,128,exception);
114906f590165f0505d42005264893fe14a9e8a79986dirk  status=WritePCDTile(pcd_image,"768x512>",384,256,exception);
115006f590165f0505d42005264893fe14a9e8a79986dirk  status=WritePCDTile(pcd_image,"768x512>",768,512,exception);
11513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(pcd_image);
11523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (pcd_image != image)
11533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pcd_image=DestroyImage(pcd_image);
11543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(status);
11553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1156