00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef BMP_H
00022 #define BMP_H
00023
00024 #include <iostream>
00025 #include <string>
00026 #include <memory>
00027 #include <vector>
00028
00029 #include <cvd/image.h>
00030 #include <cvd/byte.h>
00031 #include <cvd/internal/convert_pixel_types.h>
00032 #include <cvd/internal/load_and_save.h>
00033 #include <cvd/internal/simple_vector.h>
00034
00035 namespace CVD {
00036 namespace BMP {
00037 void writeBMPHeader(unsigned int width, unsigned int height, unsigned int channels, std::ostream& out);
00038 void readBMPHeader(unsigned int& width, unsigned int& height, unsigned int& channels, unsigned int& compression, std::istream& in);
00039
00040 template <class T, int Channels> struct BMPReader;
00041
00042 template <class T> struct BMPReader<T,1> {
00043 static void read(Image<T>& im, std::istream& in) {
00044 Internal::simple_vector<Rgb<byte> > palette(256);
00045 bool notgray = false;
00046 for (int i=0; i<256; i++) {
00047 byte buf[4];
00048 in.read((char*)buf,4);
00049 palette[i].red = buf[2];
00050 palette[i].green = buf[1];
00051 palette[i].blue = buf[0];
00052 if (buf[0] != i || buf[0] != buf[1] || buf[1] != buf[2])
00053 notgray = true;
00054 }
00055 size_t rowSize = im.size().x;
00056 if (rowSize % 4)
00057 rowSize += 4 - (rowSize%4);
00058 Internal::simple_vector<byte> rowbuf(rowSize);
00059
00060 if (notgray) {
00061 std::cerr << "not gray" << std::endl;
00062 Internal::simple_vector<T> cvt(256);
00063 Pixel::ConvertPixels<Rgb<byte>,T>::convert(&palette[0], &cvt[0], 256);
00064 for (int r=im.size().y-1; r>=0; r--) {
00065 in.read((char*)&rowbuf[0], static_cast<std::streamsize>(rowSize));
00066 for (int c=0; c<im.size().x; c++)
00067 im[r][c] = cvt[rowbuf[c]];
00068 }
00069 } else {
00070 for (int r=im.size().y-1; r>=0; r--) {
00071 in.read((char*)&rowbuf[0], static_cast<std::streamsize>(rowSize));
00072 Pixel::ConvertPixels<byte,T>::convert(&rowbuf[0], im[r], im.size().x);
00073 }
00074 }
00075 }
00076 };
00077 template <class T> struct BMPReader<T,3> {
00078 static void read(Image<T>& im, std::istream& in) {
00079 size_t rowSize = im.size().x*3;
00080 if (rowSize % 4)
00081 rowSize += 4 - (rowSize%4);
00082 Internal::simple_vector<byte> rowbuf(rowSize);
00083 for (int r=im.size().y-1; r>=0; r--) {
00084 in.read((char*)&rowbuf[0], static_cast<std::streamsize>(rowSize));
00085 for (int c=0; c<im.size().x*3; c+=3) {
00086 byte tmp = rowbuf[c];
00087 rowbuf[c] = rowbuf[c+2];
00088 rowbuf[c+2] = tmp;
00089 }
00090 Pixel::ConvertPixels<Rgb<byte>, T>::convert((Rgb<byte>*)&rowbuf[0], im[r], im.size().x);
00091 }
00092 }
00093 };
00094
00095 template <class T> void readBMP(Image<T>& im, std::istream& in) {
00096 unsigned int w,h,ch, comp;
00097 readBMPHeader(w,h,ch,comp,in);
00098
00099 im.resize(ImageRef(w,h));
00100 if (ch == 1)
00101 BMPReader<T,1>::read(im, in);
00102 else
00103 BMPReader<T,3>::read(im,in);
00104 }
00105
00106 template <class T> void readBMP(BasicImage<T>& im, std::istream& in) {
00107 unsigned int w,h,ch, comp;
00108 readBMPHeader(w,h,ch,comp,in);
00109 if (comp || (ch != 3 && ch != 1))
00110 throw CVD::Exceptions::Image_IO::UnsupportedImageType();
00111
00112 ImageRef size(w, h);
00113 if(im.size() != size)
00114 throw Exceptions::Image_IO::ImageSizeMismatch(size, im.size());
00115
00116 if (ch == 1)
00117 BMPReader<T,1>::read(im, in);
00118 else
00119 BMPReader<T,3>::read(im,in);
00120 }
00121
00122 template <class T, int Channels> struct BMPWriter;
00123 template <class T> struct BMPWriter<T,1> {
00124 static void write(const BasicImage<T>& im, std::ostream& out) {
00125 writeBMPHeader(im.size().x, im.size().y, 1, out);
00126 int rowSize = im.size().x;
00127 if (rowSize % 4)
00128 rowSize += 4 - (rowSize % 4);
00129 Internal::simple_vector<byte> rowbuf(rowSize);
00130 for (int r=im.size().y-1; r>=0; r--) {
00131 Pixel::ConvertPixels<T,byte>::convert(im[r], &rowbuf[0], im.size().x);
00132 out.write((const char*)&rowbuf[0], rowSize);
00133 }
00134 }
00135 };
00136 template <> struct BMPWriter<byte,1> {
00137 static void write(const BasicImage<byte>& im, std::ostream& out) {
00138 writeBMPHeader(im.size().x, im.size().y, 1, out);
00139 int pad = (im.size().x % 4) ? (4 - (im.size().x % 4)) : 0;
00140 char zeros[4]={0,0,0,0};
00141 for (int r=im.size().y-1; r>=0; r--) {
00142 out.write((const char*)im[r], im.size().x);
00143 if (pad)
00144 out.write(zeros,pad);
00145 }
00146 }
00147 };
00148
00149 template <class T> struct BMPWriter<T,3> {
00150 static void write(const BasicImage<T>& im, std::ostream& out) {
00151 writeBMPHeader(im.size().x, im.size().y, 3, out);
00152 int rowSize = im.size().x*3;
00153 if (rowSize % 4)
00154 rowSize += 4 - (rowSize % 4);
00155 Internal::simple_vector<byte> rowbuf(rowSize);
00156 for (int r=im.size().y-1; r>=0; r--) {
00157 Pixel::ConvertPixels<T,Rgb<byte> >::convert(im[r], (Rgb<byte>*)&rowbuf[0], im.size().x);
00158 for (int c=0; c<im.size().x*3; c+=3) {
00159 byte tmp = rowbuf[c];
00160 rowbuf[c] = rowbuf[c+2];
00161 rowbuf[c+2] = tmp;
00162 }
00163 out.write((const char*)&rowbuf[0], rowSize);
00164 }
00165 }
00166 };
00167 template <class T> struct BMPWriterChooser { enum { channels = 1}; };
00168 template <class T> struct BMPWriterChooser<Rgb<T> > { enum { channels = 3}; };
00169
00170 template <class T> void writeBMP(const BasicImage<T>& im, std::ostream& out) {
00171 BMPWriter<T,BMPWriterChooser<T>::channels>::write(im,out);
00172 }
00173 }
00174 }
00175
00176 #endif