1 // GnashImage.h: Base class for reading image data in Gnash.
2 //
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
4 // Free Software Foundation, Inc
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 //
20
21 // The GnashImage class and subclasses are partly based on the public domain
22 // work of Thatcher Ulrich <tu@tulrich.com> 2002
23
24 #ifndef GNASH_GNASHIMAGE_H
25 #define GNASH_GNASHIMAGE_H
26
27 #include <boost/noncopyable.hpp>
28 #include <cstdint>
29 #include <memory>
30
31 #include "GnashEnums.h"
32 #include "log.h"
33 #include "dsodefs.h"
34
35 // Forward declarations
36 namespace gnash {
37 class IOChannel;
38 }
39
40 namespace gnash {
41
42 /// Image handling functions and classes.
43 namespace image {
44
45 /// The types of images handled in Gnash.
46 enum ImageType
47 {
48 GNASH_IMAGE_INVALID,
49 TYPE_RGB,
50 TYPE_RGBA
51 };
52
53 /// The locations of images handled in Gnash.
54 enum ImageLocation
55 {
56 GNASH_IMAGE_CPU = 1,
57 GNASH_IMAGE_GPU
58 };
59
60 inline size_t
numChannels(ImageType t)61 numChannels(ImageType t)
62 {
63 switch (t) {
64 case TYPE_RGBA:
65 return 4;
66 case TYPE_RGB:
67 return 3;
68 default:
69 std::abort();
70 }
71 }
72
73 /// Base class for different types of bitmaps
74 //
75 /// 1. Bytes are packed in RGB(A) order.
76 /// 2. Rowstride is equal to channels * width
77 class DSOEXPORT GnashImage : boost::noncopyable
78 {
79 public:
80
81 typedef std::uint8_t value_type;
82 typedef std::unique_ptr<value_type[]> container_type;
83 typedef value_type* iterator;
84 typedef const value_type* const_iterator;
85
~GnashImage()86 virtual ~GnashImage() {}
87
88 /// Return the ImageType of the image.
89 //
90 /// This saves guessing when dynamic_cast is used.
type()91 ImageType type() const {
92 return _type;
93 }
94
95 /// Return the ImageLocation of the image.
96 //
97 /// This saves guessing when dynamic_cast is used.
location()98 ImageLocation location() const {
99 return _location;
100 }
101
102 /// Get the size of the image buffer
103 //
104 /// @return The size of the buffer in bytes
size()105 size_t size() const {
106 return stride() * _height;
107 }
108
109 /// Get the pitch of the image buffer
110 //
111 /// @return The rowstride of the buffer in bytes
stride()112 virtual size_t stride() const {
113 return _width * channels();
114 }
115
116 /// Get the number of channels
117 //
118 /// @return The number of channels
channels()119 size_t channels() const {
120 return numChannels(_type);
121 }
122
123 /// Get the image's width
124 //
125 /// @return The image's width in pixels.
width()126 size_t width() const {
127 return _width;
128 }
129
130 /// Get the image's width
131 //
132 /// @return The image's height in pixels.
height()133 size_t height() const {
134 return _height;
135 }
136
137 /// Copy image data from a buffer.
138 //
139 /// Note that this buffer MUST have the same rowstride and type, or
140 /// unexpected things will happen. In general, it is only safe to copy
141 /// from another GnashImage or unexpected things will happen.
142 ///
143 /// @param data buffer to copy data from.
144 void update(const_iterator data);
145
146 /// Copy image data from another image data
147 //
148 /// Note that this buffer must have the same rowstride and type
149 ///
150 /// @param from image to copy data from.
151 void update(const GnashImage& from);
152
153 /// Access the raw data.
begin()154 virtual iterator begin() {
155 return _data.get();
156 }
157
158 /// Access the raw data
begin()159 virtual const_iterator begin() const {
160 return _data.get();
161 }
162
163 /// An iterator to the end of the data.
end()164 iterator end() {
165 return begin() + size();
166 }
167
168 /// An iterator to the end of the data.
end()169 const_iterator end() const {
170 return begin() + size();
171 }
172
173 protected:
174
175 /// Construct a GnashImage from a data buffer, taking ownership of the data.
176 //
177 /// @param data The raw image data. This class takes ownership.
178 /// @param width The width of the image in pixels.
179 /// @param height The height of the image in pixels.
180 /// @param pitch The pitch (rowstride) of the image in bytes.
181 /// @param type The ImageType of the image.
182 GnashImage(iterator data, size_t width, size_t height, ImageType type,
183 ImageLocation location = GNASH_IMAGE_CPU);
184
185 /// Construct an empty GnashImage
186 //
187 /// Note: there is an arbitrary limit of std::int32_t::max bytes for the
188 /// total size of the bitmap constructed with this constructor.
189 //
190 /// @param width The width of the image in pixels.
191 /// @param height The height of the image in pixels.
192 /// @param type The ImageType of the image.
193 GnashImage(size_t width, size_t height, ImageType type,
194 ImageLocation location = GNASH_IMAGE_CPU);
195
196 /// The type of the image: RGBA or RGB.
197 const ImageType _type;
198
199 /// Image data location (CPU or GPU)
200 const ImageLocation _location;
201
202 /// Width of image, in pixels
203 const size_t _width;
204
205 /// Height of image, in pixels
206 const size_t _height;
207
208 /// Data if held in this class
209 container_type _data;
210
211 };
212
213 /// 24-bit RGB bitmap
214 //
215 /// Channels are in RGB order.
216 class DSOEXPORT ImageRGB : public GnashImage
217 {
218 public:
219
220 /// Create an empty RGB image with uninitialized data.
221 ImageRGB(size_t width, size_t height);
222
223 /// Create an ImageRGB taking ownership of the data.
ImageRGB(iterator data,size_t width,size_t height)224 ImageRGB(iterator data, size_t width, size_t height)
225 :
226 GnashImage(data, width, height, TYPE_RGB)
227 {}
228
229 virtual ~ImageRGB();
230 };
231
232 /// 32-bit RGBA bitmap
233 //
234 /// Channels are in RGBA order.
235 class DSOEXPORT ImageRGBA : public GnashImage
236 {
237
238 public:
239
240 /// Create an empty RGB image with uninitialized data.
241 ImageRGBA(size_t width, size_t height);
242
ImageRGBA(iterator data,size_t width,size_t height)243 ImageRGBA(iterator data, size_t width, size_t height)
244 :
245 GnashImage(data, width, height, TYPE_RGBA)
246 {}
247
248 ~ImageRGBA();
249
250 /// Set pixel value
251 //
252 /// TODO: move in base class ?
253 ///
254 void setPixel(size_t x, size_t y, value_type r, value_type g, value_type b,
255 value_type a);
256 };
257
258 /// The base class for reading image data.
259 class Input : boost::noncopyable
260 {
261 public:
262
263 /// Construct an Input object to read from an IOChannel.
264 //
265 /// @param in The stream to read data from. Ownership is shared
266 /// between caller and Input, so it is freed
267 /// automatically when the last owner is destroyed.
Input(std::shared_ptr<IOChannel> in)268 Input(std::shared_ptr<IOChannel> in)
269 :
270 _inStream(in),
271 _type(GNASH_IMAGE_INVALID)
272 {}
273
~Input()274 virtual ~Input() {}
275
276 /// Begin processing the image data.
277 virtual void read() = 0;
278
279 /// Get the image's height in pixels.
280 //
281 /// @return The height of the image in pixels.
282 virtual size_t getHeight() const = 0;
283
284 /// Get the image's width in pixels.
285 //
286 /// @return The width of the image in pixels.
287 virtual size_t getWidth() const = 0;
288
289 /// Get number of components (channels)
290 //
291 /// @return The number of components, e.g. 3 for RGB
292 virtual size_t getComponents() const = 0;
293
294 /// Read a scanline's worth of image data into the given buffer.
295 //
296 /// @param rgbData The buffer for writing raw RGB data to.
297 virtual void readScanline(unsigned char* rgbData) = 0;
298
299 /// Get the ImageType of the image.
300 //
301 /// @return The type of the image. This is GNASH_IMAGE_INVALID
302 /// at least until read() has been called and reads some
303 /// valid data.
imageType()304 ImageType imageType() { return _type; }
305
306 /// \brief
307 /// For reading SWF JPEG3-style image data, like ordinary JPEG,
308 /// but stores the data in ImageRGBA format.
309 DSOEXPORT static std::unique_ptr<ImageRGBA> readSWFJpeg3(
310 std::shared_ptr<gnash::IOChannel> in);
311
312 /// Read image data from an IOChannel into an GnashImage.
313 //
314 /// @param in The IOChannel to read the image from.
315 /// @param type The type of image to read.
316 /// @return An GnashImage with the read image data. If type
317 /// is an unsupported FileType or image reading fails,
318 /// a NULL unique_ptr is returned.
319 DSOEXPORT static std::unique_ptr<GnashImage> readImageData(
320 std::shared_ptr<gnash::IOChannel> in, FileType type);
321
322 protected:
323
324 std::shared_ptr<IOChannel> _inStream;
325
326 ImageType _type;
327
328 };
329
330 // Base class for writing image data.
331 class Output : boost::noncopyable
332 {
333
334 public:
335
336 /// Construct an Output for writing to an IOChannel
337 //
338 /// @param out The gnash::IOChannel to write the image to. Ownership
339 /// is shared.
340 /// @param width The width of the resulting image
341 /// @param height The height of the resulting image.
Output(std::shared_ptr<IOChannel> out,size_t width,size_t height)342 Output(std::shared_ptr<IOChannel> out, size_t width, size_t height)
343 :
344 _width(width),
345 _height(height),
346 _outStream(out)
347 {}
348
~Output()349 virtual ~Output() {}
350
351 /// Write RGB image data using the parameters supplied at construction.
352 //
353 /// @param rgbData The raw RGB image data to write as an image.
354 virtual void writeImageRGB(const unsigned char* rgbData) = 0;
355
356 /// Write RGBA image data using the parameters supplied at construction.
357 //
358 /// @param rgbaData The raw RGBA image data to write as an image.
writeImageRGBA(const unsigned char *)359 virtual void writeImageRGBA(const unsigned char* /*rgbaData*/)
360 {
361 log_error(_("This image format does not support writing RGBA images"));
362 }
363
364 /// Write the given image to the given IOChannel in a specified format.
365 //
366 /// @param type The image format to write in (see GnashEnums.h)
367 /// @param out The IOChannel to write to.
368 /// @param image The image to write.
369 /// @param quality The quality of the image output, from 0..100. Values
370 /// outside this range will be clamped to the minimum or
371 /// maxium value. The quality is not used for all
372 /// formats.
373 DSOEXPORT static void writeImageData(FileType type,
374 std::shared_ptr<gnash::IOChannel> out, const GnashImage& image,
375 int quality);
376
377 protected:
378
379 const size_t _width;
380
381 const size_t _height;
382
383 std::shared_ptr<IOChannel> _outStream;
384
385 };
386
387 /// Get a pointer to a given row of any image.
388 //
389 /// @param row The index of the required row.
390 /// @return A pointer to the first byte of the specified row.
391 inline GnashImage::iterator
scanline(GnashImage & im,size_t row)392 scanline(GnashImage& im, size_t row)
393 {
394 assert(row < im.height());
395 return im.begin() + im.stride() * row;
396 }
397
398 /// Get a read-only pointer to a given row of any image.
399 //
400 /// @param y The index of the required row.
401 /// @return A read-only pointer to the first byte of the specified row.
402 inline GnashImage::const_iterator
scanline(const GnashImage & im,size_t row)403 scanline(const GnashImage& im, size_t row)
404 {
405 assert(row < im.height());
406 return im.begin() + im.stride() * row;
407 }
408
409 DSOEXPORT void mergeAlpha(ImageRGBA& im, GnashImage::const_iterator alphaData,
410 const size_t bufferLength);
411
412 } // namespace image
413 } // namespace gnash
414
415 #endif
416