libcvd-members
[Top][All Lists]
Advanced

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

[libcvd-members] libcvd cvd/documentation.h cvd/image_io.h cvd/i...


From: Edward Rosten
Subject: [libcvd-members] libcvd cvd/documentation.h cvd/image_io.h cvd/i...
Date: Thu, 01 Jan 2009 22:29:29 +0000

CVSROOT:        /cvsroot/libcvd
Module name:    libcvd
Changes by:     Edward Rosten <edrosten>        09/01/01 22:29:29

Modified files:
        cvd            : documentation.h image_io.h 
Added files:
        cvd/internal/io: fits.h 
        pnm_src        : fits.cc 

Log message:
        Added simplistic support for FITS reading. 1, 2 and 3D images are 
supported,
        with sizes of 1,2,3 or 4 supported in the 3rd axis.
        
        All native FITS datatypes (uint8, int16, int43, float32, float64) 
supported.
        
        BZERO field ignored, so support for "standard" uint16 is not present.
        
        Tested on rgb8 and monochrome float32 images.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/libcvd/cvd/documentation.h?cvsroot=libcvd&r1=1.22&r2=1.23
http://cvs.savannah.gnu.org/viewcvs/libcvd/cvd/image_io.h?cvsroot=libcvd&r1=1.37&r2=1.38
http://cvs.savannah.gnu.org/viewcvs/libcvd/cvd/internal/io/fits.h?cvsroot=libcvd&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/libcvd/pnm_src/fits.cc?cvsroot=libcvd&rev=1.1

Patches:
Index: cvd/documentation.h
===================================================================
RCS file: /cvsroot/libcvd/libcvd/cvd/documentation.h,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -b -r1.22 -r1.23
--- cvd/documentation.h 1 Jan 2009 22:27:21 -0000       1.22
+++ cvd/documentation.h 1 Jan 2009 22:29:28 -0000       1.23
@@ -48,7 +48,7 @@
                        - PNM   
                        - BMP
                        - FITS
-                         - Support for FITS images of 1, 2 or 3 dimensions.
+                         - Support for FITS images of 1, 2 or 3 dimensions 
(reading only).
                        - PS   (saving only)
                        - EPS  (saving only)
                - External libraries required

Index: cvd/image_io.h
===================================================================
RCS file: /cvsroot/libcvd/libcvd/cvd/image_io.h,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -b -r1.37 -r1.38
--- cvd/image_io.h      5 Aug 2008 23:54:45 -0000       1.37
+++ cvd/image_io.h      1 Jan 2009 22:29:29 -0000       1.38
@@ -36,6 +36,7 @@
 #include <cvd/internal/io/pnm_grok.h>
 #include <cvd/internal/io/save_postscript.h>
 #include <cvd/internal/io/bmp.h>
+#include <cvd/internal/io/fits.h>
 
 
 #ifdef CVD_HAVE_JPEG
@@ -231,6 +232,8 @@
 #endif
          else if(c == 'B')
            BMP::readBMP(im, i);
+         else if(c == 'S')
+           FITS::readFITS(im, i);
          else
            throw Exceptions::Image_IO::UnsupportedImageType();
        }
@@ -331,6 +334,15 @@
        /// Load a PNM image from a stream.
        /// @b Deprecated Use img_load(Image<I>& im, std::istream& i) instead. 
This can handle 
        /// and automatically detect other file formats as well.
+       ///
+       ///     Loading is simplistic, and automatic conversions of values are 
performed.
+       /// So, for instance bytes are assumed to be in the range 0--255 and 
floats in
+       /// the range 0--1, so loading bytes in to an Image<float> will result 
in an
+       /// image with floats in the range 0--1. In the reverse direction, 
+       /// floats falling outside the range 0--1, will wrap when converted to 
bytes.
+       ///
+       /// The image loader ignores the data range given by the file, if it is 
given.
+       ///
        /// @param PixelType The pixel type of the image
        /// @param im The image
        /// @param i The stream

Index: cvd/internal/io/fits.h
===================================================================
RCS file: cvd/internal/io/fits.h
diff -N cvd/internal/io/fits.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ cvd/internal/io/fits.h      1 Jan 2009 22:29:29 -0000       1.1
@@ -0,0 +1,188 @@
+/*                       
+       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_INCLUDE_INTERNAL_IO_FITS_H
+#define CVD_INCLUDE_INTERNAL_IO_FITS_H
+
+#include <iostream>
+#include <memory>
+#include <vector>
+#include <string>
+#include <cvd/image.h>
+#include <cvd/internal/load_and_save.h>
+
+namespace CVD
+{
+namespace FITS
+{
+
+       using CVD::Internal::TypeList;
+       using CVD::Internal::Head;
+
+       //Probably not the best way to deal with FITS. Data is unlikely to be 
RGBA, for
+       //instance. Maybe it would be best to implement loading of tr1::array 
and Vector.
+
+       
////////////////////////////////////////////////////////////////////////////////
+       //
+       // FITS reading
+       //
+
+       class ReadPimpl;
+       class reader
+       {
+               public:
+                       reader(std::istream&);
+                       ~reader();
+
+                       ImageRef size();
+
+                       void get_raw_pixel_line(unsigned char*);
+                       void get_raw_pixel_line(signed short*);
+                       void get_raw_pixel_line(signed int*);
+                       void get_raw_pixel_line(float*);
+                       void get_raw_pixel_line(double*);
+
+                       void get_raw_pixel_line(Rgb<unsigned char>*);
+                       void get_raw_pixel_line(Rgb<signed short>*);
+                       void get_raw_pixel_line(Rgb<signed int>*);
+                       void get_raw_pixel_line(Rgb<float>*);
+                       void get_raw_pixel_line(Rgb<double>*);
+
+                       void get_raw_pixel_line(Rgba<unsigned char>*);
+                       void get_raw_pixel_line(Rgba<signed short>*);
+                       void get_raw_pixel_line(Rgba<signed int>*);
+                       void get_raw_pixel_line(Rgba<float>*);
+                       void get_raw_pixel_line(Rgba<double>*);
+
+                       std::string datatype();
+                       std::string name();
+
+
+                       typedef TypeList<byte, 
+                                       TypeList<signed short,
+                                       TypeList<signed int,
+                                       TypeList<float,
+                                       TypeList<double,
+                                       TypeList<Rgb<byte>, 
+                                       TypeList<Rgb<signed short>, 
+                                       TypeList<Rgb<signed int>, 
+                                       TypeList<Rgb<float>, 
+                                       TypeList<Rgb<double>, 
+                                       TypeList<Rgba<byte>, 
+                                       TypeList<Rgba<signed short>, 
+                                       TypeList<Rgba<signed int>, 
+                                       TypeList<Rgba<float>, 
+                                       TypeList<Rgba<double>, 
+                                                             Head> > > > > > > 
> > > > > > > > Types;
+               
+               private:
+                       ReadPimpl* t; 
+       };
+
+       
+       template <class T> void readFITS(SubImage<T>& im, std::istream& in)
+       {
+               CVD::Internal::readImage<T, CVD::FITS::reader>(im, in);
+       }
+
+       template <class T> void readFITS(Image<T>& im, std::istream& in)
+       {
+               CVD::Internal::readImage<T, CVD::FITS::reader>(im, in);
+       }
+#if 0
+       
////////////////////////////////////////////////////////////////////////////////
+       //
+       // FITS writing, copied and midified from tiff.h
+       //
+
+       template<int g8> struct IntMapper    { typedef unsigned short type;};
+       template<>       struct IntMapper<1> { typedef unsigned char type; };
+
+
+       //Mapping for integral types
+       template<class ComponentIn, int is_integral> struct ComponentMapper_
+       {
+               typedef typename IntMapper< 
(Pixel::traits<ComponentIn>::bits_used > 8) >::type type;
+       };
+
+       //Mapping for non integral types
+       template<class ComponentIn> struct ComponentMapper_<ComponentIn, 0> { 
typedef double type; };
+       template<> struct ComponentMapper_<float, 0> { typedef float type; };
+       
+       template<class ComponentIn> struct ComponentMapper
+       {
+               typedef typename ComponentMapper_<ComponentIn, 
Pixel::traits<ComponentIn>::integral>::type type;
+       };
+       
+       //Mapping for Rgbish types
+       template<class ComponentIn> struct ComponentMapper<Rgb<ComponentIn> >
+       {
+               typedef Rgb<typename ComponentMapper_<ComponentIn, 
Pixel::traits<ComponentIn>::integral>::type> type;
+       };
+
+       template<class ComponentIn> struct ComponentMapper<Rgba<ComponentIn> >
+       {
+               typedef Rgba<typename ComponentMapper_<ComponentIn, 
Pixel::traits<ComponentIn>::integral>::type> type;
+       };
+
+       template<> struct ComponentMapper<Rgb8>
+       {
+               typedef Rgb<byte> type;
+       };
+
+
+       
+       class WritePimpl;
+
+       class writer
+       {
+               public:
+                       writer(std::ostream&, ImageRef size, const std::string& 
type);
+                       ~writer();
+
+                       void write_raw_pixel_line(const unsigned char*);
+                       void write_raw_pixel_line(const unsigned short*);
+                       void write_raw_pixel_line(const float*);
+                       void write_raw_pixel_line(const double*);
+
+                       void write_raw_pixel_line(const Rgb<unsigned char>*);
+                       void write_raw_pixel_line(const Rgb<unsigned short>*);
+                       void write_raw_pixel_line(const Rgb<float>*);
+                       void write_raw_pixel_line(const Rgb<double>*);
+
+                       void write_raw_pixel_line(const Rgba<unsigned char>*);
+                       void write_raw_pixel_line(const Rgba<unsigned short>*);
+                       void write_raw_pixel_line(const Rgba<float>*);
+                       void write_raw_pixel_line(const Rgba<double>*);
+
+                       template<class Incoming> struct Outgoing
+                       {               
+                               typedef typename 
ComponentMapper<Incoming>::type type;
+                       };              
+
+               private:
+                       WritePimpl* t; 
+       };
+       
+#endif 
+
+}
+}
+#endif

Index: pnm_src/fits.cc
===================================================================
RCS file: pnm_src/fits.cc
diff -N pnm_src/fits.cc
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ pnm_src/fits.cc     1 Jan 2009 22:29:29 -0000       1.1
@@ -0,0 +1,375 @@
+/*                       
+       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 "cvd/internal/io/fits.h"
+#include "cvd/image_io.h"
+#include "cvd/config.h"
+#include <tiffio.h>
+#include <algorithm>
+#include <vector>
+#include <deque>
+#include <iostream>
+#include <sstream>
+
+using namespace CVD;
+using namespace CVD::FITS;
+using namespace CVD::Exceptions::Image_IO;
+using namespace std;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Private implementation of FITS reading
+//
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Useful string manipulation functions
+//
+
+
+//Trim off whitespace on the right hand side
+static string rtrim(string str)
+{
+       string ws (" \t\f\v\n\r");
+       size_t pos;
+  
+       pos=str.find_last_not_of(ws);
+       if (pos!=string::npos)
+               str.erase(pos+1);
+       else
+               str.clear();
+
+    return str;
+}
+
+//Trim off whitespace on the left hand side
+static string ltrim(const string& str)
+{
+       string ws (" \t\f\v\n\r");
+       size_t pos;
+  
+       pos=str.find_first_not_of(ws);
+       if (pos!=string::npos)
+               return string(str.begin()+pos, str.end());
+       else
+               return "";
+}
+
+
+static bool get_bool(const string& s)
+{
+       if(s == "T")
+               return 1;
+       else if (s == "F")
+               return 0;
+       else
+               throw(Exceptions::Image_IO::MalformedImage("Invalid boolean: `" 
+ s + "'"));
+}
+
+static int get_int(const string& s)
+{
+       int i;
+       istringstream is(s);
+       is >> i;
+
+       if(is.bad())
+               throw(Exceptions::Image_IO::MalformedImage("Invalid integer: `" 
+ s + "'"));
+       return i;
+}
+
+static int get_uint(const string& s)
+{
+       unsigned int i;
+       istringstream is(s);
+       is >> i;
+
+       if(is.bad())
+               throw(Exceptions::Image_IO::MalformedImage("Invalid unsigned 
integer: `" + s + "'"));
+       return i;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Private implementation of FITS reading
+//
+
+class CVD::FITS::ReadPimpl
+{
+       public:
+               ReadPimpl(istream&);
+               ~ReadPimpl();
+               ImageRef size();
+               string datatype();
+               template<class C> void get_raw_pixel_line(C* data);
+
+       private:
+               istream& i;
+               unsigned long row;
+               ImageRef my_size;
+               string   type;
+       
+               //HDU is the FITS term: header description units.
+               //The HDU has multiple 36 card stacks of 80 column cards.
+               //which is 2880 bytes
+               char HDU_card_stack[2880], *card;
+
+               void next_card()
+               {
+                       if(card != NULL)
+                                       card += 80;
+
+                       if(card == NULL || card == HDU_card_stack + 2880)
+                       {       
+                               i.read(HDU_card_stack, 2880);
+                               if(i.eof())
+                                       
throw(Exceptions::Image_IO::MalformedImage("EOF in header."));
+
+                               card =  HDU_card_stack;
+                       }
+               }
+
+               bool match_card_start(const string& s)
+               {
+                       if(s.size() > 80)
+                               return 0;
+                       return equal(s.begin(), s.end(), card);
+               }
+               
+               //keywords are left justified, in columns 1--8
+               string get_keyword()
+               {
+                       string k;
+                       k.resize(8);
+                       copy(card, card+8, k.begin());
+                       return rtrim(k);
+               }
+
+               void check_for_seperator()
+               {
+                       if(card[8] != '=' || card[9] != ' ')
+                               
throw(Exceptions::Image_IO::MalformedImage("Missing `= ' separator in card."));
+               }
+
+               void expect_keyword(const string& k)
+               {
+                       check_for_seperator();
+                       if(k != get_keyword())
+                               throw 
Exceptions::Image_IO::MalformedImage("FITS images missing "+k+"(got" + 
get_keyword() + ")");
+               }
+
+               //numeric fields are right justified, in columns 11--30
+               string get_numeric_field()
+               {
+                       string f;
+                       f.resize(20);
+                       copy(card+10, card+30, f.begin());
+                       return ltrim(f);
+               }
+
+               vector<unsigned char> data;
+               int bytes_per_pixel;
+
+};
+
+
+template<class T> void ReadPimpl::get_raw_pixel_line(T* d)
+{
+       if(datatype() != PNM::type_name<T>::name())
+               throw ReadTypeMismatch(datatype(), PNM::type_name<T>::name());
+
+       if(row  > (unsigned long)my_size.y)
+               throw InternalLibraryError("CVD", "Read past end of image.");
+
+       unsigned char* rowp = &data[row * bytes_per_pixel * my_size.x];
+       row++;
+       copy(rowp, rowp + my_size.x * bytes_per_pixel,  (unsigned char*)(d));
+}
+
+string ReadPimpl::datatype()
+{
+       return type;
+}
+
+ImageRef ReadPimpl::size()
+{
+       return my_size;
+}
+
+ReadPimpl::~ReadPimpl()
+{      
+}
+
+
+ReadPimpl::ReadPimpl(istream& is)
+:i(is),row(0),card(NULL)
+{
+       next_card();
+       if(!match_card_start("SIMPLE  =                    T"))
+               throw(Exceptions::Image_IO::MalformedImage("FITS images must 
start with \"SIMPLE  =                    T\""));
+
+       next_card();
+       expect_keyword("BITPIX");
+       int bpp = get_int(get_numeric_field());
+
+       if(bpp == 8)
+               type = PNM::type_name<byte>::name();
+       else if(bpp == 16)
+               type = PNM::type_name<short>::name();
+       else if(bpp == 32)
+               type = PNM::type_name<int>::name();
+       else if(bpp == -32)
+               type = PNM::type_name<float>::name();
+       else if(bpp == -64)
+               type = PNM::type_name<double>::name();
+       else
+               throw Exceptions::Image_IO::MalformedImage("FITS images has 
unrecognised BITPIX (" + get_numeric_field() + ")");
+               
+       
+       unsigned int num_axes;
+       next_card();
+       expect_keyword("NAXIS");
+       num_axes=get_uint(get_numeric_field());
+
+       if(num_axes < 1 || num_axes>3)
+               throw Exceptions::Image_IO::UnsupportedImageSubType("FITS", 
get_numeric_field() + " axes given (1, 2 or 3 supported).");
+       
+       //Read in the axis lengths
+       //select obvious defailts for missing axes
+       int a1=0, a2=1, a3=1;
+       next_card();
+       expect_keyword("NAXIS1");
+       a1 = get_uint(get_numeric_field());
+
+       if(num_axes > 1)
+       {
+               next_card();
+               expect_keyword("NAXIS2");
+               a2 = get_uint(get_numeric_field());
+
+               if(num_axes > 2)
+               {
+                       next_card();
+                       expect_keyword("NAXIS3");
+                       a3 = get_uint(get_numeric_field());
+               }
+       }
+
+       //Figure out the colourspace
+       if(a3 == 1)
+               type = type;
+       else if(a3 == 2)
+               type = "CVD::GreyAlpha<" + type  + ">";
+       else if(a3 == 3)
+               type = "CVD::Rgb<" + type  + ">";
+       else if(a3 == 4)
+               type = "CVD::Rgba<" + type  + ">";
+       else 
+               throw Exceptions::Image_IO::UnsupportedImageSubType("FITS", 
"3rd axis (colour planes) has"+ get_numeric_field() + " elements(1, 2, 3 or 4 
supported).");
+
+       my_size.x = a1;
+       my_size.y = a2;
+
+       //Read the rest of the header
+       //The last useful card has END as the first keyword, but no separator.
+       //The remaining cards in the current stack should be blank.
+       //Since we read a stack at a time, the read pointer will be in the
+       //correct place.
+       for(;;)
+       {
+               next_card();
+               if(get_keyword() == "END")
+                       break;
+       }
+
+       //We should really use BZERO, too.
+       
+       //Images are planar. So, deplanarize here.
+       //Also, correct the endianness
+       //FIXME this could be much more efficient.
+       bpp = abs(bpp)/8;
+       
+       size_t nelems = a1 * a2 * a3;
+       size_t nbytes = nelems * bpp;
+       vector<unsigned char> raw_data;
+       raw_data.resize(nbytes);
+       data.resize(nbytes);
+       i.read((char*)(&raw_data[0]), nbytes);
+
+       if(i.eof())
+               throw(Exceptions::Image_IO::MalformedImage("EOF in image."));
+               
+
+       //Make the data follow the native byte ordering
+       #ifdef CVD_ARCH_LITTLE_ENDIAN
+               for(size_t i=0; i < nelems; i++)
+                       reverse(&raw_data[i*bpp], &raw_data[i*bpp] + bpp);
+       #endif
+       
+       //Convert planar to inline
+       for(int c=0; c < a1; c++)
+               for(int r=0; r < a2; r++)
+                       for(int p=0; p < a3; p++)
+                               for(int b=0; b < bpp; b++)
+                                               data[((r * a1 + c)*a3 + p)*bpp 
+ b] = raw_data[p*a1*a2*bpp+ (r*a1+c)*bpp+b];
+       
+       bytes_per_pixel = a3 * bpp;
+}
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Implementation of public parts of TIFF reading
+//
+
+reader::reader(istream& i)
+:t(new ReadPimpl(i))
+{}
+
+reader::~reader()
+{
+       delete t;
+};
+
+string reader::datatype()
+{
+       return t->datatype();
+}
+
+string reader::name()
+{
+       return "FITS";
+}
+
+ImageRef reader::size()
+{
+       return t->size();
+};
+
+//Mechanically generate the pixel reading calls.
+#define GEN1(X) void reader::get_raw_pixel_line(X*d){t->get_raw_pixel_line(d);}
+#define GEN3(X) GEN1(X) GEN1(Rgb<X>) GEN1(Rgba<X>)
+
+GEN3(unsigned char)
+GEN3(signed short)
+GEN3(signed int)
+GEN3(float)
+GEN3(double)




reply via email to

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