[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] /srv/bzr/gnash/trunk r9577: Provide a unified image-writi
From: |
Benjamin Wolsey |
Subject: |
[Gnash-commit] /srv/bzr/gnash/trunk r9577: Provide a unified image-writing interface: ImageOutput. Bring JPEG writing |
Date: |
Mon, 11 Aug 2008 19:14:52 +0200 |
User-agent: |
Bazaar (1.5) |
------------------------------------------------------------
revno: 9577
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Mon 2008-08-11 19:14:52 +0200
message:
Provide a unified image-writing interface: ImageOutput. Bring JPEG writing
under this structure and implement PNG writing. I see no point in
implementing GIF writing.
There are no users of these yet. They will write any valid image_base
(presently just image::rgb) to the provided IOChannel.
modified:
libbase/GnashImage.h
libbase/GnashImageJpeg.cpp
libbase/GnashImageJpeg.h
libbase/GnashImagePng.cpp
libbase/GnashImagePng.h
libbase/image.cpp
libbase/image.h
------------------------------------------------------------
revno: 9575.1.3
committer: Benjamin Wolsey <address@hidden>
branch nick: work
timestamp: Mon 2008-08-11 10:09:17 +0200
message:
Make an ImageOutput base class; JpegImageOutput is a subclass of it.
It's not used, so no idea if it works.
modified:
libbase/GnashImage.h
libbase/GnashImageJpeg.cpp
libbase/GnashImageJpeg.h
libbase/image.cpp
------------------------------------------------------------
revno: 9575.1.4
committer: Benjamin Wolsey <address@hidden>
branch nick: work
timestamp: Mon 2008-08-11 10:22:38 +0200
message:
Replace write_jpeg with generic writeImageData().
modified:
libbase/image.cpp
libbase/image.h
------------------------------------------------------------
revno: 9575.1.5
committer: Benjamin Wolsey <address@hidden>
branch nick: work
timestamp: Mon 2008-08-11 12:56:22 +0200
message:
ImageOutput handles writing a whole image, not just line by line.
Take an image_base for writeImageData so we can handle rgba data
in future. Constructing an image::image_base object from raw data
requires a memcpy, so a method taking raw data may be useful
(though users are free to construct their own ImageOutput objects
directly).
modified:
libbase/GnashImage.h
libbase/GnashImageJpeg.cpp
libbase/GnashImageJpeg.h
libbase/image.cpp
libbase/image.h
------------------------------------------------------------
revno: 9575.1.6
committer: Benjamin Wolsey <address@hidden>
branch nick: work
timestamp: Mon 2008-08-11 18:42:50 +0200
message:
Implement writing RGB PNG files. Take shared_ptr to IOChannel so that the
ImageOutput class keeps the data for as long as might be necessary.
modified:
libbase/GnashImage.h
libbase/GnashImageJpeg.cpp
libbase/GnashImageJpeg.h
libbase/GnashImagePng.cpp
libbase/GnashImagePng.h
libbase/image.cpp
libbase/image.h
=== modified file 'libbase/GnashImage.h'
--- a/libbase/GnashImage.h 2008-08-06 16:24:10 +0000
+++ b/libbase/GnashImage.h 2008-08-11 16:42:50 +0000
@@ -71,6 +71,31 @@
};
+class ImageOutput
+{
+
+public:
+
+ ImageOutput(boost::shared_ptr<IOChannel> out, size_t width, size_t height)
:
+ _width(width),
+ _height(height),
+ _outStream(out)
+ {}
+
+ virtual ~ImageOutput() {}
+
+ virtual void writeImageRGB(unsigned char* rgbData) = 0;
+
+protected:
+
+ const size_t _width;
+
+ const size_t _height;
+
+ boost::shared_ptr<IOChannel> _outStream;
+
+};
+
} // namespace gnash
=== modified file 'libbase/GnashImageJpeg.cpp'
--- a/libbase/GnashImageJpeg.cpp 2008-08-06 19:25:21 +0000
+++ b/libbase/GnashImageJpeg.cpp 2008-08-11 16:42:50 +0000
@@ -530,61 +530,46 @@
};
-
-
-
-
-// Basically this is a thin wrapper around jpeg_compress
-// object.
-class output_IOChannel : public JpegImageOutput
+JpegImageOutput::JpegImageOutput(boost::shared_ptr<IOChannel> out, size_t
width, size_t height, int quality)
+ :
+ ImageOutput(out, width, height)
{
-public:
- // State needed for output.
- jpeg_compress_struct m_cinfo;
- jpeg_error_mgr m_jerr;
-
- /// Constructor.
- //
- /// Read the header data from in, and
- /// prepare to read data.
- output_IOChannel(gnash::IOChannel& out, int width, int height, int
quality)
- {
m_cinfo.err = jpeg_std_error(&m_jerr);
// Initialize decompression object.
jpeg_create_compress(&m_cinfo);
- rw_dest_IOChannel::setup(&m_cinfo, out);
- m_cinfo.image_width = width;
- m_cinfo.image_height = height;
+ rw_dest_IOChannel::setup(&m_cinfo, *_outStream);
+ m_cinfo.image_width = _width;
+ m_cinfo.image_height = _height;
m_cinfo.input_components = 3;
m_cinfo.in_color_space = JCS_RGB;
jpeg_set_defaults(&m_cinfo);
jpeg_set_quality(&m_cinfo, quality, TRUE);
jpeg_start_compress(&m_cinfo, TRUE);
- }
-
-
- ~output_IOChannel()
- // Destructor. Clean up our jpeg reader state.
- {
+}
+
+
+JpegImageOutput::~JpegImageOutput()
+{
jpeg_finish_compress(&m_cinfo);
-/*
- rw_dest_IOChannel* src = (rw_source_IOChannel*) m_cinfo.dest;
- delete dest;
- m_cinfo.dest = NULL;
-*/
jpeg_destroy_compress(&m_cinfo);
- }
-
-
- void write_scanline(unsigned char* rgb_data)
- // Write out a single scanline.
- {
- jpeg_write_scanlines(&m_cinfo, &rgb_data, 1);
- }
-};
+}
+
+
+void
+JpegImageOutput::writeImageRGB(unsigned char* rgbData)
+{
+ // RGB...
+ const size_t components = 3;
+
+ for (size_t y = 0; y < _height; ++y)
+ {
+ unsigned char* ypos = &rgbData[y * _width * components];
+ jpeg_write_scanlines(&m_cinfo, &ypos, 1);
+ }
+}
void
@@ -596,11 +581,11 @@
}
-/*static*/
-JpegImageOutput*
-JpegImageOutput::create(gnash::IOChannel* in, int width, int height, int
quality)
+std::auto_ptr<ImageOutput>
+JpegImageOutput::create(boost::shared_ptr<IOChannel> out, size_t width, size_t
height, int quality)
{
- return new output_IOChannel(*in, width, height, quality);
+ std::auto_ptr<ImageOutput> outChannel(new JpegImageOutput(out, width,
height, quality));
+ return outChannel;
}
} // namespace gnash
=== modified file 'libbase/GnashImageJpeg.h'
--- a/libbase/GnashImageJpeg.h 2008-08-06 19:25:21 +0000
+++ b/libbase/GnashImageJpeg.h 2008-08-11 16:42:50 +0000
@@ -52,7 +52,7 @@
namespace gnash
{
/// Bascially this is a thin wrapper around jpeg_decompress object.
-class JpegImageInput : public gnash::ImageInput
+class JpegImageInput : public ImageInput
{
private:
@@ -142,20 +142,29 @@
};
// Helper object for writing jpeg image data.
-class JpegImageOutput
+class JpegImageOutput : public ImageOutput
{
+
public:
+
/// Create an output object bount to a gnash::IOChannel
//
/// @param quality
/// Quality goes from 1-100.
///
- DSOEXPORT static JpegImageOutput* create(gnash::IOChannel* out,
int width, int height, int quality);
-
- virtual ~JpegImageOutput() {}
-
- // ...
- virtual void write_scanline(unsigned char* rgb_data) = 0;
+ JpegImageOutput(boost::shared_ptr<IOChannel> out, size_t width, size_t
height, int quality);
+
+ ~JpegImageOutput();
+
+ void writeImageRGB(unsigned char* rgbData);
+
+ DSOEXPORT static std::auto_ptr<ImageOutput>
create(boost::shared_ptr<IOChannel> out, size_t width, size_t height, int
quality);
+
+private:
+
+ jpeg::jpeg_compress_struct m_cinfo;
+ jpeg::jpeg_error_mgr m_jerr;
+
};
} // namespace gnash
=== modified file 'libbase/GnashImagePng.cpp'
--- a/libbase/GnashImagePng.cpp 2008-08-06 16:24:10 +0000
+++ b/libbase/GnashImagePng.cpp 2008-08-11 16:42:50 +0000
@@ -25,6 +25,7 @@
#include <sstream>
#include <cstring> // std::memcpy
+#include <boost/scoped_array.hpp>
namespace gnash {
@@ -46,16 +47,30 @@
readData(png_structp pngptr, png_bytep data, png_size_t length)
{
// Do not call unless the PNG exists.
- assert (pngptr);
+ assert(pngptr);
IOChannel* in = reinterpret_cast<IOChannel*>(png_get_io_ptr(pngptr));
in->read(reinterpret_cast<char*>(data), length);
}
+static void
+writeData(png_structp pngptr, png_bytep data, png_size_t length)
+{
+ // Do not call unless the PNG exists.
+ assert(pngptr);
+ IOChannel* out = reinterpret_cast<IOChannel*>(png_get_io_ptr(pngptr));
+ out->write(reinterpret_cast<char*>(data), length);
+}
+
+static void
+flushData(png_structp /*pngptr*/)
+{
+
+}
+
PngImageInput::PngImageInput(boost::shared_ptr<IOChannel> in) :
ImageInput(in),
_pngPtr(0),
- _infoPtr(0),
- _currentRow(0)
+ _infoPtr(0)
{
init();
}
@@ -80,11 +95,11 @@
}
void
-PngImageInput::readScanline(unsigned char* rgb_data)
+PngImageInput::readScanline(unsigned char* rgbData)
{
assert (_currentRow < getHeight());
png_bytepp row_pointers = png_get_rows(_pngPtr, _infoPtr);
- std::memcpy(rgb_data, row_pointers[_currentRow], getWidth() *
getComponents());
+ std::memcpy(rgbData, row_pointers[_currentRow], getWidth() *
getComponents());
++_currentRow;
}
@@ -116,6 +131,77 @@
png_read_png(_pngPtr, _infoPtr, PNG_TRANSFORM_STRIP_ALPHA, NULL);
}
+///
+/// PNG output
+///
+
+PngImageOutput::PngImageOutput(boost::shared_ptr<IOChannel> out, size_t width,
size_t height, int quality)
+ :
+ ImageOutput(out, width, height),
+ _pngPtr(0),
+ _infoPtr(0)
+{
+ init();
+}
+
+
+PngImageOutput::~PngImageOutput()
+{
+ png_destroy_write_struct(&_pngPtr, &_infoPtr);
+}
+
+
+void
+PngImageOutput::init()
+{
+ // Initialize png library.
+ _pngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
+ NULL, &error, &warning);
+ if (!_pngPtr) return;
+
+ _infoPtr = png_create_info_struct(_pngPtr);
+
+ if (!_infoPtr)
+ {
+ png_destroy_write_struct(&_pngPtr, (png_infopp)NULL);
+ return;
+ }
+}
+
+
+void
+PngImageOutput::writeImageRGB(unsigned char* rgbData)
+{
+ png_set_write_fn(_pngPtr, _outStream.get(), &writeData, &flushData);
+
+ boost::scoped_array<png_bytep> rows(new png_bytep[_height]);
+
+ // RGB
+ const size_t components = 3;
+
+ for (size_t y = 0; y < _height; ++y)
+ {
+ rows[y] = rgbData + _width * y * components;
+ }
+
+ png_set_rows(_pngPtr, _infoPtr, rows.get());
+
+ png_set_IHDR(_pngPtr, _infoPtr, _width, _height,
+ 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+
+ png_write_png(_pngPtr, _infoPtr, PNG_TRANSFORM_IDENTITY, NULL);
+}
+
+
+std::auto_ptr<ImageOutput>
+PngImageOutput::create(boost::shared_ptr<IOChannel> out, size_t width, size_t
height, int quality)
+{
+ std::auto_ptr<ImageOutput> outChannel(new PngImageOutput(out, width,
height, quality));
+ return outChannel;
+}
+
+
} // namespace gnash
// Local Variables:
=== modified file 'libbase/GnashImagePng.h'
--- a/libbase/GnashImagePng.h 2008-08-06 16:24:10 +0000
+++ b/libbase/GnashImagePng.h 2008-08-11 16:42:50 +0000
@@ -35,58 +35,89 @@
namespace gnash {
- class PngImageInput : public ImageInput
- {
- private:
- // State needed for input.
- png_structp _pngPtr;
- png_infop _infoPtr;
-
- // A counter for keeping track of the last row copied.
- size_t _currentRow;
-
- void init();
-
- public:
-
- /// Constructor.
- //
- /// @param in
- /// The stream to read from.
- PngImageInput(boost::shared_ptr<IOChannel> in);
-
- // Destructor. Free libpng-allocated memory.
- ~PngImageInput();
-
- void read();
-
- // Return the height of the image.
- size_t getHeight() const;
-
- // Return the width of the image.
- size_t getWidth() const;
-
- // Return number of components (i.e. == 3 for RGB
- // data). The size of the data for a scanline is
- // get_width() * get_components().
- //
- int getComponents() const { return 3; }
-
- // Read a scanline's worth of image data into the
- // given buffer. The amount of data read is
- // get_width() * get_components().
- //
- void readScanline(unsigned char* rgb_data);
-
-
- DSOEXPORT static std::auto_ptr<ImageInput>
create(boost::shared_ptr<IOChannel> in)
- {
- std::auto_ptr<ImageInput> ret ( new PngImageInput(in) );
- if ( ret.get() ) ret->read();
- return ret;
- }
-
- };
+class PngImageInput : public ImageInput
+{
+
+private:
+ // State needed for input.
+ png_structp _pngPtr;
+ png_infop _infoPtr;
+
+ // A counter for keeping track of the last row copied.
+ size_t _currentRow;
+
+ void init();
+
+public:
+
+ /// Constructor.
+ //
+ /// @param in
+ /// The stream to read from.
+ PngImageInput(boost::shared_ptr<IOChannel> in);
+
+ // Destructor. Free libpng-allocated memory.
+ ~PngImageInput();
+
+ void read();
+
+ // Return the height of the image.
+ size_t getHeight() const;
+
+ // Return the width of the image.
+ size_t getWidth() const;
+
+ // Return number of components (i.e. == 3 for RGB
+ // data). The size of the data for a scanline is
+ // get_width() * get_components().
+ //
+ int getComponents() const { return 3; }
+
+ // Read a scanline's worth of image data into the
+ // given buffer. The amount of data read is
+ // get_width() * get_components().
+ //
+ void readScanline(unsigned char* rgb_data);
+
+
+ DSOEXPORT static std::auto_ptr<ImageInput>
create(boost::shared_ptr<IOChannel> in)
+ {
+ std::auto_ptr<ImageInput> ret ( new PngImageInput(in) );
+ if ( ret.get() ) ret->read();
+ return ret;
+ }
+
+};
+
+// Helper object for writing jpeg image data.
+class PngImageOutput : public ImageOutput
+{
+
+public:
+
+ /// Create an output object bount to a gnash::IOChannel
+ //
+ /// @param out The IOChannel used for output. Must be kept alive
throughout
+ ///
+ /// @param quality Unused in PNG output
+
+ PngImageOutput(boost::shared_ptr<IOChannel> out, size_t width, size_t
height, int quality);
+
+ ~PngImageOutput();
+
+ void writeImageRGB(unsigned char* rgbData);
+
+ DSOEXPORT static std::auto_ptr<ImageOutput>
create(boost::shared_ptr<IOChannel> out, size_t width, size_t height, int
quality);
+
+private:
+
+ void init();
+
+ /// Libpng structures for image and output state.
+ png_structp _pngPtr;
+ png_infop _infoPtr;
+
+};
} // namespace gnash
=== modified file 'libbase/image.cpp'
--- a/libbase/image.cpp 2008-08-07 08:08:28 +0000
+++ b/libbase/image.cpp 2008-08-11 16:42:50 +0000
@@ -17,6 +17,7 @@
#include "GnashImageGif.h"
#include "GnashImageJpeg.h"
#include "IOChannel.h"
+#include "log.h"
namespace gnash
{
@@ -186,49 +187,66 @@
// utility
//
-
// Write the given image to the given out stream, in jpeg format.
- void write_jpeg(gnash::IOChannel* out, rgb* image, int quality)
+ void writeImageData(FileType type, boost::shared_ptr<IOChannel> out,
image::image_base* image, int quality)
{
- size_t height = image->height();
-
- std::auto_ptr<JpegImageOutput> j_out (
JpegImageOutput::create(out, image->width(), height, quality) );
-
- for (size_t y = 0; y < height; ++y)
- {
- j_out->write_scanline(image->scanline(y));
- }
-
+ image::rgb* im = dynamic_cast<image::rgb*>(image);
+
+ // We only handle rgb data at the moment.
+ assert(im);
+
+ const size_t width = im->width();
+ const size_t height = im->height();
+
+ std::auto_ptr<ImageOutput> outChannel;
+
+ switch (type)
+ {
+ case GNASH_FILETYPE_PNG:
+ outChannel = PngImageOutput::create(out, width, height,
quality);
+ break;
+ case GNASH_FILETYPE_JPEG:
+ outChannel = JpegImageOutput::create(out, width, height,
quality);
+ break;
+ default:
+ log_error("Requested to write image as unsupported filetype");
+ break;
+ }
+
+ outChannel->writeImageRGB(im->data());
}
// See gnash.h for file types.
std::auto_ptr<rgb> readImageData(boost::shared_ptr<IOChannel> in, FileType
type)
{
std::auto_ptr<rgb> im (NULL);
- std::auto_ptr<ImageInput> infile;
+ std::auto_ptr<ImageInput> inChannel;
switch (type)
{
case GNASH_FILETYPE_PNG:
- infile = PngImageInput::create(in);
+ inChannel = PngImageInput::create(in);
break;
case GNASH_FILETYPE_GIF:
- infile = GifImageInput::create(in);
+ inChannel = GifImageInput::create(in);
break;
case GNASH_FILETYPE_JPEG:
- infile = JpegImageInput::create(in);
+ inChannel = JpegImageInput::create(in);
break;
default:
break;
}
- if (!infile.get()) return im;
-
- im.reset(new image::rgb(infile->getWidth(), infile->getHeight()));
-
- for (size_t i = 0, e = infile->getHeight(); i < e; ++i)
+ if (!inChannel.get()) return im;
+
+ const size_t height = inChannel->getHeight();
+ const size_t width = inChannel->getWidth();
+
+ im.reset(new image::rgb(width, height));
+
+ for (size_t i = 0; i < height; ++i)
{
- infile->readScanline(im->scanline(i));
+ inChannel->readScanline(im->scanline(i));
}
return im;
}
=== modified file 'libbase/image.h'
--- a/libbase/image.h 2008-08-07 08:08:28 +0000
+++ b/libbase/image.h 2008-08-11 16:42:50 +0000
@@ -228,8 +228,14 @@
};
- /// Write the given image to the given out stream, in jpeg format.
- DSOEXPORT void write_jpeg(boost::shared_ptr<gnash::IOChannel> out,
rgb* image, int quality);
+ /// Write the given image to the given out channel in a specified
format.
+ //
+ /// @param type The image format to write in (see libcore/gnash.h)
+ /// @param out The IOChannel to write to.
+ /// @param image The image to write.
+ /// @param quality The quality of the image output (not used for all
formats)
+ DSOEXPORT void writeImageData(FileType type,
boost::shared_ptr<gnash::IOChannel> out,
+ image_base* image, int quality);
/// \brief
/// For reading SWF JPEG2-style image data, using pre-loaded
- [Gnash-commit] /srv/bzr/gnash/trunk r9577: Provide a unified image-writing interface: ImageOutput. Bring JPEG writing,
Benjamin Wolsey <=