Last active
March 20, 2019 08:09
-
-
Save techno-tanoC/e97f9735a293ad25723b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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