My old project for strange attractors
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.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

160 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