[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libcvd-members] libcvd cvd/internal/io/png.h pnm_src/png.cc
|
From: |
Edward Rosten |
|
Subject: |
[libcvd-members] libcvd cvd/internal/io/png.h pnm_src/png.cc |
|
Date: |
Tue, 05 Aug 2008 22:12:06 +0000 |
CVSROOT: /cvsroot/libcvd
Module name: libcvd
Changes by: Edward Rosten <edrosten> 08/08/05 22:12:05
Modified files:
cvd/internal/io: png.h
pnm_src : png.cc
Log message:
Convert PNG reading to use the new mechanism
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/libcvd/cvd/internal/io/png.h?cvsroot=libcvd&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/libcvd/pnm_src/png.cc?cvsroot=libcvd&r1=1.6&r2=1.7
Patches:
Index: cvd/internal/io/png.h
===================================================================
RCS file: /cvsroot/libcvd/libcvd/cvd/internal/io/png.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- cvd/internal/io/png.h 13 May 2008 12:44:26 -0000 1.5
+++ cvd/internal/io/png.h 5 Aug 2008 22:12:05 -0000 1.6
@@ -35,83 +35,73 @@
namespace CVD{
namespace PNG{
+using CVD::Internal::TypeList;
+using CVD::Internal::Head;
-struct png_in
+
+
+class png_reader
{
- enum
- {
- Grey,
- GreyAlpha,
- Rgb,
- RgbAlpha
- }colour_type;
+ public:
+ png_reader(std::istream&);
+ ~png_reader();
- png_in(std::istream&);
- ~png_in();
+ ImageRef size();
- void expand_depth_to_8();
- void unpack_to_bytes();
+ void get_raw_pixel_line(bool*);
+ void get_raw_pixel_line(unsigned char*);
+ void get_raw_pixel_line(unsigned short*);
+ void get_raw_pixel_line(Rgb<unsigned char>*);
+ void get_raw_pixel_line(Rgb<unsigned short>*);
+ void get_raw_pixel_line(Rgba<unsigned char>*);
+ void get_raw_pixel_line(Rgba<unsigned short>*);
- void get_raw_pixel_lines(unsigned char**, int);
- void get_raw_pixel_lines(unsigned short**, int);
+ std::string datatype();
+ std::string name();
- void read_end();
+ typedef TypeList<bool,
+ TypeList<byte,
+ TypeList<unsigned short,
+ TypeList<Rgb<byte>,
+ TypeList<Rgb<unsigned short>,
+ TypeList<Rgba<byte>,
+ TypeList<Rgba<unsigned short>,
+ Head> > > > > > >
Types;
- int depth;
- int width, height;
- std::string error_string;
+ private:
std::istream& i;
-
+ std::string type;
+ unsigned long row;
png_struct_def* png_ptr;
png_info_struct* info_ptr, *end_info;
+ std::string error_string;
+ ImageRef my_size;
+
+ template<class C> void read_pixels(C*);
};
-struct png_out
+template <class T> void readPNG(BasicImage<T>& im, std::istream& in)
{
- 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*>&);
+ CVD::Internal::readImage<T, png_reader>(im, in);
+}
- void read_end();
+template <class T> void readPNG(Image<T>& im, std::istream& in)
+{
+ CVD::Internal::readImage<T, png_reader>(im, in);
+}
- std::string error_string;
- std::ostream& o;
- png_struct_def* png_ptr;
- png_info_struct* info_ptr, *end_info;
-};
////////////////////////////////////////////////////////////////////////////////
//
-// Utility
+// How to convert Misc types in to PNG compatible types
//
-template<class C, class D> void make_row_pointers(SubImage<C>& im,
std::vector<D*>& rows)
-{
- rows.resize(im.size().y);
- for(int r=0; r < im.size().y; r++)
- 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);
@@ -119,227 +109,35 @@
rows[r] = (const D*)im[r];
}
-////////////////////////////////////////////////////////////////////////////////
-//
-// Read Greyscale PNG
-//
-template<class Dest, class Src_ish> struct readPNG_grey
-{
- static void read(SubImage<Dest>& im, png_in& png)
- {
- if(png.depth < 8)
- png.expand_depth_to_8();
-
- std::vector<Src_ish> row_buf(png.width);
- Src_ish *row = &row_buf[0];
-
- for(int r=0; r < png.height; r++)
- {
- png.get_raw_pixel_lines(&row, 1);
- Pixel::ConvertPixels<Src_ish, Dest>::convert(row,
im[r], png.width);
- }
- }
-};
-
-template<class Dest> struct readPNG_grey<Dest, bool>
-{
- static void read(SubImage<Dest>& im, png_in& png)
- {
- readPNG_grey<Dest, byte>::read(im, png);
- }
-};
-
-template<> struct readPNG_grey<bool, bool>
-{
- static void read(SubImage<bool>& im, png_in& png)
- {
- png.unpack_to_bytes();
- std::vector<byte*> rows;
- make_row_pointers(im, rows);
- png.get_raw_pixel_lines(&rows[0], png.height);
- }
-};
-
-template<> struct readPNG_grey<byte, unsigned char>
-{
- static void read(SubImage<byte>& im, png_in& png)
- {
- if(png.depth < 8)
- png.expand_depth_to_8();
-
- std::vector<byte*> rows;
- make_row_pointers(im, rows);
-
- png.get_raw_pixel_lines(&rows[0], png.height);
- }
-};
-
-
-template<> struct readPNG_grey<unsigned short, unsigned short>
-{
- static void read(SubImage<unsigned short>& im, png_in& png)
- {
- std::vector<unsigned short*> rows;
- make_row_pointers(im, rows);
- png.get_raw_pixel_lines(&rows[0], png.height);
- }
-};
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Read RGB PNG
-//
-
-template<class Dest, class Src> struct readPNG_rgb
+struct png_out
{
- static void read(SubImage<Dest>& im, png_in& png)
- {
- std::vector<Src> row_buf(png.width*3);
- Src* row = &row_buf[0];
-
- for(int r=0; r < png.height; r++)
+ typedef enum
{
- png.get_raw_pixel_lines(&row, 1);
- Pixel::ConvertPixels<Rgb<Src>, Dest
>::convert(reinterpret_cast<Rgb<Src>*>(row), im[r], png.width);
- }
- }
-};
+ Grey,
+ GreyAlpha,
+ Rgb,
+ RgbAlpha
+ }colour_type;
-template<> struct readPNG_rgb<Rgb<byte>, byte>
-{
- static void read(SubImage<Rgb<byte> >& im, png_in& png)
- {
- std::vector<byte*> rows;
- make_row_pointers(im, rows);
- png.get_raw_pixel_lines(&rows[0] , png.height);
- }
-};
+ png_out(int w, int h, colour_type t, int depth, std::ostream&);
+ ~png_out();
-template<> struct readPNG_rgb<Rgb<unsigned short>, unsigned short>
-{
- static void read(SubImage<Rgb<unsigned short> >& im, png_in& png)
- {
- std::vector<unsigned short*> rows;
- make_row_pointers(im, rows);
- png.get_raw_pixel_lines(&rows[0], png.height);
- }
-};
+ void pack();
+ void rgbx();
-////////////////////////////////////////////////////////////////////////////////
-//
-// Read RGBA PNG
-//
+ void write_raw_pixel_lines(const std::vector<const unsigned char*>&);
+ void write_raw_pixel_lines(const std::vector<const unsigned short*>&);
-template<class Dest, class Src> struct readPNG_rgba
-{
- static void read(SubImage<Dest>& im, png_in& png)
- {
- std::vector<Src> row_buf(png.width*4);
- Src* row = &row_buf[0];
+ void read_end();
- for(int r=0; r < png.height; r++)
- {
- png.get_raw_pixel_lines(&row, 1);
- Pixel::ConvertPixels<Rgba<Src>, Dest
>::convert(reinterpret_cast<Rgba<Src>*>(row), im[r], png.width);
- }
- }
-};
+ std::string error_string;
-template<> struct readPNG_rgb<Rgba<byte>, byte>
-{
- static void read(SubImage<Rgba<byte> >& im, png_in& png)
- {
- std::vector<byte*> rows;
- make_row_pointers(im, rows);
- png.get_raw_pixel_lines(&rows[0] , png.height);
- }
-};
+ std::ostream& o;
-template<> struct readPNG_rgb<Rgba<unsigned short>, unsigned short>
-{
- static void read(SubImage<Rgba<unsigned short> >& im, png_in& png)
- {
- std::vector<unsigned short*> rows;
- make_row_pointers(im, rows);
- png.get_raw_pixel_lines(&rows[0], png.height);
- }
+ png_struct_def* png_ptr;
+ png_info_struct* info_ptr, *end_info;
};
-////////////////////////////////////////////////////////////////////////////////
-//
-// Runtime switch on type
-//
-
-template<class C> void readPNG(SubImage<C>& im, png_in& png)
-{
- switch(png.colour_type)
- {
- case png_in::Grey:
- if(png.depth == 16)
- readPNG_grey<C, unsigned
short>::read(im, png);
- else if(png.depth == 1)
- readPNG_grey<C, bool>::read(im, png);
- else
- readPNG_grey<C, unsigned
char>::read(im, png);
- break;
-
- case png_in::GreyAlpha:
- throw
Exceptions::Image_IO::UnsupportedImageSubType("PNG", "Grey-alpha not yet
supported");
- break;
-
- case png_in::Rgb:
- if(png.depth == 16)
- readPNG_rgb<C, unsigned
short>::read(im, png);
- else
- readPNG_rgb<C, unsigned char>::read(im,
png);
- break;
-
- case png_in::RgbAlpha:
- if(png.depth == 16)
- readPNG_rgba<C, unsigned
short>::read(im, png);
- else
- readPNG_rgba<C, unsigned
char>::read(im, png);
- break;
- }
-
- //This clears the stream of PNGs
- png.read_end();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Adapter for various image manifestations
-//
-
-template <class T> void readPNG(SubImage<T>& im, std::istream& in)
-{
- png_in png(in);
- ImageRef size(png.width, png.height);
- if (im.size() != size)
- throw Exceptions::Image_IO::ImageSizeMismatch(size, im.size());
- readPNG(im, png);
-}
-
-template <class T> void readPNG(Image<T>& im, std::istream& in)
-{
- png_in png(in);
- ImageRef size(png.width, png.height);
- im.resize(size);
- 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; static const
png_out::colour_type Colour = png_out::Grey; static const int Depth=8;};
template<> struct PNGType<1,1>{ typedef unsigned short type; static const
png_out::colour_type Colour = png_out::Grey; static const int Depth=16;};
Index: pnm_src/png.cc
===================================================================
RCS file: /cvsroot/libcvd/libcvd/pnm_src/png.cc,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- pnm_src/png.cc 30 Jul 2008 00:10:01 -0000 1.6
+++ pnm_src/png.cc 5 Aug 2008 22:12:05 -0000 1.7
@@ -5,10 +5,15 @@
#include <png.h>
using namespace CVD;
+using namespace CVD::Exceptions;
+using namespace CVD::Exceptions::Image_IO;
using namespace PNG;
using namespace std;
-
+////////////////////////////////////////////////////////////////////////////////
+//
+// C++ istreams based I/O functions
+//
static void error_fn(png_structp png_ptr, png_const_charp error_msg)
{
*(string*)(png_ptr->error_ptr) = error_msg;
@@ -29,9 +34,6 @@
//to fail because it has internal checksums
}
-
-
-
static void write_fn(png_structp png_ptr, unsigned char* data, size_t
numbytes)
{
ostream* o = (ostream*)png_get_io_ptr(png_ptr);
@@ -44,58 +46,66 @@
(*o) << flush;
}
+////////////////////////////////////////////////////////////////////////////////
+//
+// PNG reading functions
+//
-
-
-
-void png_in::unpack_to_bytes()
+string png_reader::datatype()
{
- //No error checking. Only call for Grey images
- png_set_packing(png_ptr);
+ return type;
}
-void png_in::expand_depth_to_8()
+string png_reader::name()
{
- //No error checking. Only call for Grey images
- png_set_gray_1_2_4_to_8(png_ptr);
+ return "PNG";
}
-void png_in::get_raw_pixel_lines(unsigned char** row_ptr, int nlines)
+ImageRef png_reader::size()
{
- if(depth == 16)
- throw Exceptions::Image_IO::ReadTypeMismatch(1);
+ return my_size;
+}
- if(setjmp(png_jmpbuf(png_ptr)))
- throw Exceptions::Image_IO::MalformedImage(error_string);
- //NB no check for read past end.
- png_read_rows(png_ptr, row_ptr, NULL, nlines);
-}
+//Mechanically generate the pixel reading calls.
+#define GEN1(X) void png_reader::get_raw_pixel_line(X*d){read_pixels(d);}
+#define GEN3(X) GEN1(X) GEN1(Rgb<X>) GEN1(Rgba<X>)
+GEN1(bool)
+GEN3(unsigned char)
+GEN3(unsigned short)
-void png_in::get_raw_pixel_lines(unsigned short** row_ptr, int nlines)
+
+template<class P> void png_reader::read_pixels(P* data)
{
- if(depth != 16)
- throw Exceptions::Image_IO::ReadTypeMismatch(0);
+ if(datatype() != PNM::type_name<P>::name())
+ throw ReadTypeMismatch(datatype(), PNM::type_name<P>::name());
+
+ if(row > (unsigned long)my_size.y)
+ throw InternalLibraryError("CVD", "Read past end of image.");
+
if(setjmp(png_jmpbuf(png_ptr)))
throw Exceptions::Image_IO::MalformedImage(error_string);
- //NB no check for read past end.
- png_read_rows(png_ptr, (unsigned char**)row_ptr, NULL, nlines);
+ unsigned char* cptr = reinterpret_cast<unsigned char*>(data);
+ unsigned char** row_ptr = &cptr;
+
+ png_read_rows(png_ptr, row_ptr, NULL, 1);
}
-png_in::png_in(std::istream& in)
-:i(in)
+
+
+png_reader::png_reader(std::istream& in)
+:i(in),type(""),row(0),png_ptr(0),info_ptr(0),end_info(0)
{
+ //Read the header and make sure it really is a PNG...
unsigned char header[8];
in.read((char*)header, 8);
if(png_sig_cmp(header, 0, 8))
- {
throw Exceptions::Image_IO::MalformedImage("Not a PNG image");
- }
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL,
NULL);
@@ -136,23 +146,42 @@
png_read_info(png_ptr, info_ptr);
png_uint_32 w, h;
- int colour, interlace, dummy;
+ int colour, interlace, dummy, depth;
png_get_IHDR(png_ptr, info_ptr, &w, &h, &depth, &colour, &interlace,
&dummy, &dummy);
- width = w;
- height = h;
+ my_size.x = w;
+ my_size.y = h;
+
+ //Figure out the type name, and what processing to to.
+ if(depth == 1)
+ {
+ //Unpack bools to bytes to ease loading.
+ png_set_packing(png_ptr);
+ type = PNM::type_name<bool>::name();
+ }
+ else if(depth <= 8)
+ {
+ //Expand nonbool colour depths up to 8bpp
+ if(depth < 8)
+ png_set_gray_1_2_4_to_8(png_ptr);
+
+ type = PNM::type_name<unsigned char>::name();
+ }
+ else
+ type = PNM::type_name<unsigned short>::name();
+
if(colour & PNG_COLOR_MASK_COLOR)
if(colour & PNG_COLOR_MASK_ALPHA)
- colour_type = RgbAlpha;
+ type = "CVD::Rgba<" + type + ">";
else
- colour_type = Rgb;
+ type = "CVD::Rgb<" + type + ">";
else
if(colour & PNG_COLOR_MASK_ALPHA)
- colour_type = GreyAlpha;
+ type = "CVD::GreyAlpha<" + type + ">";
else
- colour_type = Grey;
+ type = type;
//Get rid of palette, by transforming it to RGB
if(colour == PNG_COLOR_TYPE_PALETTE)
@@ -167,21 +196,22 @@
#endif
}
-void png_in::read_end()
+png_reader::~png_reader()
{
+ //Clear the stream of any remaining PNG bits.
//It doesn't matter if there's an error here
if(!setjmp(png_jmpbuf(png_ptr)))
png_read_end(png_ptr, end_info);
-}
-png_in::~png_in()
-{
//Destroy all PNG structs
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
}
-
+////////////////////////////////////////////////////////////////////////////////
+//
+// PNG writing functions.
+//
png_out::png_out(int w, int h, colour_type t, int depth, std::ostream& out)
:o(out)
| [Prev in Thread] |
Current Thread |
[Next in Thread] |
- [libcvd-members] libcvd cvd/internal/io/png.h pnm_src/png.cc,
Edward Rosten <=