// // Image.hpp // AwesomeAttractorND // // Created by Joshua Moerman on 11/2/11. // Copyright 2011 Vadovas. All rights reserved. // #ifndef AwesomeAttractorND_Image_hpp #define AwesomeAttractorND_Image_hpp #include #include #include #include struct pixel { pixel(double red, double green, double blue) : red(clamp(255*red)) , green(clamp(255*green)) , blue(clamp(255*blue)) {} pixel(int red, int green, int blue) : red(clamp(red)) , green(clamp(green)) , blue(clamp(blue)) {} void swapRB(){ std::swap(red, blue); } private: uint8_t clamp(int n){ return std::min(255, std::max(0, n)); } uint8_t red; uint8_t green; uint8_t blue; }; namespace ImageFormats { namespace bmp { struct bitmap_file_header { uint32_t filesize; uint16_t creator1; uint16_t creator2; uint32_t bmp_offset; template bitmap_file_header(DIBT dib_header): filesize(dib_header.bytes() + dib_header.header_sz + 12 + 2), creator1(0), creator2(0), bmp_offset(dib_header.header_sz + 12 + 2){} void write(std::ostream& out) const { out << "BM"; out.write(reinterpret_cast(this), 12); } }; struct bitmapcoreheader { uint32_t header_sz; uint16_t width; uint16_t height; uint16_t nplanes; uint16_t bitspp; bitmapcoreheader(int width, int height, int bitspp = 24): header_sz(sizeof(bitmapcoreheader)), width(width), height(height), nplanes(1), bitspp(bitspp){} void write(std::ostream& out) const { out.write(reinterpret_cast(this), header_sz); } unsigned int bytes(){ return width*height*bitspp/8; } }; template struct bitmap { bitmap(int width, int height) : dib_header(width, height, sizeof(P)*8) , header(dib_header) , data(0) {} void write(std::string const & filename){ std::ofstream file(filename.c_str()); write(file); } void write(std::ostream& out){ header.write(out); dib_header.write(out); //std::copy_n((char const *)data, dib_header.bytes(), std::ostream_iterator(out)); std::copy((char const *)data, (char const *)data + dib_header.bytes(), std::ostream_iterator(out)); } private: DIBT dib_header; bitmap_file_header header; P const * data; }; template struct bitmap_stream { typedef pixel pixel; bitmap_stream(int width, int height, std::string filename) : dib_header(width, height) , header(dib_header) , file(filename.c_str()) , x(0) , y(0) { if(!file) throw std::runtime_error("bitmap file could not be opened."); header.write(file); dib_header.write(file); } bitmap_stream& operator<<(pixel const & p){ if (y >= dib_header.height){ throw std::out_of_range("Writing BMP image out of bounds."); } pixel p2(p); p2.swapRB(); file.write((char const *)&p2, 3); ++x; if (x >= dib_header.width){ x = 0; ++y; } return *this; } private: DIBT dib_header; bitmap_file_header header; std::ofstream file; uint16_t x; uint16_t y; }; } } #endif