You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
159 lines
3.4 KiB
159 lines
3.4 KiB
//
|
|
// ImageFormatBMP.hpp
|
|
// AwesomeAttractorND
|
|
//
|
|
// Created by Joshua Moerman on 11/12/11.
|
|
// Copyright 2011 Vadovas. All rights reserved.
|
|
//
|
|
|
|
#ifndef AwesomeAttractorND_ImageFormatBMP_hpp
|
|
#define AwesomeAttractorND_ImageFormatBMP_hpp
|
|
|
|
#include <ostream>
|
|
#include <fstream>
|
|
#include <stdexcept>
|
|
#include <algorithm>
|
|
|
|
namespace ImageFormats {
|
|
namespace bmp {
|
|
struct pixelBGR{
|
|
pixelBGR(double red, double green, double blue)
|
|
: blue(clamp(255*blue))
|
|
, green(clamp(255*green))
|
|
, red(clamp(255*red))
|
|
{}
|
|
|
|
pixelBGR(int red, int green, int blue)
|
|
: blue(clamp(blue))
|
|
, green(clamp(green))
|
|
, red(clamp(red))
|
|
{}
|
|
|
|
void swapRB(){
|
|
std::swap(red, blue);
|
|
}
|
|
|
|
private:
|
|
uint8_t clamp(int n){
|
|
return std::min(255, std::max(0, n));
|
|
}
|
|
|
|
uint8_t blue;
|
|
uint8_t green;
|
|
uint8_t red;
|
|
};
|
|
|
|
struct bitmap_file_header {
|
|
uint32_t filesize;
|
|
uint16_t creator1;
|
|
uint16_t creator2;
|
|
uint32_t bmp_offset;
|
|
|
|
template <typename DIBT>
|
|
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<const char*>(this), 12);
|
|
}
|
|
};
|
|
|
|
struct bitmapcoreheader {
|
|
uint32_t header_sz;
|
|
uint16_t width;
|
|
uint16_t height;
|
|
uint16_t nplanes;
|
|
uint16_t bitspp;
|
|
|
|
bitmapcoreheader(uint16_t width, uint16_t height, uint16_t bitspp = 24):
|
|
header_sz(sizeof(bitmapcoreheader)),
|
|
width(width),
|
|
height(height),
|
|
nplanes(1),
|
|
bitspp(bitspp){}
|
|
|
|
void write(std::ostream& out) const {
|
|
out.write(reinterpret_cast<const char*>(this), header_sz);
|
|
}
|
|
|
|
uint32_t bytes(){
|
|
return width*height*bitspp/8;
|
|
}
|
|
};
|
|
|
|
template <typename P = pixelBGR, typename DIBT = bitmapcoreheader>
|
|
struct bitmap {
|
|
typedef P pixel;
|
|
|
|
bitmap(uint16_t width, uint16_t height)
|
|
: dib_header(width, height, sizeof(pixel)*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<char>(out));
|
|
std::copy((char const *)data, (char const *)data + dib_header.bytes(), std::ostream_iterator<char>(out));
|
|
}
|
|
|
|
private:
|
|
DIBT dib_header;
|
|
bitmap_file_header header;
|
|
P const * data;
|
|
};
|
|
|
|
template <typename P = pixelBGR, typename DIBT = bitmapcoreheader>
|
|
struct bitmap_stream {
|
|
typedef P pixel;
|
|
|
|
bitmap_stream(uint16_t width, uint16_t height, std::string filename)
|
|
: dib_header(width, height, sizeof(pixel)*8)
|
|
, 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, sizeof(pixel));
|
|
++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
|
|
|