00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef GNASH_GNASHIMAGE_H
00025 #define GNASH_GNASHIMAGE_H
00026
00027 #include <boost/shared_ptr.hpp>
00028 #include <boost/noncopyable.hpp>
00029 #include <boost/cstdint.hpp>
00030 #include <boost/scoped_array.hpp>
00031 #include <memory>
00032 #include <boost/iterator/iterator_facade.hpp>
00033 #include <iterator>
00034
00035 #include "FileTypes.h"
00036 #include "log.h"
00037 #include "dsodefs.h"
00038
00039
00040 namespace gnash {
00041 class IOChannel;
00042 class JpegImageInput;
00043 }
00044
00045 namespace gnash {
00046
00048 enum ImageType
00049 {
00050 GNASH_IMAGE_INVALID,
00051 GNASH_IMAGE_RGB,
00052 GNASH_IMAGE_RGBA
00053 };
00054
00056 enum ImageLocation
00057 {
00058 GNASH_IMAGE_CPU = 1,
00059 GNASH_IMAGE_GPU
00060 };
00061
00062 inline size_t
00063 numChannels(ImageType t)
00064 {
00065 switch (t) {
00066 case GNASH_IMAGE_RGBA:
00067 return 4;
00068 case GNASH_IMAGE_RGB:
00069 return 3;
00070 default:
00071 std::abort();
00072 }
00073 }
00074
00075 template<typename Iterator>
00076 class ARGB
00077 {
00078 public:
00079
00080 ARGB(Iterator i, ImageType t)
00081 :
00082 _it(i),
00083 _t(t)
00084 {}
00085
00087
00089 ARGB& operator=(boost::uint32_t pixel) {
00090 switch (_t) {
00091 case GNASH_IMAGE_RGBA:
00092
00093 *(_it + 3) = (pixel & 0xff000000) >> 24;
00094 case GNASH_IMAGE_RGB:
00095 *_it = (pixel & 0x00ff0000) >> 16;
00096 *(_it + 1) = (pixel & 0x0000ff00) >> 8;
00097 *(_it + 2) = (pixel & 0x000000ff);
00098 default:
00099 break;
00100 }
00101 return *this;
00102 }
00103
00104 private:
00105 Iterator _it;
00106 ImageType _t;
00107 };
00108
00109 template<typename Iterator, typename Pixel>
00110 struct pixel_iterator : public boost::iterator_facade<
00111 pixel_iterator<Iterator, Pixel>,
00112 boost::uint32_t,
00113 std::random_access_iterator_tag,
00114 Pixel>
00115 {
00116
00117 typedef std::ptrdiff_t difference_type;
00118
00119 pixel_iterator(Iterator it, ImageType t)
00120 :
00121 _it(it),
00122 _t(t)
00123 {}
00124
00125 boost::uint32_t toARGB() const {
00126 boost::uint32_t ret = 0xff000000;
00127 switch (_t) {
00128 case GNASH_IMAGE_RGBA:
00129
00130 ret = *(_it + 3) << 24;
00131 case GNASH_IMAGE_RGB:
00132 ret |= (*_it << 16 | *(_it + 1) << 8 | *(_it + 2));
00133 default:
00134 break;
00135 }
00136 return ret;
00137 }
00138
00139 private:
00140
00141 friend class boost::iterator_core_access;
00142
00143 Pixel dereference() const {
00144 return Pixel(_it, _t);
00145 }
00146
00147 void increment() {
00148 _it += numChannels(_t);
00149 }
00150
00151 bool equal(const pixel_iterator& o) const {
00152 return o._it == _it;
00153 }
00154
00155 difference_type distance_to(const pixel_iterator& o) const {
00156 return (o._it - _it) / numChannels(_t);
00157 }
00158
00159 void advance(difference_type n) {
00160 _it += n * numChannels(_t);
00161 }
00162
00163 Iterator _it;
00164 ImageType _t;
00165 };
00166
00168
00171 class DSOEXPORT GnashImage : boost::noncopyable
00172 {
00173 public:
00174
00175 typedef boost::uint8_t value_type;
00176 typedef boost::scoped_array<value_type> container_type;
00177 typedef value_type* iterator;
00178 typedef const value_type* const_iterator;
00179
00180 typedef pixel_iterator<iterator, ARGB<iterator> > argb_iterator;
00181
00182 virtual ~GnashImage() {}
00183
00185
00187 ImageType type() const {
00188 return _type;
00189 }
00190
00192
00194 ImageLocation location() const {
00195 return _location;
00196 }
00197
00199
00201 size_t size() const {
00202 return stride() * _height;
00203 }
00204
00206
00208 virtual size_t stride() const {
00209 return _width * channels();
00210 }
00211
00213
00215 size_t channels() const {
00216 return numChannels(_type);
00217 }
00218
00220
00222 size_t width() const {
00223 return _width;
00224 }
00225
00227
00229 size_t height() const {
00230 return _height;
00231 }
00232
00234
00240 void update(const_iterator data);
00241
00243
00247 void update(const GnashImage& from);
00248
00250 virtual iterator begin() {
00251 return _data.get();
00252 }
00253
00255 virtual const_iterator begin() const {
00256 return _data.get();
00257 }
00258
00260 iterator end() {
00261 return begin() + size();
00262 }
00263
00265 const_iterator end() const {
00266 return begin() + size();
00267 }
00268
00270 argb_iterator argb_begin() {
00271 return argb_iterator(begin(), _type);
00272 }
00273
00275 argb_iterator argb_end() {
00276 return argb_iterator(end(), _type);
00277 }
00278
00279 protected:
00280
00282
00288 GnashImage(iterator data, size_t width, size_t height, ImageType type,
00289 ImageLocation location = GNASH_IMAGE_CPU);
00290
00292
00295
00299 GnashImage(size_t width, size_t height, ImageType type,
00300 ImageLocation location = GNASH_IMAGE_CPU);
00301
00302
00304 const ImageType _type;
00305
00307 const ImageLocation _location;
00308
00310 const size_t _width;
00311
00313 const size_t _height;
00314
00316 container_type _data;
00317
00318 };
00319
00321
00323 class DSOEXPORT ImageRGB : public GnashImage
00324 {
00325 public:
00326
00328 ImageRGB(size_t width, size_t height);
00329
00331 ImageRGB(iterator data, size_t width, size_t height)
00332 :
00333 GnashImage(data, width, height, GNASH_IMAGE_RGB)
00334 {}
00335
00336 virtual ~ImageRGB();
00337 };
00338
00340
00342 class DSOEXPORT ImageRGBA : public GnashImage
00343 {
00344
00345 public:
00346
00348 ImageRGBA(size_t width, size_t height);
00349
00350 ImageRGBA(iterator data, size_t width, size_t height)
00351 :
00352 GnashImage(data, width, height, GNASH_IMAGE_RGBA)
00353 {}
00354
00355 ~ImageRGBA();
00356
00358
00361 void setPixel(size_t x, size_t y, value_type r, value_type g, value_type b,
00362 value_type a);
00363
00364 void mergeAlpha(const_iterator alphaData, const size_t bufferLength);
00365
00366 };
00367
00369 class ImageInput : boost::noncopyable
00370 {
00371 public:
00372
00374
00378 ImageInput(boost::shared_ptr<IOChannel> in)
00379 :
00380 _inStream(in),
00381 _type(GNASH_IMAGE_INVALID)
00382 {}
00383
00384 virtual ~ImageInput() {}
00385
00387 virtual void read() = 0;
00388
00390
00392 virtual size_t getHeight() const = 0;
00393
00395
00397 virtual size_t getWidth() const = 0;
00398
00400
00402 virtual size_t getComponents() const = 0;
00403
00405
00407 virtual void readScanline(unsigned char* rgbData) = 0;
00408
00410
00414 ImageType imageType() { return _type; }
00415
00419 DSOEXPORT static std::auto_ptr<ImageRGBA> readSWFJpeg3(
00420 boost::shared_ptr<gnash::IOChannel> in);
00421
00423
00429 DSOEXPORT static std::auto_ptr<GnashImage> readImageData(
00430 boost::shared_ptr<gnash::IOChannel> in, FileType type);
00431
00432 protected:
00433
00434 boost::shared_ptr<IOChannel> _inStream;
00435
00436 ImageType _type;
00437
00438 };
00439
00440
00441 class ImageOutput : boost::noncopyable
00442 {
00443
00444 public:
00445
00447
00452 ImageOutput(boost::shared_ptr<IOChannel> out, size_t width, size_t height)
00453 :
00454 _width(width),
00455 _height(height),
00456 _outStream(out)
00457 {}
00458
00459 virtual ~ImageOutput() {}
00460
00462
00464 virtual void writeImageRGB(const unsigned char* rgbData) = 0;
00465
00467
00469 virtual void writeImageRGBA(const unsigned char* )
00470 {
00471 log_error(_("This image format does not support writing RGBA images"));
00472 }
00473
00475
00481 DSOEXPORT static void writeImageData(FileType type,
00482 boost::shared_ptr<gnash::IOChannel> out, const GnashImage& image,
00483 int quality);
00484
00485 protected:
00486
00487 const size_t _width;
00488
00489 const size_t _height;
00490
00491 boost::shared_ptr<IOChannel> _outStream;
00492
00493 };
00494
00496
00499 inline GnashImage::iterator
00500 scanline(GnashImage& im, size_t row)
00501 {
00502 assert(row < im.height());
00503 return im.begin() + im.stride() * row;
00504 }
00505
00507
00510 inline GnashImage::const_iterator
00511 scanline(const GnashImage& im, size_t row)
00512 {
00513 assert(row < im.height());
00514 return im.begin() + im.stride() * row;
00515 }
00516
00517 }
00518
00519 #endif