1 /******************************************************************************* 2 * image.h 3 * 4 * --------------------------------------------------------------------------- 5 * Persistence of Vision Ray Tracer ('POV-Ray') version 3.7. 6 * Copyright 1991-2013 Persistence of Vision Raytracer Pty. Ltd. 7 * 8 * POV-Ray is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU Affero General Public License as 10 * published by the Free Software Foundation, either version 3 of the 11 * License, or (at your option) any later version. 12 * 13 * POV-Ray is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU Affero General Public License for more details. 17 * 18 * You should have received a copy of the GNU Affero General Public License 19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 20 * --------------------------------------------------------------------------- 21 * POV-Ray is based on the popular DKB raytracer version 2.12. 22 * DKBTrace was originally written by David K. Buck. 23 * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins. 24 * --------------------------------------------------------------------------- 25 * $File: //depot/public/povray/3.x/source/base/image/image.h $ 26 * $Revision: #1 $ 27 * $Change: 6069 $ 28 * $DateTime: 2013/11/06 11:59:40 $ 29 * $Author: chrisc $ 30 *******************************************************************************/ 31 32 #ifndef POVRAY_BASE_IMAGE_H 33 #define POVRAY_BASE_IMAGE_H 34 35 #include "base/configbase.h" 36 #include "base/fileinputoutput.h" 37 #include "base/pov_err.h" 38 #include "base/image/colourspace.h" 39 #include "base/image/encoding.h" 40 41 namespace pov_base 42 { 43 44 /** 45 * Generic image data container. 46 * 47 * @note Except for access functions having a @c premul parameter as well as those named 48 * @c GetEncodedSomethingValue or SetEncodedSomethingValue, all other access functions are unaware of 49 * premultiplied vs. non-premultiplied alpha issues, and will access the data in whatever format 50 * it is stored (as far as alpha handling goes). 51 * 52 * @note When backed by a gamma-encoded data container, unsigned int access methods are presumed 53 * to read/write raw encoded data, while float access methods will read/write logical 54 * linear values. 55 */ 56 class Image 57 { 58 public: 59 struct RGBMapEntry 60 { 61 float red; 62 float green; 63 float blue; 64 RGBMapEntryRGBMapEntry65 RGBMapEntry() : red(0.0f), green(0.0f), blue(0.0f) { } RGBMapEntryRGBMapEntry66 RGBMapEntry(float r, float g, float b) : red(r), green(g), blue(b) { } 67 }; 68 69 struct RGBAMapEntry 70 { 71 float red; 72 float green; 73 float blue; 74 float alpha; 75 RGBAMapEntryRGBAMapEntry76 RGBAMapEntry() : red(0.0f), green(0.0f), blue(0.0f), alpha(0.0f) { } RGBAMapEntryRGBAMapEntry77 RGBAMapEntry(float r, float g, float b, float a) : red(r), green(g), blue(b), alpha(a) { } 78 }; 79 80 struct RGBFTMapEntry 81 { 82 float red; 83 float green; 84 float blue; 85 float filter; 86 float transm; 87 RGBFTMapEntryRGBFTMapEntry88 RGBFTMapEntry() : red(0.0f), green(0.0f), blue(0.0f), filter(0.0f), transm(0.0f) { } RGBFTMapEntryRGBFTMapEntry89 RGBFTMapEntry(float r, float g, float b, float f, float t) : red(r), green(g), blue(b), filter(f), transm(t) { } 90 }; 91 92 enum ColourMapType 93 { 94 NoColourMap, 95 RGBColourMap, 96 RGBAColourMap, 97 RGBFTColourMap 98 }; 99 100 enum ImageDataType 101 { 102 /// Value used to indicate that image decoder is free to pick the most fitting type. 103 Undefined, 104 /// Palette-based image with 2 palette entries. 105 Bit_Map, 106 /// Palette-based image with up to 256 palette entries. 107 Colour_Map, 108 /// Single-channel (grayscale) image using 8-bit linear encoding. 109 Gray_Int8, 110 /// Single-channel (grayscale) image using 16-bit linear encoding. 111 Gray_Int16, 112 /// Dual-channel (grayscale and alpha) image using 8-bit linear encoding. 113 GrayA_Int8, 114 /// Dual-channel (grayscale and alpha) image using 16-bit linear encoding. 115 GrayA_Int16, 116 /// 3-channel (colour) image using 8-bit linear encoding. 117 RGB_Int8, 118 /// 3-channel (colour) image using 16-bit linear encoding. 119 RGB_Int16, 120 /// 4-channel (colour and alpha) image using 8-bit linear encoding. 121 RGBA_Int8, 122 /// 4-channel (colour and alpha) image using 16-bit linear encoding. 123 RGBA_Int16, 124 /// 5-channel (colour, filter and transmit) image using single-precision floating-point encoding. 125 RGBFT_Float, 126 /// 3-channel (colour) image using 8-bit gamma encoding. 127 RGB_Gamma8, 128 /// 3-channel (colour) image using 16-bit gamma encoding. 129 RGB_Gamma16, 130 /// 4-channel (colour and alpha) image using 8-bit gamma colour encoding and 8-bit linear alpha encoding. 131 RGBA_Gamma8, 132 /// 4-channel (colour and alpha) image using 16-bit gamma colour encoding and 16-bit linear alpha encoding. 133 RGBA_Gamma16, 134 /// Single-channel (grayscale) image using 8-bit gamma encoding. 135 Gray_Gamma8, 136 /// Single-channel (grayscale) image using 16-bit gamma encoding. 137 Gray_Gamma16, 138 /// Dual-channel (grayscale and alpha) image using 8-bit gamma greyscale encoding and 8-bit linear alpha encoding. 139 GrayA_Gamma8, 140 /// Dual-channel (grayscale and alpha) image using 16-bit gamma greyscale encoding and 16-bit linear alpha encoding. 141 GrayA_Gamma16 142 }; 143 144 enum ImageFileType 145 { 146 GIF, 147 POT, 148 SYS, 149 IFF, 150 TGA, 151 PGM, 152 PPM, 153 PNG, 154 JPEG, 155 TIFF, 156 BMP, 157 EXR, 158 HDR 159 }; 160 161 struct ReadOptions 162 { 163 ImageDataType itype; 164 SimpleGammaCurvePtr defaultGamma; // the gamma curve to use by default for converting to linear colour space 165 SimpleGammaCurvePtr workingGamma; // the working colour space gamma 166 bool gammaOverride; // whether to apply defaultGamma even if the file indicates a different gamma 167 bool gammacorrect; // whether to do any gamma correction at all; if false, raw encoded values are used 168 bool premultiplyOverride; // whether to override file-format default for alpha premultiplication 169 bool premultiply; // whether to expect premultiplied ("associated") alpha or not ("straight alpha") 170 mutable vector<string> warnings; 171 ReadOptionsReadOptions172 ReadOptions() : itype(Undefined), gammaOverride(false), gammacorrect(false), premultiplyOverride(false), premultiply(false) { } 173 }; 174 175 struct WriteOptions 176 { 177 unsigned char bpcc; // bits per colour component 178 bool alphachannel; 179 bool grayscale; 180 unsigned char compress; 181 SimpleGammaCurvePtr encodingGamma; // the gamma curve to use for encoding from linear if the file format leaves any choice (NULL to use file format recommendation) 182 SimpleGammaCurvePtr workingGamma; // the working colour space gamma 183 bool premultiplyOverride; // whether to override file-format default for alpha premultiplication 184 bool premultiply; // whether to output premultiplied ("associated") alpha or not ("straight alpha") 185 DitherHandlerPtr dither; 186 unsigned int offset_x; 187 unsigned int offset_y; 188 WriteOptionsWriteOptions189 WriteOptions() : bpcc(8), alphachannel(false), grayscale(false), compress(0) /*, gamma(1.0f) */, premultiplyOverride(false), premultiply(false), offset_x(0), offset_y(0) { } 190 }; 191 ~Image()192 virtual ~Image() { } 193 194 static Image *Create(unsigned int w, unsigned int h, ImageDataType t, unsigned int maxRAMmbHint, unsigned int pixelsPerBlockHint); 195 static Image *Create(unsigned int w, unsigned int h, ImageDataType t, bool allowFileBacking = false); 196 static Image *Create(unsigned int w, unsigned int h, ImageDataType t, const vector<RGBMapEntry>& m, bool allowFileBacking = false); 197 static Image *Create(unsigned int w, unsigned int h, ImageDataType t, const vector<RGBAMapEntry>& m, bool allowFileBacking = false); 198 static Image *Create(unsigned int w, unsigned int h, ImageDataType t, const vector<RGBFTMapEntry>& m, bool allowFileBacking = false); 199 200 // ftype = use this image type, if "Undefined" use best match 201 static Image *Read(ImageFileType ftype, IStream *file, const ReadOptions& options = ReadOptions()); 202 203 // bitperpixel = use this number of bits per pixel or closest supported match, if "0" use best match 204 // compress = if "0" use no compression, other values use fomat specific compression (TBD) 205 static void Write(ImageFileType ftype, OStream *file, const Image *image, const WriteOptions& options = WriteOptions()); 206 GetWidth()207 unsigned int GetWidth() const { return width; } GetHeight()208 unsigned int GetHeight() const { return height; } GetImageDataType()209 ImageDataType GetImageDataType() const { return type; } 210 211 /// Returns true if image is fully opaque. 212 virtual bool IsOpaque() const = 0; 213 214 virtual bool IsGrayscale() const = 0; 215 virtual bool IsColour() const = 0; 216 virtual bool IsFloat() const = 0; 217 virtual bool IsInt() const = 0; 218 219 /// Returns true if backed by a palette-based container. 220 virtual bool IsIndexed() const = 0; 221 222 /// Returns true if backed by a gamma-encoded data container. 223 virtual bool IsGammaEncoded() const = 0; 224 225 /// Returns true if container features a genuine alpha channel. 226 virtual bool HasAlphaChannel() const = 0; 227 228 /// Returns true if container features genuine filter & transmit channels. 229 virtual bool HasFilterTransmit() const = 0; 230 231 /// Returns true if container features any way of storing transparency information. HasTransparency()232 virtual bool HasTransparency() const { return (HasAlphaChannel() || HasFilterTransmit()); } 233 234 /// Returns the maximum value supported by int access methods or for palette indices (1, 255 or 65535). 235 virtual unsigned int GetMaxIntValue() const = 0; 236 237 /// Specifies whether container holds color data premultiplied with alpha SetPremultiplied(bool b)238 void SetPremultiplied(bool b) { premultiplied = b; } // TODO - mechanism not fully functional yet for image reading 239 240 /// Returns true if container holds data premultiplied with alpha IsPremultiplied()241 bool IsPremultiplied() const { return premultiplied; } 242 243 /** 244 * Requests the image container to perform deferred decoding of integer values. 245 * In order for the request to be honored, the requested value range must match the container's native 246 * bit depth, and the container must have a neutral encoding gamma curve set at present. 247 * @note If the request is honored, this will also affect subsequent unsigned int read accesses. 248 * @param[in,out] gamma Gamma encoding curve of the encoded material. Set to empty by the function 249 * if the request is accepted. 250 * @param[in] max Maximum encoded value. In order for the request to be honored, this must match 251 * the image container's native bit depth. 252 * @return true it the request is accepted, false otherwise. 253 */ 254 virtual bool TryDeferDecoding(GammaCurvePtr& gamma, unsigned int max) = 0; 255 256 void GetRGBIndexedValue(unsigned char index, float& red, float& green, float& blue) const; 257 void GetRGBAIndexedValue(unsigned char index, float& red, float& green, float& blue, float& alpha) const; 258 void GetRGBFTIndexedValue(unsigned char index, float& red, float& green, float& blue, float& filter, float& transm) const; 259 260 void SetRGBIndexedValue(unsigned char index, float red, float green, float blue); 261 void SetRGBAIndexedValue(unsigned char index, float red, float green, float blue, float alpha); 262 void SetRGBFTIndexedValue(unsigned char index, float red, float green, float blue, float filter, float transm); 263 void SetRGBFTIndexedValue(unsigned char index, const Colour& colour); 264 265 virtual bool GetBitValue(unsigned int x, unsigned int y) const = 0; 266 virtual float GetGrayValue(unsigned int x, unsigned int y) const = 0; 267 virtual void GetGrayAValue(unsigned int x, unsigned int y, float& gray, float& alpha) const = 0; 268 virtual void GetRGBValue(unsigned int x, unsigned int y, float& red, float& green, float& blue) const = 0; 269 virtual void GetRGBAValue(unsigned int x, unsigned int y, float& red, float& green, float& blue, float& alpha) const = 0; 270 virtual void GetRGBFTValue(unsigned int x, unsigned int y, float& red, float& green, float& blue, float& filter, float& transm) const = 0; 271 virtual unsigned char GetIndexedValue(unsigned int x, unsigned int y); 272 273 virtual void SetBitValue(unsigned int x, unsigned int y, bool bit) = 0; 274 virtual void SetGrayValue(unsigned int x, unsigned int y, float gray) = 0; 275 virtual void SetGrayValue(unsigned int x, unsigned int y, unsigned int gray) = 0; 276 virtual void SetGrayAValue(unsigned int x, unsigned int y, float gray, float alpha) = 0; 277 virtual void SetGrayAValue(unsigned int x, unsigned int y, unsigned int gray, unsigned int alpha) = 0; 278 virtual void SetRGBValue(unsigned int x, unsigned int y, float red, float green, float blue) = 0; 279 virtual void SetRGBValue(unsigned int x, unsigned int y, unsigned int red, unsigned int green, unsigned int blue) = 0; 280 virtual void SetRGBAValue(unsigned int x, unsigned int y, float red, float green, float blue, float alpha) = 0; 281 virtual void SetRGBAValue(unsigned int x, unsigned int y, unsigned int red, unsigned int green, unsigned int blue, unsigned int alpha) = 0; 282 virtual void SetRGBFTValue(unsigned int x, unsigned int y, float red, float green, float blue, float filter, float transm) = 0; 283 virtual void SetRGBFTValue(unsigned int x, unsigned int y, const Colour& col) = 0; 284 virtual void SetIndexedValue(unsigned int x, unsigned int y, unsigned char index); 285 286 // convenience functions for image evaluation 287 void GetRGBValue(unsigned int x, unsigned int y, RGBColour& colour, bool premul = false) const; 288 void GetRGBFTValue(unsigned int x, unsigned int y, Colour& colour, bool premul = false) const; 289 290 virtual void FillBitValue(bool bit) = 0; 291 virtual void FillGrayValue(float gray) = 0; 292 virtual void FillGrayValue(unsigned int gray) = 0; 293 virtual void FillGrayAValue(float gray, float alpha) = 0; 294 virtual void FillGrayAValue(unsigned int gray, unsigned int alpha) = 0; 295 virtual void FillRGBValue(float red, float green, float blue) = 0; 296 virtual void FillRGBValue(unsigned int red, unsigned int green, unsigned int blue) = 0; 297 virtual void FillRGBAValue(float red, float green, float blue, float alpha) = 0; 298 virtual void FillRGBAValue(unsigned int red, unsigned int green, unsigned int blue, unsigned int alpha) = 0; 299 virtual void FillRGBFTValue(float red, float green, float blue, float filter, float transm) = 0; 300 virtual void FillIndexedValue(unsigned char index); 301 302 unsigned int GetColourMapSize() const; 303 304 void GetColourMap(vector<RGBMapEntry>& m) const; 305 void GetColourMap(vector<RGBAMapEntry>& m) const; 306 void GetColourMap(vector<RGBFTMapEntry>& m) const; 307 308 void SetColourMap(const vector<RGBMapEntry>& m); 309 void SetColourMap(const vector<RGBAMapEntry>& m); 310 void SetColourMap(const vector<RGBFTMapEntry>& m); 311 /* 312 void CopyTo(unsigned int x, unsigned int y, const Image& srcimage) 313 { 314 // TODO 315 } 316 void CopyToScaled(unsigned int x, unsigned int y, unsigned int w, unsigned int h, const Image& srcimage, bool smooth = false) 317 { 318 // TODO 319 }*/ 320 protected: 321 struct MapEntry 322 { 323 float red; 324 float green; 325 float blue; 326 float filter; // alpha = filter 327 float transm; 328 MapEntryMapEntry329 MapEntry() : red(0.0f), green(0.0f), blue(0.0f), filter(0.0f), transm(0.0f) { } MapEntryMapEntry330 MapEntry(float r, float g, float b, float f, float t) : red(r), green(g), blue(b), filter(f), transm(t) { } MapEntryMapEntry331 MapEntry(const RGBMapEntry& e) : red(e.red), green(e.green), blue(e.blue), filter(0.0f), transm(0.0f) { } MapEntryMapEntry332 MapEntry(const RGBAMapEntry& e) : red(e.red), green(e.green), blue(e.blue), filter(e.alpha), transm(0.0f) { } MapEntryMapEntry333 MapEntry(const RGBFTMapEntry& e) : red(e.red), green(e.green), blue(e.blue), filter(e.filter), transm(e.transm) { } 334 }; 335 336 vector<MapEntry> colormap; 337 ColourMapType colormaptype; 338 unsigned int width; 339 unsigned int height; 340 ImageDataType type; 341 bool premultiplied; 342 Image(unsigned int w,unsigned int h,ImageDataType t)343 Image(unsigned int w, unsigned int h, ImageDataType t) : 344 width(w), height(h), type(t), colormaptype(NoColourMap), premultiplied(false) { } 345 Image(unsigned int w,unsigned int h,ImageDataType t,const vector<RGBMapEntry> & m)346 Image(unsigned int w, unsigned int h, ImageDataType t, const vector<RGBMapEntry>& m) : 347 width(w), height(h), type(t), colormaptype(RGBColourMap), premultiplied(false) { colormap.resize(max(m.size(), sizeof(unsigned char) * 256)); colormap.assign(m.begin(), m.end()); } 348 Image(unsigned int w,unsigned int h,ImageDataType t,const vector<RGBAMapEntry> & m)349 Image(unsigned int w, unsigned int h, ImageDataType t, const vector<RGBAMapEntry>& m) : 350 width(w), height(h), type(t), colormaptype(RGBAColourMap), premultiplied(false) { colormap.resize(max(m.size(), sizeof(unsigned char) * 256)); colormap.assign(m.begin(), m.end()); } 351 Image(unsigned int w,unsigned int h,ImageDataType t,const vector<RGBFTMapEntry> & m)352 Image(unsigned int w, unsigned int h, ImageDataType t, const vector<RGBFTMapEntry>& m) : 353 width(w), height(h), type(t), colormaptype(RGBFTColourMap), premultiplied(false) { colormap.resize(max(m.size(), sizeof(unsigned char) * 256)); colormap.assign(m.begin(), m.end()); } 354 RGB2Gray(float red,float green,float blue)355 float RGB2Gray(float red, float green, float blue) const 356 { 357 return (red * 0.297f + green * 0.589f + blue * 0.114f); 358 } 359 private: 360 /// not available 361 Image(); 362 /// not available 363 Image(const Image&); 364 /// not available 365 Image& operator=(Image&); 366 }; 367 368 } 369 370 #endif // POVRAY_BASE_IMAGE_H 371