Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
256 lines (210 sloc) 8.49 KB
//
// bmp loader
// 2015年ぐらいに作ったC言語のやつを書き直し
// 殆ど忘れたので直すべきところがまだ大量に残ってる
// とりあえずmallocは消す
// char => uint形式に変えた
//
// todo: private
// todo: ファイル入出力がC言語
namespace Img {
struct RGB {
uint8_t b;
uint8_t g;
uint8_t r;
RGB(int b = 0, int g = 0, int r = 0) :b(b), g(g), r(r) {}
inline uint32_t val() const { return (uint32_t)(r << 16) | (uint32_t)(g << 8) | (uint32_t)(b); }
inline bool operator==(const RGB& e) const { return b == e.b&&g == e.g&&r == e.r; }
inline bool operator!=(const RGB& e) const { return b != e.b || g != e.g || r != e.r; }
inline bool operator <(const RGB& e) const { return val() < e.val(); }
};
class Bitmap {
uint8_t fileHeader[18];
uint8_t infoHeader[36];
inline uint8_t* fh_type() { return fileHeader; }
inline uint32_t& fh_size() { return *(uint32_t*)(fileHeader + 2); }
inline uint16_t& fh_reserved1() { return *(uint16_t*)(fileHeader + 6); }
inline uint16_t& fh_reserved2() { return *(uint16_t*)(fileHeader + 8); }
inline uint32_t& fh_offsetBit() { return *(uint32_t*)(fileHeader + 10); }
inline uint32_t& fh_infosize() { return *(uint32_t*)(fileHeader + 14); }
inline uint32_t& ih_width() { return *(uint32_t*)(infoHeader + 0); }
inline uint32_t& ih_height() { return *(uint32_t*)(infoHeader + 4); }
inline uint16_t& ih_planes() { return *(uint16_t*)(infoHeader + 8); }
inline uint16_t& ih_bitcount() { return *(uint16_t*)(infoHeader + 10); }
inline uint32_t& ih_compression() { return *(uint32_t*)(infoHeader + 12); }
inline uint32_t& ih_sizeimage() { return *(uint32_t*)(infoHeader + 16); }
inline uint32_t& ih_xdpm() { return *(uint32_t*)(infoHeader + 20); }
inline uint32_t& ih_ydpm() { return *(uint32_t*)(infoHeader + 24); }
inline uint32_t& ih_cused() { return *(uint32_t*)(infoHeader + 28); }
inline uint32_t& ih_cimp() { return *(uint32_t*)(infoHeader + 32); }
public:
int width, height;
vector<RGB> raw;
Bitmap() {}
Bitmap(int w, int h) { resize(w, h); }
void resize(int w, int h) {
width = w; height = h;
raw.resize(w*h * 3 + 3);
}
inline RGB& operator()(int x, int y) { return raw[y*width + x]; }
inline RGB operator()(int x, int y) const { return raw[y*width + x]; }
bool load(const char* filename);
bool save(const char* filename);
};
bool Bitmap::load(const char* filename) {
int bit_pix, cpxtype, colornum;
ifstream ifs(filename, ios::in | ios::binary);
if (!ifs) {
//fprintf(stderr,"loadbmp:failed open file\n");
return false;
}
// read header + infosize
ifs.read((char*)(&fileHeader), 18);
// "BM"であることを調べる
if (fh_type()[0] != 'B' || fh_type()[1] != 'M') {
//fprintf(stderr,"loadbmp:not bmp file\n");
return false;
}
// 情報ヘッダのサイズが40のヘッダでなければ
// 読み込まない(思考放棄)
if (fh_infosize() != 40) {
// fprintf(stderr,"loadbmp:not INFO type\n");
goto loadbmp_close;
}
// 続きを読み込む(INFO)
ifs.read((char*)(&infoHeader), 36);
// bitfield持ってるor圧縮されたファイルは
// 読み込まない(思考放棄)
cpxtype = ih_compression();
if (cpxtype == 3) {
// fprintf(stderr,"loadbmp:bitfields\n");
goto loadbmp_close;
}
if (cpxtype != 0) {
// fprintf(stderr,"loadbmp:compressed bmp\n");
goto loadbmp_close;
}
// bit per pixel
bit_pix = ih_bitcount();
// ビットフィールドのファイルを読み込まない
// (放棄)
if (bit_pix == 16 || bit_pix == 32) {
// fprintf(stderr,"loadbmp:palette bmp\n");
goto loadbmp_close;
}
if (bit_pix == 24) {
// 24bitImage
// カラーインデックス数(24bitパレット)
if (ih_cused() > 1) {
// fprintf(stderr,"loadbmp:3byte palette\n");
goto loadbmp_close;
}
// image構造体作成
width = ih_width();
height = ih_height();
raw.resize(width*height + 3);
// イメージデータサイズは信用しない
// イメージデータオフセットの適応
if (fh_offsetBit() != 0)
ifs.seekg(fh_offsetBit());
// note:行データは4nbyteでなければならない
int l = (width * 3 + 3) / 4;
for (int i = 0; i < height; i++)
ifs.read((char*)(&(raw[0])) + i * 3 * width, 4 * l);
// 最後も同様に操作すると一般にオーバーフローするよ
// image型に助長を含ませる対策
}
// else if (bit_pix == 1 || bit_pix == 4 || bit_pix == 8) {
// // palette Image
//
// // カラーインデックス数
// colornum = *(int*)(bih.cused);
// if (colornum == 0) colornum = 1 << bit_pix;
//
// // パレットイメージ作成
// imagepat = createimagePat(*(int*)(bih.width), *(int*)(bih.height), colornum);
// // パレット読み込み
// fread(imagepat->palette, 4, colornum, fp);
//
// //
// // イメージデータサイズは信用しない
// // イメージデータオフセットの適応
// if (*(int*)(bfh.offsetBit) != 0)
// fseek(fp, *(int*)(bfh.offsetBit), SEEK_SET);
//
// // note:行データは4nbyteでなければならない
// l = ((imagepat->width)*bit_pix + 31) / 32;
// for (i = 0; i < (imagepat->height); i++)
// fread(&(imagepat->data[i*(imagepat->width)]), 4, l, fp);
//
// image = convertImage(imagepat);
//
// // パレット画像は解放
// freeimagePat(imagepat);
// }
else {
// ピクセル毎のビット数が不明
// fprintf(stderr,"loadbmp:bitcount error\n");
goto loadbmp_close;
}
ifs.close();
return true;
loadbmp_close:
ifs.close();
return false;
}
// -------------------------------------------
// save
// -------------------------------------------
bool Bitmap::save(const char *filename) {
int imagesize;
int i, l;
ofstream ofs(filename, ios::out | ios::binary);
if (!ofs) return false;
// note:行データは4nbyteでなければならない
l = (width * 3 + 3) / 4;
imagesize = l * 4 * height;
// fileHeader
fh_type()[0] = 'B';
fh_type()[1] = 'M';
fh_size() = 54 + imagesize; // filesize
fh_reserved1() = 0;
fh_reserved2() = 0;
fh_offsetBit() = 54;
// infomationHeader INFO
fh_infosize() = 40;
ih_width() = width;
ih_height() = height;
ih_planes() = 1;
ih_bitcount() = 24;
ih_compression() = 0;
ih_sizeimage() = 0; //imagesize;
ih_xdpm() = 0;
ih_ydpm() = 0;
ih_cused() = 0; // nopalette
ih_cimp() = 0; //clrImpt
ofs.write((const char*)fileHeader, 18);
ofs.write((const char*)infoHeader, 36);
for (i = 0; i < height; i++)
ofs.write((char*)(&(raw[0])) + i * 3 * width, 4 * l);
//本来は末端はゴミではなく0で埋めるべき
// 最後も同様に操作すると一般にオーバーフローするよ
// image型に助長を含ませる対策
return true;
}
}
/*
Img::Bitmap bmp;
assert(bmp.load(filename));
{
Img::Bitmap bmp_work = bmp_work;
for (int y = 0; y < bmp_work.height; ++y) {
for (int x = 0; x < bmp_work.width / 2; ++x) {
swap(bmp_work(x, y), bmp_work(bmp_work.width - x - 1, y));
bmp_work(x, y).r = bmp_work(x, y).g = bmp_work(x, y).b
= (bmp_work(x, y).r + bmp_work(x, y).g + bmp_work(x, y).b) / 3;
}
}
assert(bmp_work.save(filename_out1));
}
*/