[Top][All Lists]
[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [libcvd-members] libcvd pnm_src/png.cc cvd_src/image_io.cc cvd/i...,
Edward Rosten <=