0. 序文
目次
最近仕事が多くて大変なのですが、大変なことをせずに何が得られるでしょうか?
今日は、とても感動的な本「光を探している少女」をお勧めします。高校時代に同級生が借りて読んだ記憶があるのですが、最初はタイトルを見たときはあまり魅力的とは思えませんでした。
最近、私の仕事も少しずつ軌道に乗りつつありますが、研究開発の仕事って、そうですね、制限を設けることはできず、それしか研究開発に反映できず、研究開発のメリットを最大限に発揮することができます。半年ほど働いていると、徐々に自分なりの理解が深まってきましたが、それは経験なのかもしれません。この気持ちは今感じられる、少し時間を与えてもらえればきっとマスターできると思う。
ダイエットコークを飲むのが大好きになりました。はー。
1.BMPフォーマットの詳細説明
これは最近の作業の内容です。タスクは、csv ファイルからデータを取得し、取得したデータをアルゴリズムを通じてグレースケール値に変換し、それを 16 ビットのビット深度を必要とする BMP 形式の画像に埋めることです。 。
1.1 写真の構成
実際、各画像は各ピクセルで構成されており、画像のサイズもピクセルの数で構成されることがわかっています。それぞれのピクセルは何で構成されているのでしょうか?bmp では値です。その前に、ビット深度と色深度という 2 つの概念について説明します。(長い間ブログを書いていませんでした、私の手は荒れていて、私の論理的思考は以前ほど良くありません、許してください)。
ビット深度: この用語は何を説明するために使用されますか? 各ピクセルのサイズはサイズと同義です。たとえば、ビット深度 24 のピクチャは、このピクチャの各ピクセルの値が 24 ビットのサイズで表されることを意味します。たとえば、ピクチャのサイズが 1080*1280 の場合、ビット深度が 24 の場合の bmp サイズは、 24 の深さは 1080* 約 1280*3 バイトです (ここでは Linux で実行しています。仮想マシンからコピーして勝利する場合、おそらくアーキテクチャが異なるため、サイズが異なります)。
色深度: bmp では、各ピクセルの値、実際には色の値は RGB の 3 つのチャネル、24 ビット画像で構成され、各チャネルは 8 ビット、つまり 1 バイトで表され、範囲は 0- 255、3 つのチャネル (赤、緑、青) の範囲は 0 ~ 255 で、これら 3 つのチャネルによって合成される色は 255*255*255 です。この値は色深度と呼ばれ、量の範囲であり、色数も
この 2 つの概念は曖昧になりやすいので、私の書いた内容がすべての人に理解してもらえるかどうかはわかりません。
1.2BMP形式
この画像は通常のファイルと考えてください。ただし、異なるのは、固定ヘッダーが必要であることです。
1.2.1 ファイルヘッダー
ファイルヘッダーはその名のとおり、このファイルの情報、つまりこの写真の情報を記述します。ここの内容には、ファイルのサイズに関する重要な情報が含まれています。パートサイズは14バイトです。
バイトオーダー |
データ構造 |
説明する |
1,2 _ |
16ビット |
上位 8 ビットは文字「B」、下位 8 ビットは文字「M」です。 |
3 ,4,5,6 |
32 |
ファイルサイズ |
7,8 _ |
16 |
予約語1 |
9 ,10 |
16 |
予約語1 |
11、12、13、14 _ |
32 |
ファイルに対するビットマップ データ セクションの開始オフセット |
データ部のオフセットの存在は、画像データ部を画像パラメータやパレットの直後に配置する必要がないことを示しており、BMP 画像の作成者は実際にパレットの後、データ部の前に任意のコンテンツを埋めることができます。正しく配置されていれば、オフセットを設定するだけです。
1.2.2ビットマップ情報ヘッダ
この部分は、画像の幅、高さ、bpp などの画像情報を記述するために使用されます。パーツのサイズは 40 バイトです。
バイトオーダー |
データ構造 |
説明する |
15、16、17、18 _ |
単位 |
現在の構造のサイズ、通常は 40 または 56 |
19 ,20,21,22 |
整数 |
画像の幅 (ピクセル) |
23 ,24,25,26 |
整数 |
画像の高さ (ピクセル) |
27 ,28 |
言葉 |
常に1 |
29 ,30 |
言葉 |
各ピクセルが占めるビット数は bpp です |
31 ,32,33,34 |
単位 |
圧縮方法 |
35 ,36,37,38 |
単位 |
画像サイズ |
39 ,40,41,42 |
整数 |
水平解像度 |
43 ,44,45,46 |
整数 |
垂直解像度 |
47 ,48,49,50 |
単位 |
引用色彩数 |
51 ,52,53,54 |
単位 |
キーカラー番号 |
31~34バイトは画像データの圧縮方式を表し、パラメータ値の範囲は0、1、2、3などです。
0 ----------------RGB モード
1 --------------- 8bpp ランレングス符号化方式
2 --------------- 4bpp ランレングス符号化方式
3 ---------------- ビットフィールドモード
圧縮オプションがビットフィールドに設定されている場合のみ、現在の構造サイズは 56 バイトになり、それ以外の場合は 40 バイトになります。
1.2.3 パレット
私たちが普段目にしている画像は主に24ビット画像、つまりR、G、Bの3色をそれぞれ8ビットで表現した画像であり、このような画像をトゥルーカラーと呼びますが、この場合にはパレットは必要ありません。つまり、ビットマップ データの直後にビットマップ情報ヘッダーが続きます。この部分は省略しますので、興味のある方はご自身で勉強してください。
1.2.4 ビットマップデータ
各ピクセルの値、ビットマップ データであり、各ピクセルは 1 バイトを占めます。24 ビット データは、BGR に従って埋められます。たとえば、2 ピクセルの bmp24 ビットマップ、その構成は次のとおりです: 14 バイトのファイル ヘッダー情報、40 バイトのビットマップ情報、2 ピクセル、各ピクセル サイズは 24 ビット、また3 バイトの場合、最初のピクセルの青は 8 ビット、次に緑の 8 ビット、そして赤の 8 ビットが続き、最後のピクセルにも同じことが当てはまります。合計 14+40+2*3=60 バイト。この 2 ピクセルの bmp ファイルのサイズは 60 バイトになります。(パレットは関係ありません)
詳しいコードは後述します。
2.生成する
コード部分については、生成されたコードのみを示しますが、完全なコードは完全なコードからダウンロードできます。このコードは csv ファイルからデータを取得し、データを分割して抽出していることに注意してください。
int bmp_gen_pic(char *fileName, uint32_t width, uint32_t height, unsigned char *color)
{
// width = 2048 height = 512 color = data_pic
#if 1
FILE *fp;
uint32_t i, j;
LITTLE l_width, l_height, l_bfSize, l_biSizeImage;
uint8_t r = color[0];
uint8_t g = color[0];
uint8_t b = color[0];
uint32_t width_r = (width * 24 / 8 + 3) / 4 * 4; // width_r 此变量代表的是每行的字节数 6144(整形) 这步保证宽度是4的倍数(bmp格式要求)
// printf("width_r = %ld\n",width_r);
uint32_t bfSize = width_r * height + 54 + 2; //此变量代表生成的图片的大小
uint32_t biSizeImage = width_r * height; //此变量代表图片的像素大小
// printf("hight = %ld\n",height);
// printf("size = %ld\n",biSizeImage);
l_width.value = width; // 2048
l_height.value = height; // 512
l_bfSize.value = bfSize; // 3145784
l_biSizeImage.value = biSizeImage; // 3145728
/* BMP file format: www.cnblogs.com/wainiwann/p/7086844.html */
// bmp格式头 固定
uint8_t bmp_head_map[54] = {
//这个头文件 包含两部分 一是文件头 14 二是位图信息头 40
/* bmp file header: 14 byte */
0x42, 0x4d, // 42 代表 B 4d代表M
// bmp pixel size: width * height * 3 + 54
l_bfSize.bytes[0], l_bfSize.bytes[1], l_bfSize.bytes[2], l_bfSize.bytes[3], //代表文件的尺寸
0, 0, 0, 0,
54, 0, 0, 0, /* 14+40=54 */ //位图部分相对文件的起始偏移量 就是多少字节后是位图数据(像素值)
/**************************************************************/
/* bmp map info: 40 byte */
40, 0, 0, 0, //当前的大小 就是40 意思后面40都是描述本部分
// width 图像宽度(像素)
l_width.bytes[0], l_width.bytes[1], l_width.bytes[2], l_width.bytes[3],
// height 图像高度(像素)
l_height.bytes[0], l_height.bytes[1], l_height.bytes[2], l_height.bytes[3],
1, 0, //恒为1
24, 0, //每个像素占用的位数(bpp) /* 24 bit: R[8]/G[8]/B[8] */
0, 0, 0, 0, // biCompression:0 压缩方式
//图像的尺寸
l_biSizeImage.bytes[0], l_biSizeImage.bytes[1], l_biSizeImage.bytes[2], l_biSizeImage.bytes[3],
0, 0, 0, 0, //水平分辨率 //biXPelsPerMeter: 60 0F 00 00
0, 0, 0, 0, //垂直分辨率 //biYPelsPerMeter
0, 0, 0, 0, //引用色彩数 //biClrUsed
0, 0, 0, 0 //关键色彩数 //biClrImportant
};
/* write in binary format */
fp = fopen(fileName, "wb+"); // wb+代表打开一个读写打开一个二进制文件
if (fp == NULL)
{
printf("%s: file create failed!\n", fileName);
return -1;
}
printf("%s: file create success!\n", fileName);
fwrite(bmp_head_map, sizeof(bmp_head_map), 1, fp); //写入1个sizeof(头)的大小
uint8_t databmp[KUAN*GAO*3];
memset(databmp, 0, sizeof(databmp));
uint32_t pos = 0;
#if 1
for (i = 0; i < height; i++)
{ // 512
for (j = 0; j < width; j++) // 2048
{
//fprintf(fp, "%c%c%c", color[j + i * width], color[j + i * width], color[j + i * width]); /* BGR */ // FF FF FF 白色 00 00 00 黑色
databmp[pos++] = color[j + i * width];
databmp[pos++] = color[j + i * width];
databmp[pos++] = color[j + i * width];
}
}
fwrite(databmp, sizeof(databmp), 1, fp);
#endif
fprintf(fp, "%c%c", 0, 0); // PhotoShop two byte "0"
if (fclose(fp))
{
printf("file close failed!\n");
return -1;
}
fp = NULL;
return 0;
#endif
}
コードには明確に注釈を付けましたが、理解できない場合はメッセージを残してください。
3. まとめ
おい、書くのに一週間かかった、クソ。
仕事が忙しくてブログがおろそかになってしまいますが、ご容赦ください。
仕事中はエネルギーを使い果たしてしまって、疲れているのに疲れていないのですが、仕事を終えてからは何も考えるのをやめて、シンプルで純粋な娯楽を楽しみたいのです。
人生には新鮮さが必要です、すべてがこのようなものです。
最後に言いたいのは、「考える」という状況に陥らず、実行することが難しいということです。来てみれば分かりますが、同じです。