gnash-commit
[Top][All Lists]
Advanced

[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


reply via email to

[Prev in Thread] Current Thread [Next in Thread]