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.
148 lines
3.0 KiB
148 lines
3.0 KiB
13 years ago
|
//
|
||
|
// 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 <ostream>
|
||
|
#include <fstream>
|
||
|
#include <stdexcept>
|
||
|
#include <tr1/memory>
|
||
|
|
||
|
struct pixel {
|
||
|
friend class Image;
|
||
|
|
||
|
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))
|
||
|
{}
|
||
|
|
||
|
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 <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(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<const char*>(this), header_sz);
|
||
|
}
|
||
|
|
||
|
unsigned int bytes(){
|
||
|
return width*height*bitspp/8;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template <typename P = pixel, typename DIBT = bitmapcoreheader>
|
||
|
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<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 DIBT = bitmapcoreheader>
|
||
|
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())
|
||
|
{
|
||
|
header.write(file);
|
||
|
dib_header.write(file);
|
||
|
}
|
||
|
|
||
|
bitmap_stream& operator<<(pixel const & p){
|
||
|
file.write(&p, 3);
|
||
|
++x;
|
||
|
if (x >= dib_header.width){
|
||
|
x = 0;
|
||
|
++y;
|
||
|
}
|
||
|
if (y >= dib_header.height){
|
||
|
throw std::out_of_range("Writing BMP image out of bounds.");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
DIBT dib_header;
|
||
|
bitmap_file_header header;
|
||
|
std::ofstream file;
|
||
|
|
||
|
uint16_t x;
|
||
|
uint16_t y;
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|