Skip to content

Instantly share code, notes, and snippets.

@techno-tanoC techno-tanoC/bmpProc.cpp
Last active Mar 20, 2019

Embed
What would you like to do?
#include <cstdio>
#include <iostream>
#include <cstring>
#include <time.h>
#include <stdio.h>
#define FILE_HEADER_SIZE 14
#define INFO_HEADER_SIZE 40
#define NOTE_PAD_WIDTH 315;
using namespace std;
//ファイルヘッダ構造体
typedef struct FileHeader{
unsigned char data[FILE_HEADER_SIZE];
string fileType;
int fileSize;
} FileHeader;
//情報ヘッダ構造体
typedef struct InfoHeader{
unsigned char data[INFO_HEADER_SIZE];
int infoHeaderSize;
int width;
int height;
int clrPerPixel;
int dataSize;
} InfoHeader;
//ピクセルの色情報構造体
typedef struct Color{
int r;
int g;
int b;
}Color;
int bit2Integer(unsigned char b1, unsigned char b2, unsigned char b3, unsigned char b4);
//ビットマップ処理クラス
class BitMapProcessor{
FILE *bmp; //ビットマップのファイルポインタ
unsigned char *img; //
unsigned char *org;
FileHeader fHeader;
InfoHeader iHeader;
public:
BitMapProcessor(){
bmp = NULL;
img = NULL;
org = NULL;
cout << "コンストラクタが呼ばれました" << endl;
};
‾BitMapProcessor(){
fclose(bmp);
delete []img;
delete []org;
cout << "デストラクタが呼ばれました" << endl;
};
void loadData(string filename);
void dispBmpInfo();
void writeData(string filename);
Color getColor(int row, int col);
void setColor(int row, int col, int r, int g, int b);
void restore();
int height() { return iHeader.height; };
int width() { return iHeader.width; };
private:
void readFileHeader();
void readInfoHeader();
void readBmpData();
};
int bit2Integer(unsigned char b1, unsigned char b2, unsigned char b3, unsigned char b4){
return b1 +
b2 * 256 +
b3 * 256 * 256 +
b4 * 256 * 256 * 256;
}
//
void BitMapProcessor :: loadData(string filename){
if (bmp != NULL)
fclose(bmp);
bmp = fopen(filename.c_str(), "rb");
if (bmp == NULL)
{
printf("ファイルオープンに失敗しました¥n");
exit(0);
}
readFileHeader();
readInfoHeader();
readBmpData();
}
//ファイルヘッダを読む
void BitMapProcessor :: readFileHeader(){
unsigned char data[FILE_HEADER_SIZE];
/* size_t size = */ fread(data, sizeof(unsigned char), FILE_HEADER_SIZE, bmp);
memcpy(fHeader.data, data, sizeof(data));
fHeader.fileType = "";
fHeader.fileType += data[0];
fHeader.fileType += data[1];
fHeader.fileSize = bit2Integer(data[2], data[3], data[4], data[5]);
}
//情報ヘッダを読む
void BitMapProcessor :: readInfoHeader(){
unsigned char data[INFO_HEADER_SIZE];
/* size_t size = */ fread(data, sizeof(unsigned char), INFO_HEADER_SIZE, bmp);
memcpy(iHeader.data, data, sizeof(data));
iHeader.infoHeaderSize = bit2Integer(data[0], data[1], data[2], data[3]);
iHeader.width = bit2Integer(data[4], data[5], data[6], data[7]);
iHeader.height = bit2Integer(data[8], data[9], data[10], data[11]);
iHeader.clrPerPixel = bit2Integer(data[14], data[15], 0, 0);
iHeader.dataSize = bit2Integer(data[20], data[21], data[22], data[23]);
}
//画像データを読む
void BitMapProcessor :: readBmpData(){
if (img != NULL)
delete []img;
unsigned int sz = iHeader.dataSize;
img = new unsigned char [sz];
size_t size = fread(img, sizeof(unsigned char), sz, bmp);
if (size != sz)
{
printf("画像データ読み込みのサイズが矛盾しています(´・ω・`) ");
exit(0);
}
//バックアップ用にorgに画像データをコピー
if (org != NULL)
delete []org;
org = new unsigned char [sz];
memcpy(org, img, sz);
}
//ビットマップ情報の表示(デバッグ用)
void BitMapProcessor :: dispBmpInfo(){
cout << "■ファイルヘッダ情報" << endl;
cout << "ファイルタイプ : " << fHeader.fileType << endl;
cout << "ファイルサイズ : " << fHeader.fileSize << endl;
cout << "■情報ヘッダ情報" << endl;
cout << "情報ヘッダサイズ : " << iHeader.infoHeaderSize << endl;
cout << "画像幅 : " << iHeader.width << endl;
cout << "画像高 : " << iHeader.height << endl;
cout << "1ピクセルあたりの色数 : " << iHeader.clrPerPixel << endl;
cout << "画像データのサイズ : " << iHeader.dataSize << endl;
}
//ビットマップデータのファイル書き出し
void BitMapProcessor :: writeData(string filename){
FILE *out = fopen(filename.c_str(), "wb");
if (out == NULL)
{
printf("書き出し先のファイルを開けません");
exit(0);
}
fwrite(fHeader.data, sizeof(unsigned char), FILE_HEADER_SIZE, out);
fwrite(iHeader.data, sizeof(unsigned char), INFO_HEADER_SIZE, out);
fwrite(img, sizeof(unsigned char), iHeader.dataSize, out);
fclose(out);
}
//指定されたピクセルの色を取得
Color BitMapProcessor :: getColor(int row, int col){
if (row < 0 || row >= iHeader.height)
{
printf("getColor : rowが範囲外です¥n");
exit(0);
}
if (col < 0 || col >= iHeader.width)
{
printf("getColor : colが範囲外です¥n");
exit(0);
}
int width = 3 * iHeader.width;
while (width % 4)
++width; //ビットマップの1列は4の倍数ビットからなる
int bPos = row * width + 3 * col;
int gPos = bPos + 1;
int rPos = bPos + 2;
Color color;
color.r = img[rPos];
color.g = img[gPos];
color.b = img[bPos];
return color;
}
//指定されたピクセルに色を設定
void BitMapProcessor :: setColor(int row, int col, int r, int g, int b){
if (row < 0 || row >= iHeader.height)
{
printf("getColor() : rowが範囲外です");
exit(0);
}
if (col < 0 || col >= iHeader.width)
{
printf("getColor() : colが範囲外です");
exit(0);
}
int width = 3 * iHeader.width;
while(width % 4)
++width;
int bPos = row * width + 3 * col;
int gPos = bPos + 1;
int rPos = bPos + 2;
img[rPos] = r;
img[gPos] = g;
img[bPos] = b;
}
//ビットマップデータを加工前に復元する
void BitMapProcessor :: restore(){
memcpy(img, org, iHeader.dataSize);
}
//モノクロ化
void twoTone(BitMapProcessor *bmp){
for (int i = 0; i < bmp->height(); i++)
for (int j = 0; j < bmp->width(); j++)
{
int ave = 0;
ave += bmp->getColor(i, j).r;
ave += bmp->getColor(i, j).g;
ave += bmp->getColor(i, j).b;
ave /= 3;
bmp->setColor(i, j, ave, ave, ave);
}
}
//色の反転
void invert(BitMapProcessor *bmp){
for (int i = 0; i < bmp->height(); i++)
for (int j = 0; j < bmp->width(); j++)
{
int ave = 0;
int r = bmp->getColor(i, j).r;
int g = bmp->getColor(i, j).g;
int b = bmp->getColor(i, j).b;
bmp->setColor(i, j, 255 - r, 255 - g, 255 - b);
}
}
//オリジナル
void randame(BitMapProcessor *bmp){
time_t mytime;
srand(time(&mytime));
for (int i = 0; i < bmp->height(); i++)
for (int j = 0; j < bmp->width(); j++)
{
bmp->setColor(i, j, rand() % 256, rand() % 256, rand() % 256);
}
}
//色を解析して文字にする
void ascii(BitMapProcessor *bmp){
FILE *fp;
char c[NOTE_PAD_WIDTH + 1];
if((fp = fopen("ascii2.txt", "w")) == NULL){
cout << "file open error" << endl;
exit(1);
}
for (int i = bmp->height() - 1; i > 0 ; i--){
for (int j = bmp->width() - 1; j > 0; j--){
int max = 0;
int r = bmp->getColor(i, j).r;
int g = bmp->getColor(i, j).g;
int b = bmp->getColor(i, j).b;
if(r >= b && r >= g)
max = r;
else if(g >= r && g >= b)
max = g;
else if(b >= r && b >= g)
max = b;
if(max >= 230)
c[j] = 'o';
else if(max >= 150)
c[j] = 'n';
else
c[j] = 'm';
}
fputs(c, fp);
fputs("¥n", fp);
}
fclose(fp);
}
//まどマギ用
void asciiMadoka(BitMapProcessor *bmp){
FILE *fp;
char c[NOTE_PAD_WIDTH + 1];
if((fp = fopen("ascii5.txt", "w")) == NULL){
cout << "file open error" << endl;
exit(1);
}
for (int i = bmp->height() - 1; i > 0 ; i--){
for (int j = bmp->width() - 1; j > 0; j--){
int max = 0;
int r = bmp->getColor(i, j).r;
int g = bmp->getColor(i, j).g;
int b = bmp->getColor(i, j).b;
if(r >= b && r >= g)
max = r;
else if(g >= r && g >= b)
max = g;
else if(b >= r && b >= g)
max = b;
//m g a d o i
if(max >= 220)
c[j] = 'i';
else if(max >= 190)
c[j] = 'o';
else if(max >= 150)
c[j] = 'd';
else if(max >= 130)
c[j] = 'a';
else if(max >= 100)
c[j] = 'g';
else
c[j] = 'm';
}
fputs(c, fp);
fputs("¥n", fp);
}
fclose(fp);
}
//色を解析して文字にする(html用)
void asciiHtml(BitMapProcessor *bmp){
FILE *fp;
char c[315 + 1];
if((fp = fopen("ascii.txt", "w")) == NULL){
cout << "file open error" << endl;
exit(1);
}
for (int i = bmp->height(); i > 0 ; i--){
for (int j = bmp->width(); j > 0; j--){
int max = 0;
int r = bmp->getColor(i, j).r;
int g = bmp->getColor(i, j).g;
int b = bmp->getColor(i, j).b;
if(r >= b && r >= g)
max = r;
else if(g >= r && g >= b)
max = g;
else if(b >= r && b >= g)
max = b;
if(max >= 212)
c[j] = 'i';
else if(max >= 128)
c[j] = 'n';
else if(max >= 64)
c[j] = 'm';
else
c[j] = '@';
}
fputs(c, fp);
fputs("<br>", fp);
fputs("¥n", fp);
}
fclose(fp);
}
//色を解析して文字にする
void asciiHoge(BitMapProcessor *bmp){
FILE *fp;
char c[469];
if((fp = fopen("ascii4.txt", "w")) == NULL){
cout << "file open error" << endl;
exit(1);
}
for (int i = bmp->height() - 1; i > 0 ; i--){
for (int j = bmp->width() - 1; j > 0; j--){
int max = 0;
int r = bmp->getColor(i, j).r;
int g = bmp->getColor(i, j).g;
int b = bmp->getColor(i, j).b;
if(r >= b && r >= g)
max = r;
else if(g >= r && g >= b)
max = g;
else if(b >= r && b >= g)
max = b;
if(max >= 230)
c[j] = 'l';
else if(max >= 100)
c[j] = 'n';
else
c[j] = 'm';
}
fputs(c, fp);
fputs("¥n", fp);
}
fclose(fp);
}
int main(){
BitMapProcessor bmp;
bmp.loadData("test.bmp");
bmp.dispBmpInfo();
// asciiHoge(&bmp);
// ascii(&bmp);
// asciiMadoka(&bmp);
// twoTone(&bmp);
// bmp.writeData("twoTone.bmp");
// bmp.restore();
// invert(&bmp);
// bmp.writeData("invert.bmp");
// bmp.restore();
// randame(&bmp);
// bmp.writeData("twoToneMado.bmp");
// bmp.restore();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.