13ed852eea50f9d4cd633efb8c2b054b8e33c253cristy// This may look like C code, but it is really -*- C++ -*-
23ed852eea50f9d4cd633efb8c2b054b8e33c253cristy//
33ed852eea50f9d4cd633efb8c2b054b8e33c253cristy// Copyright Bob Friesenhahn, 1999, 2000, 2001, 2002, 2003
477328896b876314656427663695bc7b2c9be3f74dirk// Copyright Dirk Lemstra 2013-2015
53ed852eea50f9d4cd633efb8c2b054b8e33c253cristy//
63ed852eea50f9d4cd633efb8c2b054b8e33c253cristy// Pixels Implementation
73ed852eea50f9d4cd633efb8c2b054b8e33c253cristy//
83ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
93ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define MAGICKCORE_IMPLEMENTATION  1
103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define MAGICK_PLUSPLUS_IMPLEMENTATION 1
113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1205065f4c09f42c5cd3b5720e5b52c0c3928d2b2bcristy#include <cstring>
133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "Magick++/Include.h"
143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include <string> // This is here to compile with Visual C++
153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "Magick++/Thread.h"
163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "Magick++/Exception.h"
173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "Magick++/Pixels.h"
183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
196f0033cdfd3b04c652521d2ff9c375366972225adirkMagick::Pixels::Pixels(Magick::Image &image_)
203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  : _image(image_),
213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    _x(0),
223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    _y(0),
233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    _columns(0),
243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    _rows(0)
253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
26e31feb8a39ea937a6328da579085cd2ee66ab4c0dirk  GetPPException;
2707f84e72b205d18eb8ad35380af95351d9f0a1a3dirk    _view=AcquireVirtualCacheView(image_.image(),exceptionInfo),
2877328896b876314656427663695bc7b2c9be3f74dirk  ThrowPPException(image_.quiet());
293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
316f0033cdfd3b04c652521d2ff9c375366972225adirkMagick::Pixels::~Pixels(void)
323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
336f0033cdfd3b04c652521d2ff9c375366972225adirk  if (_view)
346f0033cdfd3b04c652521d2ff9c375366972225adirk    _view=DestroyCacheView(_view);
353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
376f0033cdfd3b04c652521d2ff9c375366972225adirkMagick::Quantum* Magick::Pixels::get(const ssize_t x_,const ssize_t y_,
386f0033cdfd3b04c652521d2ff9c375366972225adirk  const size_t columns_,const size_t rows_)
393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
406f0033cdfd3b04c652521d2ff9c375366972225adirk  _x=x_;
416f0033cdfd3b04c652521d2ff9c375366972225adirk  _y=y_;
426f0033cdfd3b04c652521d2ff9c375366972225adirk  _columns=columns_;
436f0033cdfd3b04c652521d2ff9c375366972225adirk  _rows=rows_;
443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
45e31feb8a39ea937a6328da579085cd2ee66ab4c0dirk  GetPPException;
466f0033cdfd3b04c652521d2ff9c375366972225adirk  Quantum* pixels=GetCacheViewAuthenticPixels(_view,x_,y_,columns_,rows_,
47e31feb8a39ea937a6328da579085cd2ee66ab4c0dirk    exceptionInfo);
4807f84e72b205d18eb8ad35380af95351d9f0a1a3dirk  ThrowPPException(_image.quiet());
493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return pixels;
513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
536f0033cdfd3b04c652521d2ff9c375366972225adirkconst Magick::Quantum* Magick::Pixels::getConst(const ssize_t x_,
546f0033cdfd3b04c652521d2ff9c375366972225adirk  const ssize_t y_,const size_t columns_,const size_t rows_)
553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
566f0033cdfd3b04c652521d2ff9c375366972225adirk  _x=x_;
576f0033cdfd3b04c652521d2ff9c375366972225adirk  _y=y_;
586f0033cdfd3b04c652521d2ff9c375366972225adirk  _columns=columns_;
596f0033cdfd3b04c652521d2ff9c375366972225adirk  _rows=rows_;
603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
61e31feb8a39ea937a6328da579085cd2ee66ab4c0dirk  GetPPException;
626f0033cdfd3b04c652521d2ff9c375366972225adirk  const Quantum* pixels=GetCacheViewVirtualPixels(_view,x_,y_,columns_,rows_,
63e31feb8a39ea937a6328da579085cd2ee66ab4c0dirk    exceptionInfo);
6407f84e72b205d18eb8ad35380af95351d9f0a1a3dirk  ThrowPPException(_image.quiet());
653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
666f0033cdfd3b04c652521d2ff9c375366972225adirk  return pixels;
673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6900bcb8c08b29ab70e1d24a21ccfe8515baa2af6cdirkssize_t Magick::Pixels::offset(PixelChannel channel) const
7000bcb8c08b29ab70e1d24a21ccfe8515baa2af6cdirk{
7100bcb8c08b29ab70e1d24a21ccfe8515baa2af6cdirk  if (_image.constImage()->channel_map[channel].traits == UndefinedPixelTrait)
7200bcb8c08b29ab70e1d24a21ccfe8515baa2af6cdirk    return -1;
7300bcb8c08b29ab70e1d24a21ccfe8515baa2af6cdirk  return _image.constImage()->channel_map[channel].offset;
7400bcb8c08b29ab70e1d24a21ccfe8515baa2af6cdirk}
7500bcb8c08b29ab70e1d24a21ccfe8515baa2af6cdirk
766f0033cdfd3b04c652521d2ff9c375366972225adirkMagick::Quantum* Magick::Pixels::set(const ssize_t x_,const ssize_t y_,
776f0033cdfd3b04c652521d2ff9c375366972225adirk  const size_t columns_,const size_t rows_)
783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
796f0033cdfd3b04c652521d2ff9c375366972225adirk  _x=x_;
806f0033cdfd3b04c652521d2ff9c375366972225adirk  _y=y_;
816f0033cdfd3b04c652521d2ff9c375366972225adirk  _columns=columns_;
826f0033cdfd3b04c652521d2ff9c375366972225adirk  _rows=rows_;
836f0033cdfd3b04c652521d2ff9c375366972225adirk
84e31feb8a39ea937a6328da579085cd2ee66ab4c0dirk  GetPPException;
856f0033cdfd3b04c652521d2ff9c375366972225adirk  Quantum* pixels=QueueCacheViewAuthenticPixels(_view,x_,y_,columns_,rows_,
86e31feb8a39ea937a6328da579085cd2ee66ab4c0dirk    exceptionInfo);
8707f84e72b205d18eb8ad35380af95351d9f0a1a3dirk  ThrowPPException(_image.quiet());
886f0033cdfd3b04c652521d2ff9c375366972225adirk
896f0033cdfd3b04c652521d2ff9c375366972225adirk  return pixels;
903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
916f0033cdfd3b04c652521d2ff9c375366972225adirk
926f0033cdfd3b04c652521d2ff9c375366972225adirkvoid Magick::Pixels::sync(void)
933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
94e31feb8a39ea937a6328da579085cd2ee66ab4c0dirk  GetPPException;
958aebeb37446aee3cd6a9649420bfe2a167bb2de9cristy  (void) SyncCacheViewAuthenticPixels(_view,exceptionInfo);
9607f84e72b205d18eb8ad35380af95351d9f0a1a3dirk  ThrowPPException(_image.quiet());
973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy// Return pixel colormap index array
1004c08aed51c5899665ade97263692328eea4af106cristy/*
1016f0033cdfd3b04c652521d2ff9c375366972225adirkMagick::void* Magick::Pixels::metacontent(void)
1023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
1036f0033cdfd3b04c652521d2ff9c375366972225adirk  void* pixel_metacontent=GetCacheViewAuthenticMetacontent(_view);
1043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1056f0033cdfd3b04c652521d2ff9c375366972225adirk  if (!pixel_metacontent)
1063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    _image.throwImageException();
1073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1084c08aed51c5899665ade97263692328eea4af106cristy  return pixel_metacontent;
1093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1104c08aed51c5899665ade97263692328eea4af106cristy*/
111a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk
112a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirkMagick::PixelData::PixelData(Magick::Image &image_,std::string map_,
113a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk  const StorageType type_)
114a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk{
115a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk  init(image_,0,0,image_.columns(),image_.rows(),map_,type_);
116a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk}
117a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk
118a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirkMagick::PixelData::PixelData(Magick::Image &image_,const ::ssize_t x_,
119a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk  const ::ssize_t y_,const size_t width_,const size_t height_,std::string map_,
120a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk  const StorageType type_)
121a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk{
122a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk  init(image_,x_,y_,width_,height_,map_,type_);
123a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk}
124a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk
125a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirkMagick::PixelData::~PixelData(void)
126a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk{
127a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk  relinquish();
128a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk}
129a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk
130a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirkconst void *Magick::PixelData::data(void) const
131a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk{
132a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk  return(_data);
133a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk}
134a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk
1352a9bf2113bca33b919674599c11805300c7b7a7bdirk::ssize_t Magick::PixelData::length(void) const
136a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk{
137a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk  return(_length);
138a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk}
139a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk
1402a9bf2113bca33b919674599c11805300c7b7a7bdirk::ssize_t Magick::PixelData::size(void) const
141a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk{
142a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk  return(_size);
143a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk}
144a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk
145a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirkvoid Magick::PixelData::init(Magick::Image &image_,const ::ssize_t x_,
146a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk  const ::ssize_t y_,const size_t width_,const size_t height_,
147a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk  std::string map_,const StorageType type_)
148a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk{
149a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk  size_t
150a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk    size;
151a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk
152a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk  _data=(void *) NULL;
153a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk  _length=0;
154a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk  _size=0;
1559bb7c84a6ae3b9a07cf67c2e18d5dce78e75ad31cristy  if ((x_ < 0) || (width_ == 0) || (y_ < 0) || (height_ == 0) ||
156d9b47c63dc5ef8f7f38d1aa7e012306696f8bf57cristy      (x_ > (ssize_t) image_.columns()) || ((width_ + x_) > image_.columns())
157d9b47c63dc5ef8f7f38d1aa7e012306696f8bf57cristy      || (y_ > (ssize_t) image_.rows()) || ((height_ + y_) > image_.rows())
15898d9f1c5c10b246b0a5cb86c4ae849b45885c7cbdirk      || (map_.length() == 0))
159a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk    return;
160a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk
161a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk  switch(type_)
162a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk  {
163a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk    case CharPixel:
164a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk      size=sizeof(unsigned char);
165a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk      break;
166a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk    case DoublePixel:
167a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk      size=sizeof(double);
168a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk      break;
169a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk    case FloatPixel:
170a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk      size=sizeof(float);
171a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk      break;
172a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk    case LongPixel:
173a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk      size=sizeof(unsigned int);
174a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk      break;
175a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk    case LongLongPixel:
176a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk      size=sizeof(MagickSizeType);
177a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk      break;
178a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk    case QuantumPixel:
179a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk      size=sizeof(Quantum);
180a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk      break;
181a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk    case ShortPixel:
182a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk      size=sizeof(unsigned short);
183a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk      break;
184a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk    default:
18577328896b876314656427663695bc7b2c9be3f74dirk      throwExceptionExplicit(MagickCore::OptionError,"Invalid type");
186a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk      return;
187a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk  }
188a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk
189a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk  _length=width_*height_*map_.length();
190a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk  _size=_length*size;
191a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk  _data=AcquireMagickMemory(_size);
192a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk
193a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk  GetPPException;
194933b13290dde32a0c054340cb1a242564684e0e8dirk  MagickCore::ExportImagePixels(image_.image(),x_,y_,width_,height_,
195e31feb8a39ea937a6328da579085cd2ee66ab4c0dirk    map_.c_str(),type_,_data,exceptionInfo);
19677328896b876314656427663695bc7b2c9be3f74dirk  if (exceptionInfo->severity != MagickCore::UndefinedException)
197a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk    relinquish();
19877328896b876314656427663695bc7b2c9be3f74dirk  ThrowPPException(image_.quiet());
199a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk}
200a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk
201a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirkvoid Magick::PixelData::relinquish(void) throw()
202a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk{
203a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk  if (_data != (void *)NULL)
204a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk    _data=RelinquishMagickMemory(_data);
205a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk  _length=0;
206a7c1e5c12b9aec82327d2cae6ff71712c4b875d4dirk  _size=0;
2079bb7c84a6ae3b9a07cf67c2e18d5dce78e75ad31cristy}
208