libcvd-members
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[libcvd-members] libcvd pnm_src/png.cc cvd_src/image_io.cc cvd/i...


From: Edward Rosten
Subject: [libcvd-members] libcvd pnm_src/png.cc cvd_src/image_io.cc cvd/i...
Date: Fri, 29 Sep 2006 21:40:28 +0000

CVSROOT:        /cvsroot/libcvd
Module name:    libcvd
Changes by:     Edward Rosten <edrosten>        06/09/29 21:40:28

Modified files:
        pnm_src        : png.cc 
        cvd_src        : image_io.cc 
        cvd            : image_io.h 
        cvd/internal/io: png.h 

Log message:
        PNG write support.
        
        Tested with 8 bit and 1 bit PNGs only.  Native support for 1, 8, 16, 24 
and 
        48 bit images.
        
        Note that PNG code is SubImage ready (ie it uses subimages, but the rest
        of the load/save functions do not yet).

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/libcvd/pnm_src/png.cc?cvsroot=libcvd&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/libcvd/cvd_src/image_io.cc?cvsroot=libcvd&r1=1.22&r2=1.23
http://cvs.savannah.gnu.org/viewcvs/libcvd/cvd/image_io.h?cvsroot=libcvd&r1=1.31&r2=1.32
http://cvs.savannah.gnu.org/viewcvs/libcvd/cvd/internal/io/png.h?cvsroot=libcvd&r1=1.1&r2=1.2

Patches:
Index: pnm_src/png.cc
===================================================================
RCS file: /cvsroot/libcvd/libcvd/pnm_src/png.cc,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- pnm_src/png.cc      29 Sep 2006 17:42:23 -0000      1.2
+++ pnm_src/png.cc      29 Sep 2006 21:40:27 -0000      1.3
@@ -31,7 +31,7 @@
 
 
 
-/*
+
 static void write_fn(png_structp png_ptr, unsigned char*  data, size_t 
numbytes)
 {
        ostream* o = (ostream*)png_get_io_ptr(png_ptr);
@@ -43,7 +43,10 @@
        ostream* o = (ostream*)png_get_io_ptr(png_ptr);
        (*o) << flush;
 }
-*/
+
+
+
+
 
 void png_in::unpack_to_bytes()
 {
@@ -179,3 +182,92 @@
 }
 
 
+
+
+png_out::png_out(int w, int h, colour_type t, int depth, std::ostream& out)
+:o(out)
+{
+       //Create required structs
+       png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, &error_string, 
error_fn, warn_fn);
+       if(!png_ptr)
+               throw Exceptions::OutOfMemory();
+
+       info_ptr = png_create_info_struct(png_ptr);
+       if (!info_ptr)     
+       {        
+               png_destroy_write_struct(&png_ptr,NULL);
+               throw Exceptions::OutOfMemory();
+       }
+
+       //Set up error handling
+       if(setjmp(png_jmpbuf(png_ptr)))     
+       {         
+               png_destroy_write_struct(&png_ptr, &info_ptr);
+               throw Exceptions::Image_IO::MalformedImage(error_string);
+       }
+
+       //Set up stream IO
+       png_set_write_fn(png_ptr, &o, write_fn, flush_fn);
+
+       int c_type;
+       switch(t)
+       {
+               case Grey: c_type = PNG_COLOR_TYPE_GRAY; break;
+               case GreyAlpha: c_type = PNG_COLOR_TYPE_GRAY_ALPHA; break;
+               case Rgb: c_type = PNG_COLOR_TYPE_RGB; break;
+               case RgbAlpha: c_type = PNG_COLOR_TYPE_RGB_ALPHA; break;
+       }
+
+
+       //Set up the image type
+       png_set_IHDR(png_ptr, info_ptr, w, h, depth, c_type, 
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+       
+       #ifdef CVD_ARCH_LITTLE_ENDIAN
+               if (depth > 8)
+                       png_set_swap(png_ptr);
+       #endif
+
+       //Write the header 
+       png_write_info(png_ptr, info_ptr);
+}
+
+void png_out::pack()
+{
+       png_set_packing(png_ptr);
+}
+
+void png_out::rgbx()
+{
+       png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
+}
+
+void png_out::write_raw_pixel_lines(const std::vector<const unsigned char*>& p)
+{
+       //Set up error handling
+       if(setjmp(png_jmpbuf(png_ptr)))     
+       {         
+               png_destroy_write_struct(&png_ptr, &info_ptr);
+               throw Exceptions::Image_IO::MalformedImage(error_string);
+       }
+
+       png_write_rows(png_ptr, const_cast<unsigned char**>(&p[0]), p.size());
+}
+
+void png_out::write_raw_pixel_lines(const std::vector<const unsigned short*>& 
p)
+{
+       //Set up error handling
+       if(setjmp(png_jmpbuf(png_ptr)))     
+       {         
+               png_destroy_write_struct(&png_ptr, &info_ptr);
+               throw Exceptions::Image_IO::MalformedImage(error_string);
+       }
+
+       png_write_rows(png_ptr, reinterpret_cast<unsigned 
char**>(const_cast<unsigned short**>(&p[0])), p.size());
+
+}
+
+png_out::~png_out()
+{
+       png_write_end(png_ptr, info_ptr);
+       png_destroy_write_struct(&png_ptr, &info_ptr);
+}

Index: cvd_src/image_io.cc
===================================================================
RCS file: /cvsroot/libcvd/libcvd/cvd_src/image_io.cc,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -b -r1.22 -r1.23
--- cvd_src/image_io.cc 28 Sep 2006 00:28:32 -0000      1.22
+++ cvd_src/image_io.cc 29 Sep 2006 21:40:27 -0000      1.23
@@ -104,9 +104,13 @@
        if (suffix == "ps") 
                return  ImageType::PS;
 #ifdef CVD_IMAGE_HAVE_JPEG
-       else if (suffix == "jpg") 
+       else if (suffix == "jpg" || suffix == "jpeg") 
                 return  ImageType::JPEG;
 #endif
+#ifdef CVD_IMAGE_HAVE_PNG
+       else if (suffix == "png") 
+                return  ImageType::PNG;
+#endif
        else if (suffix == "eps")
                return  ImageType::EPS;
        else if (suffix == "bmp") 

Index: cvd/image_io.h
===================================================================
RCS file: /cvsroot/libcvd/libcvd/cvd/image_io.h,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -b -r1.31 -r1.32
--- cvd/image_io.h      28 Sep 2006 23:23:51 -0000      1.31
+++ cvd/image_io.h      29 Sep 2006 21:40:28 -0000      1.32
@@ -73,6 +73,7 @@
                        EPS,
                        BMP,
                        CVD_IMAGE_HAVE_JPEG  //This is a macro, ending in ,
+                       CVD_IMAGE_HAVE_PNG
                };
        }
 
@@ -108,7 +109,7 @@
 
        #ifdef DOXYGEN_INCLUDE_ONLY_FOR_DOCS
        // This is not the real definition, but this is what it would look like 
if all
-       // the macros were expanded. The real definition is in 
internal/disk_image.h
+       // the macros were expanded. The real definition is above
        /// Contains the enumeration of possible image types
        namespace ImageType
        {
@@ -119,10 +120,17 @@
                        Automatic,
                        /// Unknown image type (can be returned by @ref 
string_to_image_type
                        Unknown,
-                       /// PNM image format (PBM, PGM or PPM). This is a raw 
image format.
+                       /// PNM image format (PBM, PGM or PPM).
+                       /// This writes 8 or 16 bit raw PGMs or PPMs. PBM is 
not currently supported
                        PNM, 
                        /// JPEG image format. This is a compressed (lossy) 
image format, but defaults to 95% quality, which has very few compression 
artefacts. This image type is only present if libjpeg is available.
+                       /// RGB and Greyscale JPEGs are supported
                        JPEG,
+                       /// Windows BMP (or DIB) format. Uncompressed 8 bit 
grey scale and 24 bit RGB are supported.
+                       BMP,
+                       /// PNG imager format. 1, 8 and 16 bit, Greyscale, RGB 
and RGBA images are supported.
+                       /// This image type is only present if libpng is 
available.
+                       PNG,
                        /// Postscript  format. This outputs a bare PostScript 
image with the coordinate system set up 
                        /// to that (x,y) corresponds to pixel (x,y), with 
(0,0) being at the top left of the pixel (0,0).
                        /// The Y axis is therefore inverted compared to normal 
postscript drawing, but is image aligned.
@@ -259,6 +267,9 @@
          #ifdef CVD_IMAGE_HAVE_JPEG
                  case ImageType::JPEG: JPEG::writeJPEG(im,o); break;
          #endif
+         #ifdef CVD_IMAGE_HAVE_PNG
+                 case ImageType::PNG: PNG::writePNG(im,o); break;
+         #endif
          case ImageType::PS:   PS::writePS(im, o);  break;
          case ImageType::EPS:  PS::writeEPS(im,o);  break;
          case ImageType::BMP:  BMP::writeBMP(im,o);  break;

Index: cvd/internal/io/png.h
===================================================================
RCS file: /cvsroot/libcvd/libcvd/cvd/internal/io/png.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- cvd/internal/io/png.h       28 Sep 2006 23:23:51 -0000      1.1
+++ cvd/internal/io/png.h       29 Sep 2006 21:40:28 -0000      1.2
@@ -1,3 +1,23 @@
+/*                       
+                        This file is part of the CVD Library.
+
+                        Copyright (C) 2005 The Authors
+
+                        This library is free software; you can redistribute it 
and/or
+                        modify it under the terms of the GNU Lesser General 
Public
+                        License as published by the Free Software Foundation; 
either
+                        version 2.1 of the License, or (at your option) any 
later version.
+
+                        This library is distributed in the hope that it will 
be useful,
+                        but WITHOUT ANY WARRANTY; without even the implied 
warranty of
+                        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
See the GNU
+                        Lesser General Public License for more details.
+
+                        You should have received a copy of the GNU Lesser 
General Public
+                        License along with this library; if not, write to the 
Free Software
+                        Foundation, Inc., 
+                        51 Franklin Street, Fifth Floor, Boston, MA  
02110-1301  USA
+*/
 #ifndef CVD_INTERNAL_IO_PNG_H
 #define CVD_INTERNAL_IO_PNG_H
 #include <iostream>
@@ -49,6 +69,35 @@
 
 };
 
+struct png_out
+{
+       typedef enum
+       {
+               Grey,
+               GreyAlpha,
+               Rgb,
+               RgbAlpha
+       }colour_type;
+
+       png_out(int w, int h, colour_type t, int depth, std::ostream&);
+       ~png_out();
+
+       void pack();
+       void rgbx();
+
+       void write_raw_pixel_lines(const std::vector<const unsigned char*>&);
+       void write_raw_pixel_lines(const std::vector<const unsigned short*>&);
+
+       void read_end();
+
+       std::string error_string;
+
+       std::ostream& o;
+
+       png_struct_def* png_ptr;
+       png_info_struct* info_ptr, *end_info;
+};
+
 
////////////////////////////////////////////////////////////////////////////////
 //
 // Utility
@@ -62,6 +111,14 @@
                rows[r] = (D*)im[r];
 }
 
+
+template<class C, class D> void make_row_pointers(const SubImage<C>& im, 
std::vector<const D*>& rows)
+{
+       rows.resize(im.size().y);
+       for(int r=0; r < im.size().y; r++)
+               rows[r] = (const D*)im[r];
+}
+
 
////////////////////////////////////////////////////////////////////////////////
 //
 // Read Greyscale PNG
@@ -271,5 +328,169 @@
        readPNG(im, png);
 }
 
+
+
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// How to convert Misc types in to PNG compatible types
+//
+
+template<int Components, bool use_16bit> struct PNGType;
+template<> struct PNGType<1,0>{ typedef byte type; typedef enum { Colour = 
png_out::Grey, Depth=8} col;};
+template<> struct PNGType<1,1>{ typedef unsigned short type; typedef enum { 
Colour = png_out::Grey, Depth=16} col;};
+template<> struct PNGType<3,0>{ typedef Rgb<byte> type; typedef enum { Colour 
= png_out::Rgb, Depth=8} col;};
+template<> struct PNGType<3,1>{ typedef Rgb<unsigned short> type; typedef enum 
{ Colour = png_out::Rgb, Depth=16} col;};
+template<> struct PNGType<4,0>{ typedef Rgba<byte> type; typedef enum { Colour 
= png_out::RgbAlpha, Depth=8} col;};
+template<> struct PNGType<4,1>{ typedef Rgba<unsigned short> type; typedef 
enum { Colour = png_out::RgbAlpha, Depth=16} col;};
+
+
+template<class T> class PNGWriter
+{
+       static void write(const SubImage<T>& i, std::ostream& o)
+       {
+               typedef PNGType<Pixel::Component<T>::count, 
Internal::save_default<T>::use_16bit> PNGInfo;
+
+               typedef typename PNGInfo::type Out;
+               typedef typename Pixel::Component<Out>::type Comp;
+               
+               png_out po(i.size().x, i.size().y, PNGInfo::Colour, 
PNGInfo::Depth, o);
+               std::vector<Out> row_buf(i.size().x);
+               std::vector<const Comp*> rows;
+               rows.push_back(reinterpret_cast<const Comp*>(&row_buf[0]));
+
+
+               
+               for(int r=0; r < i.size().y ; r++)
+               {
+                       Pixel::ConvertPixels<T,Out>::convert(i[r], &row_buf[0], 
i.size().x);
+                       po.write_raw_pixel_lines(rows);
+               }
+       }
+};
+
+template<class T> void writePNG(const SubImage<T>& i, std::ostream& o)
+{
+       PNGWriter<T>::write(i, o);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Types which require no conversions
+//
+
+template<> struct PNGWriter<bool>
+{
+       static void write(const SubImage<bool>& i, std::ostream& o)
+       {
+               png_out po(i.size().x, i.size().y, png_out::Grey, 1, o);
+               po.pack();
+               std::vector<const byte*> rows;
+               make_row_pointers(i, rows);
+               po.write_raw_pixel_lines(rows);
+       }
+};
+
+template<> struct PNGWriter<byte>
+{
+       static void write(const SubImage<byte>& i, std::ostream& o)
+       {
+               png_out po(i.size().x, i.size().y, png_out::Grey, 8, o);
+               std::vector<const byte*> rows;
+               make_row_pointers(i, rows);
+               po.write_raw_pixel_lines(rows);
+       }
+};
+
+template<> struct PNGWriter<unsigned short>
+{
+       static void write(const SubImage<unsigned short>& i, std::ostream& o)
+       {
+               png_out po(i.size().x, i.size().y, png_out::Grey, 16, o);
+               std::vector<const unsigned short*> rows;
+               make_row_pointers(i, rows);
+               po.write_raw_pixel_lines(rows);
+       }
+};
+
+
+template<> struct PNGWriter<Rgb8>
+{
+       static void write(const SubImage<Rgb<byte> >& i, std::ostream& o)
+       {
+               png_out po(i.size().x, i.size().y, png_out::Rgb, 8, o);
+               po.rgbx();
+               std::vector<const byte*> rows;
+               make_row_pointers(i, rows);
+               po.write_raw_pixel_lines(rows);
+       }
+};
+
+
+template<> struct PNGWriter<Rgb<byte> >
+{
+       static void write(const SubImage<Rgb<byte> >& i, std::ostream& o)
+       {
+               png_out po(i.size().x, i.size().y, png_out::Rgb, 8, o);
+               std::vector<const byte*> rows;
+               make_row_pointers(i, rows);
+               po.write_raw_pixel_lines(rows);
+       }
+};
+
+template<> struct PNGWriter<Rgb<unsigned short> >
+{
+       static void write(const SubImage<Rgb<unsigned short> >& i, 
std::ostream& o)
+       {
+               png_out po(i.size().x, i.size().y, png_out::Rgb, 16, o);
+               std::vector<const byte*> rows;
+               make_row_pointers(i, rows);
+               po.write_raw_pixel_lines(rows);
+       }
+};
+
+template<> struct PNGWriter<Rgba<byte> >
+{
+       static void write(const SubImage<Rgba<byte> >& i, std::ostream& o)
+       {
+               png_out po(i.size().x, i.size().y, png_out::RgbAlpha, 8, o);
+               std::vector<const byte*> rows;
+               make_row_pointers(i, rows);
+               po.write_raw_pixel_lines(rows);
+       }
+};
+
+template<> struct PNGWriter<Rgba<unsigned short> >
+{
+       static void write(const SubImage<Rgba<unsigned short> >& i, 
std::ostream& o)
+       {
+               png_out po(i.size().x, i.size().y, png_out::RgbAlpha, 16, o);
+               std::vector<const byte*> rows;
+               make_row_pointers(i, rows);
+               po.write_raw_pixel_lines(rows);
+       }
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 }}
 #endif




reply via email to

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