質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

3720閲覧

visual Studio における画像ファイルの扱い方 C/C++

Kanaya979

総合スコア13

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2019/05/15 02:09

前提・実現したいこと

C++でライブラリ(OpenCV)を使わずにトリミングをするシステムを作っています。

発生している問題・エラーメッセージ

現在のシステムでは指定範囲外の画素の情報を(255,255,255)=白に書き換えて出力画像が出てくる状態です。画像のサイズ(縦横)はそのままです。

width、heightに対応するdata[]を指定サイズに合うように上書きすればいいのかな?と見当はつくのですが、画素のデータはどう更新すればよいのかわかりません。

該当のソースコード

#include <cstdio> #include <iostream> #include <cstring> #define FILE_HEADER_SIZE 14 // ファイルヘッダのサイズ #define INFO_HEADER_SIZE 40 // 情報ヘッダのサイズ using namespace std; /* * ファイルヘッダー構造体 */ typedef struct FileHeader { uint8_t data[FILE_HEADER_SIZE]; // 加工前データ(書き出しのため必要) string fileType; // ファイルタイプ int fileSize; // ファイルサイズ } FileHeader; /* * 情報ヘッダー構造体 */ typedef struct InfoHeader { uint8_t data[INFO_HEADER_SIZE]; // 加工前データ(書き出しのため必要) int infoHeaderSize; // 情報ヘッダのサイズ int width; // 画像の幅 int height; // 画像の高さ int clrPerPixel; // 1ピクセル当たりの色数 int dataSize; // 画像データのサイズ } InfoHeader; /* * ピクセルの色情報構造体 */ typedef struct Color { int r; // 赤成分 int g; // 緑成分 int b; // 青成分 } Color; int bit2Integer(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4); /* * ビットマップ処理クラス */ class BitMapProcessor { FILE *bmp; // ビットマップのファイルポインタ uint8_t *img; // ビットマップデータ(加工用) uint8_t *org; // ビットマップデータ(読み込み時) FileHeader fHeader; // ファイルヘッダ InfoHeader iHeader; // 情報ヘッダ public: BitMapProcessor() { bmp = NULL; img = NULL; org = NULL; }; ~BitMapProcessor() { fclose(bmp); delete[]img; delete[]org; } 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(); }; /* * 4ビット情報をInt整数値に変換 */ int bit2Integer(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t 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"); readFileHeader(); readInfoHeader(); readBmpData(); } /* * ファイルヘッダを読む */ void BitMapProcessor::readFileHeader() { uint8_t data[FILE_HEADER_SIZE]; size_t size = fread(data, sizeof(uint8_t), 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() { uint8_t data[INFO_HEADER_SIZE]; size_t size = fread(data, sizeof(uint8_t), 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; int sz = iHeader.dataSize; img = new uint8_t[sz]; size_t size = fread(img, sizeof(uint8_t), sz, bmp); if (size != sz) printf("画像データ読み込みのサイズが矛盾しています。"); // バックアップ用にorgに画像データをコピー if (org != NULL) delete[]org; org = new uint8_t[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("書き出し先のファイルを開けません。\n"); fwrite(fHeader.data, sizeof(uint8_t), FILE_HEADER_SIZE, out); fwrite(iHeader.data, sizeof(uint8_t), INFO_HEADER_SIZE, out); fwrite(img, sizeof(uint8_t), iHeader.dataSize, out); fclose(out); } /* * 指定されたピクセルの色を取得 */ Color BitMapProcessor::getColor(int row, int col) { if (row < 0 || row >= iHeader.height) printf("getColor(): rowが範囲外です。\n"); if (col < 0 || col >= iHeader.width) printf("getColor(): colが範囲外です。\n"); int width = 3 * iHeader.width; while (width % 4) // ビットマップの1列は4の倍数ビットからなる ++width; 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が範囲外です。\n"); if (col < 0 || col >= iHeader.width) printf("getColor(): colが範囲外です。\n"); int width = 3 * iHeader.width; while (width % 4) // ビットマップの1列は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 extractArea(BitMapProcessor *bmp, int r0, int r1, int c0, int c1) { for (int i = 0; i < bmp->height(); i++) for (int j = 0; j < bmp->width(); j++) { if (r0 <= i && i <= r1 && c0 <= j && j <= c1) continue; bmp->setColor(i, j, 255, 255, 255); } } /* * メイン処理 */ int main() { BitMapProcessor bmp; // ビットマップデータのロード bmp.loadData("C:\Users\shinohara yuki\source\repos\BMPcut\newVER\filename.bmp"); //仕様画像の絶対パス // ビットマップ情報の表示 bmp.dispBmpInfo(); bmp.writeData("bb.bmp"); //指定範囲の切り出し extractArea(&bmp, 0, 25, 0, 256); //(x始点,x長さ,y始点,y長さ) bmp.writeData("kii5.bmp"); bmp.restore(); return 0; }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

bitmapはフォーマット次第ではややこしいので、とりあえずARGBの32bitとします
そうすると、1ドットは4byteで表され、64x64の画像は1024pixelで4096byteのデータになります

これを、32x32だと、1/4なので、1024byteのデータですから、書き込むべきdata部を1024byteになります

トリミングするなら、白で塗りつぶした部分は書き込まず、そのままの部分だけ書き込めば、
ちょうどサイズが一致すると思います

投稿2019/05/15 02:45

izmktr

総合スコア2856

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Kanaya979

2019/05/15 06:01

考え方は理解できました。ありがとうございます。 しかしコードをどのように変更すればよいかが、、、もしわかりそうならご教授お願い致します。
izmktr

2019/05/15 07:40

このコードはあなたが書いたものではないのですか? もし、どこかのページのサンプルそのままで、全く理解してないのなら、 自分でいろいろいじって理解するところからがスタートだと思います (特にextractArea関数の挙動はしっかり抑えておきたい)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問