libcvd-members
[Top][All Lists]
Advanced

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

[libcvd-members] libcvd Makefile.in cvd/image_io.h cvd_src/image...


From: Olaf Kähler
Subject: [libcvd-members] libcvd Makefile.in cvd/image_io.h cvd_src/image...
Date: Mon, 15 Feb 2010 10:40:48 +0000

CVSROOT:        /sources/libcvd
Module name:    libcvd
Changes by:     Olaf Kähler <ok245>     10/02/15 10:40:48

Modified files:
        .              : Makefile.in 
        cvd            : image_io.h 
        cvd_src        : image_io.cc 
Added files:
        cvd/internal/io: cvdimage.h 
        pnm_src        : cvdimage.cxx 

Log message:
        added fast, lossless image compression as ImageType::CVD

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/libcvd/Makefile.in?cvsroot=libcvd&r1=1.93&r2=1.94
http://cvs.savannah.gnu.org/viewcvs/libcvd/cvd/image_io.h?cvsroot=libcvd&r1=1.41&r2=1.42
http://cvs.savannah.gnu.org/viewcvs/libcvd/cvd/internal/io/cvdimage.h?cvsroot=libcvd&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/libcvd/cvd_src/image_io.cc?cvsroot=libcvd&r1=1.30&r2=1.31
http://cvs.savannah.gnu.org/viewcvs/libcvd/pnm_src/cvdimage.cxx?cvsroot=libcvd&rev=1.1

Patches:
Index: Makefile.in
===================================================================
RCS file: /sources/libcvd/libcvd/Makefile.in,v
retrieving revision 1.93
retrieving revision 1.94
diff -u -b -r1.93 -r1.94
--- Makefile.in 27 Jun 2009 15:13:45 -0000      1.93
+++ Makefile.in 15 Feb 2010 10:40:46 -0000      1.94
@@ -96,6 +96,7 @@
                        cvd_src/yuv420.o                                \
                        pnm_src/pnm_grok.o                              \
                        pnm_src/bmp.o                                   \
+                       pnm_src/cvdimage.o                              \
                        pnm_src/fits.o                                  \
                        pnm_src/fitswrite.o                             \
                        pnm_src/save_postscript.o                       \

Index: cvd/image_io.h
===================================================================
RCS file: /sources/libcvd/libcvd/cvd/image_io.h,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -b -r1.41 -r1.42
--- cvd/image_io.h      4 Jun 2009 17:07:50 -0000       1.41
+++ cvd/image_io.h      15 Feb 2010 10:40:48 -0000      1.42
@@ -39,6 +39,7 @@
 #include <cvd/internal/io/bmp.h>
 #include <cvd/internal/io/fits.h>
 #include <cvd/internal/io/text.h>
+#include <cvd/internal/io/cvdimage.h>
 
 
 #ifdef CVD_HAVE_JPEG
@@ -87,6 +88,7 @@
                        TXT=7,
                        TEXT=7,
                        FITS=8,
+                       CVD=9,
                };
        }
 
@@ -162,6 +164,11 @@
                        /// with the load() function. There is no metadata, so 
it is not possible to support 
                        /// multiple types. 
                        TXT,
+                       /// CVD image format. 8 bit Grey-scale, RGB and RGBA
+                       /// images are currently supported. Files of this type
+                       /// have a simple PNM-like header, but use a lossless
+                       /// compression scheme (line-wise prediction + Huffman).
+                       CVD,
                        /// FITS images. Supports (native) byte, short, 
unsigned short, int, float and double
                        /// of greyscale, RGB and RGBA. Signed char is 
supported lossley but inefficiently. 
                        FITS,
@@ -244,6 +251,8 @@
            BMP::readBMP(im, i);
          else if(c == 'S')
            CVD::Internal::readImage<I, FITS::reader>(im, i);
+         else if(c == 'C')
+           CVD::Internal::readImage<I, CVDimage::reader>(im, i);
          else if(c == ' ' || c == '\t' || isdigit(c) || c == '-' || c == '+')
            CVD::Internal::readImage<I, TEXT::reader>(im, i);
          else
@@ -302,6 +311,7 @@
          case ImageType::TXT: Internal::writeImage<PixelType, 
TEXT::writer>(im, o); break;
          case ImageType::PS:   Internal::writeImage<PixelType, PS::writer>(im, 
o); break;
          case ImageType::EPS:   Internal::writeImage<PixelType, 
PS::eps_writer>(im, o); break;
+         case ImageType::CVD: Internal::writeImage<PixelType, 
CVDimage::writer>(im,o); break;
          }
        }
 

Index: cvd_src/image_io.cc
===================================================================
RCS file: /sources/libcvd/libcvd/cvd_src/image_io.cc,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -b -r1.30 -r1.31
--- cvd_src/image_io.cc 4 Jun 2009 17:09:34 -0000       1.30
+++ cvd_src/image_io.cc 15 Feb 2010 10:40:48 -0000      1.31
@@ -135,6 +135,8 @@
                return ImageType::TXT;
        else if (suffix == "fits" || suffix == "fts")
                return ImageType::FITS;
+       else if (suffix == "cvd")
+               return ImageType::CVD;
        else
                return ImageType::Unknown;
 }

Index: cvd/internal/io/cvdimage.h
===================================================================
RCS file: cvd/internal/io/cvdimage.h
diff -N cvd/internal/io/cvdimage.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ cvd/internal/io/cvdimage.h  15 Feb 2010 10:40:48 -0000      1.1
@@ -0,0 +1,110 @@
+/*                       
+       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 PNM_CVDIMAGE_H
+#define PNM_CVDIMAGE_H
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <memory>
+
+#include <cvd/image.h>
+#include <cvd/byte.h>
+#include <cvd/internal/convert_pixel_types.h>
+#include <cvd/internal/load_and_save.h>
+
+namespace CVD
+{
+namespace CVDimage
+{
+
+       using CVD::Internal::TypeList;
+       using CVD::Internal::Head;
+
+
+       class ReadPimpl;
+       class reader
+       {
+               public:
+                       reader(std::istream&);
+                       ~reader();
+
+                       ImageRef size();
+
+                       void get_raw_pixel_line(unsigned char*);
+                       void get_raw_pixel_line(Rgb<unsigned char>*);
+                       void get_raw_pixel_line(Rgba<unsigned char>*);
+
+                       std::string datatype();
+                       std::string name();
+
+
+                       typedef TypeList<byte,
+                                       TypeList<Rgb<byte>, 
+                                       TypeList<Rgba<byte>, 
+                                       Head> > > Types;
+               
+               private:
+                       std::auto_ptr<ReadPimpl> t; 
+       };
+
+
+       class WritePimpl;
+
+       class writer
+       {
+               public:
+                       writer(std::ostream&, ImageRef size, const std::string& 
type);
+                       ~writer();
+
+                       void write_raw_pixel_line(const byte*);
+                       void write_raw_pixel_line(const Rgb<byte>*);
+                       void write_raw_pixel_line(const Rgba<byte>*);
+
+                       template<class Incoming> struct Outgoing
+                       {               
+                               typedef byte type;
+                       };              
+
+               protected:
+                       std::auto_ptr<WritePimpl> t; 
+       };
+
+       template<class C> struct writer::Outgoing<Rgb<C> > 
+       {
+               typedef Rgb<byte> type;
+       };
+
+
+       template<class C> struct writer::Outgoing<Rgba<C> > 
+       {
+               typedef Rgba<byte> type;
+       };
+
+       template<> struct writer::Outgoing<Rgb8> 
+       {
+               typedef Rgb<byte> type;
+       };
+
+}
+}
+
+#endif

Index: pnm_src/cvdimage.cxx
===================================================================
RCS file: pnm_src/cvdimage.cxx
diff -N pnm_src/cvdimage.cxx
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ pnm_src/cvdimage.cxx        15 Feb 2010 10:40:48 -0000      1.1
@@ -0,0 +1,589 @@
+/*                       
+       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
+*/
+
+#include <stdio.h>
+#include <endian.h> // used for byte reordering
+#include "cvd/internal/io/cvdimage.h"
+
+#include "cvd/image_io.h"
+#include "cvd/config.h"
+#include <iostream>
+#include <iomanip>
+#include <setjmp.h>
+#include <algorithm>
+#include <set>
+#include <climits>
+#include <tr1/array>
+using namespace std;
+using namespace std::tr1;
+
+
+namespace CVD
+{
+namespace CVDimage
+{
+
+// helper functions for prediction
+
+// Use a simple linewise predictor and compute the residual differences for a
+// single line. The predictor uses the value stored @p predictionlen bytes in
+// the past to predict the current value.
+void line_diff(const byte* in, int width, byte* out, int predictionlen = 1)
+{
+       for (int i = 0; i < predictionlen; i++)
+               out[i] = in[i];
+
+       for (int i = predictionlen; i < width; i++)
+               out[i] = (256 + in[i] - in[i-predictionlen])&255;
+}
+
+void line_undiff(const byte* in, int width, byte* out, int predictionlen = 1)
+{
+       for (int i = 0; i < predictionlen; i++)
+               out[i] = in[i];
+
+       for (int i = predictionlen; i < width; i++)
+               out[i] = (in[i] + out[i-predictionlen])&255;
+}
+
+// helper functions for huffman coding
+
+struct Huff{
+       Huff* zero, *one, *parent;
+       int symbol;
+       size_t count;
+
+       bool operator()(const Huff* l, const Huff* r) const
+       {
+               if(l->count < r->count)
+                       return 1;
+               else if(l->count == r->count)
+                       return l->symbol < r->symbol;
+               else
+                       return 0;
+       }
+};
+
+
+// This function creates a histogram of the element counts. The largest #
+// count is always 65535 and the smallest nonzero count is at least 1. 0 means
+// no counts, so it is ignored in the huffman tree. This way, all the data
+// required to rebuild the tree can be stored in 512 bytes.
+void create_normalized_hist(const Image<byte>& im, array<int,256>& h)
+{
+        fill(h.begin(), h.end(), 0);
+
+       for(Image<byte>::const_iterator i = im.begin(); i!=im.end(); i++)
+               h[*i]++;
+
+       int hi = *max_element(h.begin(), h.end());
+       for(unsigned int i=0; i < h.size(); i++)
+               if(h[i])
+                       h[i]  = (((uint64_t)h[i])* 65534 / hi)+1;
+}
+
+
+
+
+// Given a histogram of for the symbols to encode, create a tree for a
+// corresponding Huffman code
+Huff* create_tree(const array<int,256>& h, vector<Huff*>& symbols)
+{
+       set<Huff*,Huff> table;
+
+       for(unsigned int i=0; i < 256; i++)
+       {
+               if(h[i])
+               {
+                       Huff s = {0,0,0,i,h[i]};
+                       Huff* ss = new Huff(s);
+                       table.insert(ss);
+                       symbols.push_back(ss);
+               }
+       }
+
+       //Starting negative and incrementing makes equal probability
+       //symbols appear in symbol order. There are at most 2x the number of 
+       //junk symbols as real ones.
+       int junk_symbol=INT_MIN;
+       while(table.size() > 1)
+       {
+
+               Huff* smallest = *table.begin();
+               table.erase(table.begin());
+
+               Huff* next_smallest = *table.begin();
+               table.erase(table.begin());
+
+               Huff s = {smallest, next_smallest, 0, junk_symbol++, 
smallest->count + next_smallest->count};
+               Huff*ss = new Huff(s);
+               
+               smallest->parent = ss;
+               next_smallest->parent=ss;
+               table.insert(ss);
+       }
+       
+       return *table.begin();
+}
+
+
+typedef uint16_t PackType;
+static const int PackBits = sizeof(PackType) * 8;
+static const int Bits_48 = 48 / PackBits == 0 ? 1 : 48/PackBits;
+static const int Bits_96 = 96 / PackBits == 0 ? 1 : 96/PackBits;
+
+struct SortIndex
+{
+       const array<int, 256>& d;
+
+       SortIndex(const array<int,256>& aa)
+       :d(aa)
+       {}
+
+       bool operator()(int a, int b) const
+       {
+               return d[a] > d[b];
+       }
+       
+};
+
+// given a image (or "some data") and histogram of the contained symbols,
+// create a Huffman tree, encode the data and return the new code
+vector<PackType> huff_compress(const Image<byte>& im, const array<int,256>& h)
+{
+//     cvd_timer t;
+
+//     cout << "Hist: " << t.reset() * 1000 << endl;
+
+       vector<Huff*> terminals;
+       Huff* table = create_tree(h, terminals);
+
+//     cout << "Tree : " << t.reset() * 1000 << endl;
+       vector<vector<byte> > symbols(256);
+
+       for(unsigned int i=0; i < terminals.size(); i++)
+       {
+               vector<byte> bits;
+
+               Huff* h = terminals[i];
+
+               int symbol = h->symbol;
+
+               while(h != table)
+               {
+                       Huff* parent = h->parent;
+
+                       if(h == parent->one)
+                               bits.push_back(1);
+                       else
+                               bits.push_back(0);
+                       
+                       h = h->parent;
+               }
+               
+               reverse(bits.begin(), bits.end());
+               symbols[symbol] = bits;
+
+       }
+//     cout << "Symbols : " << t.reset() * 1000 << endl;
+       //Longest symbol is 48 bits?
+       
+       array<array<array<PackType, 20>, PackBits>, 256> fast_symbols;
+       array<array<int, PackBits>, 256> fast_symbols_num_chunks;
+
+       for(unsigned int i=0; i < symbols.size(); i++)
+               if(symbols[i].size())
+               {
+                       for(int off=0; off < PackBits; off++)
+                       {
+                               fast_symbols_num_chunks[i][off] = 0;
+
+                               int o=off;
+                               PackType chunk = 0;
+                               for(unsigned int j=0; j < symbols[i].size(); 
j++)
+                               {
+                                       chunk |= ((PackType)symbols[i][j]) << 
(o%PackBits);
+                                       o++;
+                                       if(o % PackBits == 0)
+                                       {
+                                               
fast_symbols[i][off][fast_symbols_num_chunks[i][off]++] = chunk;
+                                               chunk = 0;
+                                       }
+                               }
+                               
+                               if(o % PackBits)
+                                       
fast_symbols[i][off][fast_symbols_num_chunks[i][off]++] = chunk;
+                       }
+               }
+
+
+       vector<PackType> r2;
+       r2.reserve(im.size().area()/(2*PackBits));
+       int bit=0;
+       for(Image<byte>::const_iterator i = im.begin(); i!=im.end(); i++)
+       {
+               const int off = bit % PackBits;
+               
+               //Deal with the first (unaligned byte)
+               if(off == 0)
+                       r2.push_back(fast_symbols[*i][0][0]);
+               else
+                       r2.back() |= fast_symbols[*i][off][0];
+
+               //Deal with any remaining bytes
+               for(int j=1; j < fast_symbols_num_chunks[*i][off]; j++)
+                       r2.push_back(fast_symbols[*i][off][j]);
+
+               bit += symbols[*i].size();
+       }
+
+
+//     cout << "Fast Packing : " << t.reset() * 1000 << endl;
+
+       return r2;
+}
+
+
+// given an encoded data stream and a histogram of the encoded symbols, create
+// a Huffman tree, decode the data and store it in the image ret.
+template<class P> void huff_decompress(const vector<P>& b, const 
array<int,256>& h, Image<byte>& ret)
+{
+       vector<Huff*> terminals;
+       Huff* table = create_tree(h, terminals);
+
+       int i=0;        
+       for(Image<byte>::iterator r=ret.begin(); r != ret.end(); r++)
+       {
+               Huff* h = table;
+
+               while(h->one)
+               {
+                       bool bit =  b[i/(sizeof(P) * 8)] & ((P)1 << 
(i%(sizeof(P) * 8)));
+                       i++;
+                       if(bit)
+                               h = h->one;
+                       else
+                               h = h->zero;
+               }
+               
+               *r = h->symbol; 
+       }
+}
+
+
+
+
+class ReadPimpl
+{
+       public:
+               ReadPimpl(std::istream&);
+               int channels(){return m_channels;}
+               long  x_size() const {return xs;}
+               long  y_size() const {return ys;}
+               long  elements_per_line() const {return xs * m_channels;}
+               void get_raw_pixel_lines(unsigned char*, unsigned long nlines);
+               ~ReadPimpl();
+               string datatype()
+               {
+                       return type;
+               }
+               
+               template<class T> void get_raw_pixel_line(T* d)
+               {
+                       if(datatype() != PNM::type_name<T>::name())
+                               throw 
CVD::Exceptions::Image_IO::ReadTypeMismatch(datatype(), 
PNM::type_name<T>::name());
+
+                       get_raw_pixel_lines((unsigned char*)d, 1);
+               }
+
+       private:
+               void read_header(std::istream& is);
+               array<int, 256> read_hist(std::istream& is);
+               vector<PackType> read_data(std::istream& is);
+               long    xs, ys;
+               int     m_channels;
+               std::istream&   i;
+               string type;
+               Image<byte> diff;
+               int row;
+};
+
+ImageRef reader::size()
+{
+       return ImageRef(t->x_size(), t->y_size());
+}
+
+void reader::get_raw_pixel_line(unsigned char* d)
+{
+       t->get_raw_pixel_line(d);
+}
+
+void reader::get_raw_pixel_line(Rgb<byte>* d)
+{
+       t->get_raw_pixel_line(d);
+}
+
+void reader::get_raw_pixel_line(Rgba<byte>* d)
+{
+       t->get_raw_pixel_line(d);
+}
+
+string reader::datatype()
+{
+       return t->datatype();
+}
+string reader::name()
+{
+       return "CVD";
+}
+
+reader::~reader()
+{}
+
+reader::reader(std::istream& i)
+:t(new ReadPimpl(i))
+{}
+
+
+ReadPimpl::ReadPimpl(istream& in)
+:i(in)
+{
+       row = 0;
+       read_header(in);
+       array<int,256> h = read_hist(in);
+
+       diff.resize(ImageRef(xs*m_channels,ys));
+       vector<PackType> d = read_data(in);
+
+       huff_decompress(d, h, diff);
+}
+
+void ReadPimpl::read_header(istream& in)
+{
+       string tmp;
+       getline(in, tmp);
+       //cout << "header-id: '" << tmp << "'" << endl;
+       if (tmp != "CVD") throw 
CVD::Exceptions::Image_IO::MalformedImage(string("Error in CVD image: incorrect 
header ID"));
+
+       getline(in, type);
+       //cout << "type: '" << type << "'" << endl;
+       if (type== "unsigned char") m_channels=1;
+       else if (type== "CVD::Rgb<unsigned char>") m_channels=3;
+       else if (type== "CVD::Rgba<unsigned char>") m_channels=4;
+       else throw CVD::Exceptions::Image_IO::MalformedImage(string("Error in 
CVD image: unknown data type"));
+
+       in >> xs >> ys;
+       //cout << "size: " << xs << "x" << ys << endl;
+
+       getline(in, tmp);
+       //cout << "extras: '" << tmp << "'";
+}
+
+array<int, 256> ReadPimpl::read_hist(std::istream& is)
+{
+       array<int, 256> h;
+       for (unsigned int i = 0; i < h.size(); i++) {
+               h[i] = ((is.get() & 255)<<8) | (is.get()&255);
+       }
+       return h;
+}
+
+vector<PackType> ReadPimpl::read_data(std::istream& is)
+{
+       vector<PackType> data;
+       while ((!is.bad())&&(!is.eof())) {
+               int bits = PackBits;
+               PackType tmp = 0;
+               while (bits>0) {
+                       tmp <<= 8;
+                       tmp |= is.get()&255;
+                       bits-=8;
+               }
+               data.push_back(tmp);
+       }
+       return data;
+}
+
+void ReadPimpl::get_raw_pixel_lines(unsigned char*data, unsigned long nlines)
+{
+       for(unsigned int i=0; i < nlines; i++)  
+       {
+               line_undiff(diff[row], xs*m_channels, data, m_channels);
+               data += xs;
+               row++;
+       }
+}
+
+ReadPimpl::~ReadPimpl()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Compression 
+//
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// CVD writing.
+//
+
+class WritePimpl
+{
+       public:
+               WritePimpl(std::ostream&, int  xsize, int ysize, const string& 
type, const std::string& comm="");
+               int channels(){return m_channels;}
+               long  x_size() const {return xs;}
+               long  y_size() const {return ys;}
+               void    write_raw_pixel_lines(const unsigned char*, unsigned 
long);
+               template<class C>       void write_raw_pixel_line(const C*);
+               ~WritePimpl();
+               
+       private:
+               void write_header(std::ostream& os);
+               void write_hist(std::ostream& os, const array<int, 256>& h);
+               void write_data(std::ostream& os, vector<PackType>& data);
+
+               long    xs, ys, row;
+               int     m_channels;
+               std::ostream&   o;
+               string type;
+               Image<byte> diff;
+};
+
+
+
+WritePimpl::WritePimpl(std::ostream& out, int xsize, int ysize, const string& 
t, const string& comm)
+:o(out)
+{
+       xs = xsize;
+       ys = ysize;
+       type = t;
+       row=0;
+       
+       if(type == "unsigned char")
+               m_channels = 1;
+       else if(type == "CVD::Rgb<unsigned char>")
+               m_channels = 3;
+       else if(type == "CVD::Rgba<unsigned char>")
+               m_channels = 4;
+       else
+               throw Exceptions::Image_IO::UnsupportedImageSubType("CVDimage", 
type);
+
+       diff.resize(ImageRef(xs*m_channels,ys));
+}
+
+void WritePimpl::write_raw_pixel_lines(const unsigned char* data, unsigned 
long nlines)
+{
+       if(nlines + row > (unsigned long) ys)
+               throw CVD::Exceptions::Image_IO::InternalLibraryError("CVD", 
"Write past end of image.");
+       
+       for(unsigned int i=0; i < nlines; i++)  
+       {
+               line_diff(data, xs*m_channels, diff[row], m_channels);
+               data += xs;
+               row++;
+       }
+}
+
+template<class C>      void WritePimpl::write_raw_pixel_line(const C*d)
+{
+       if(type != PNM::type_name<C>::name())
+               throw CVD::Exceptions::Image_IO::WriteTypeMismatch(type, 
PNM::type_name<C>::name());
+
+       write_raw_pixel_lines((const unsigned char*)d, 1); 
+}
+
+void WritePimpl::write_header(std::ostream& os)
+{
+       os << "CVD\n" << type << "\n" << xs << " " << ys << "\n";
+}
+
+void WritePimpl::write_hist(std::ostream& os, const array<int, 256>& h)
+{
+       // have to go through the data anyway, but one might want to copy the
+       // two least significant bytes out of each int, store them in a new
+       // array, and dump that in just one call to ostream::write()
+       for (unsigned int i = 0; i < h.size(); i++) {
+               os.put((h[i]>>8)&255);
+               os.put(h[i]&255);
+       }
+}
+
+void WritePimpl::write_data(std::ostream& os, vector<PackType>& data)
+{
+       // this variant should be safe, but requires one separate call to
+       // ostream::put() for each byte
+       /*for (vector<PackType>::const_iterator it = data.begin(); 
it!=data.end(); ++it) {
+               int bits = PackBits;
+               while (bits>0) {
+                       os.put(((*it)>>(bits-8))&255);
+                       bits-=8;
+               }
+       }*/
+
+       // this variant should be faster, but relies on PackType to be 16bit
+       for (vector<PackType>::iterator it = data.begin(); it!=data.end(); 
++it) *it = htobe16(*it);
+       os.write((const char*)(&(data[0])), data.size()*PackBits/8);
+}
+
+WritePimpl::~WritePimpl()
+{
+       write_header(o);
+
+       array<int, 256> h;
+        create_normalized_hist(diff, h);
+       write_hist(o, h);
+
+       vector<PackType> b = huff_compress(diff, h);
+       write_data(o, b);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Public interfaces to image writing.
+//
+
+writer::writer(ostream& o, ImageRef size, const string& s)
+:t(new WritePimpl(o, size.x, size.y, s))
+{}
+
+writer::~writer()
+{}
+
+void writer::write_raw_pixel_line(const byte* data)
+{
+       t->write_raw_pixel_line(data);
+}
+
+void writer::write_raw_pixel_line(const Rgb<byte>* data)
+{
+       t->write_raw_pixel_line(data);
+}
+
+void writer::write_raw_pixel_line(const Rgba<byte>* data)
+{
+       t->write_raw_pixel_line(data);
+}
+
+}
+}




reply via email to

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