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