BMPファイルのカラーパレット操作について教えてほしいです
具体的には
BMPファイルから特定の色を検索→その色を変更
によって擬似的に実現したいです
目的は2P、3Pカラー等の実現のためです
DXライブラリ置き場の方で非常に参考になる質問がありました↓
http://hpcgi2.nifty.com/natupaji/bbs/pa ... iew&no=889
しかし、自分の理解力のせいか内容を理解できず、BMP形式に適用させられない状態です
できたらプログラムソースとともに解説もいただきたいです
カラーパレットの操作について
Re:カラーパレットの操作について
BMPの説明はWeb上に大量にあるので、それらを参考にしたほうが良いと思います。
http://www.umekkii.jp/data/computer/fil ... bitmap.cgi
とりあえず、DXライブラリ置き場で提示したGetPaletteとSetPaletteのBMP版の
ソースを書いておきますが、解説はしません。
上記のサイトの参考にして、何をやっているかを考えてみてください。
その上で、まだわからなければ、どこからどこまでがわかっていて
どこがわからなかったかを明記して再度質問してください。
http://www.umekkii.jp/data/computer/fil ... bitmap.cgi
とりあえず、DXライブラリ置き場で提示したGetPaletteとSetPaletteのBMP版の
ソースを書いておきますが、解説はしません。
上記のサイトの参考にして、何をやっているかを考えてみてください。
その上で、まだわからなければ、どこからどこまでがわかっていて
どこがわからなかったかを明記して再度質問してください。
#include <vector> /*! * @brief BMPのパレットを取得 * * @param pBuffer BMP画像の先頭のアドレスを指定します。 * @param palette 取得するパレットバッファを指定します。 * * @return 正常に取得した場合は true を返します。 */ bool GetPalette(const char* pBuffer, std::vector<unsigned char>& palette) { BITMAPFILEHEADER header; BITMAPINFOHEADER info; std::memcpy(&header, pBuffer, sizeof(header)); pBuffer += sizeof(header); if (header.bfType != 0x4d42) { // ビットマップではない return false; } std::memcpy(&info, pBuffer, sizeof(info)); pBuffer += sizeof(info); if (info.biBitCount != 8) { // 256色ではない return false; } palette.resize(256 * 3); for (int i = 0; i < 256; ++i) { const int bmpidx = i * sizeof(RGBQUAD); const int palidx = i * 3; palette[palidx + 0] = pBuffer[bmpidx + 2]; // 赤 palette[palidx + 1] = pBuffer[bmpidx + 1]; // 緑 palette[palidx + 2] = pBuffer[bmpidx + 0]; // 青 } return true; } /*! * @brief BMPのパレットを設定 * * @param pBuffer BMP画像の先頭のアドレスを指定します。 * @param palette 設定するパレットバッファを指定します。 * * @return 正常に設定した場合は true を返します。 */ bool SetPalette(char* pBuffer, const std::vector<unsigned char>& palette) { BITMAPFILEHEADER header; BITMAPINFOHEADER info; std::memcpy(&header, pBuffer, sizeof(header)); pBuffer += sizeof(header); if (header.bfType != 0x4d42) { // ビットマップではない return false; } std::memcpy(&info, pBuffer, sizeof(info)); pBuffer += sizeof(info); if (info.biBitCount != 8) { // 256色ではない return false; } for (int i = 0; i < 256; ++i) { const int bmpidx = i * sizeof(RGBQUAD); const int palidx = i * 3; pBuffer[bmpidx + 2] = palette[palidx + 0]; // 赤 pBuffer[bmpidx + 1] = palette[palidx + 1]; // 緑 pBuffer[bmpidx + 0] = palette[palidx + 2]; // 青 } return true; }
Re:カラーパレットの操作について
ソースありがとうございます
まさか同じ人が来てくれるとは思いませんでした
BITMAPFILEHEADER header;
BITMAPINFOHEADER info;
によってファイルヘッダと情報ヘッダを参照しているのは分かるのですが、
for (int i = 0; i < 256; ++i) {
const int bmpidx = i * sizeof(RGBQUAD);
const int palidx = i * 3;
pBuffer[palidx + 2] = palette[bmpidx + 0]; // 赤
pBuffer[palidx + 1] = palette[bmpidx + 1]; // 緑
pBuffer[palidx + 0] = palette[bmpidx + 2]; // 青
}
からよく分からないです(GetPallete,SetPallete同様
BMPのパレットデータが青、緑、赤という順番にあわせて読んでパレット用データに入れてるのだと思いますけど
いまいち自身がないです
あとpBufferとpalletteによりどのように色が変換されているのかも良く分かりません
このままだと
・BMPからパレットデータを読み取り
・パレットデータをBMPへ
という作業であって
特定の色を検索→その色を変換
という作業ではないと思います
初心者のような質問ですいませんm(_ _)m
まさか同じ人が来てくれるとは思いませんでした
BITMAPFILEHEADER header;
BITMAPINFOHEADER info;
によってファイルヘッダと情報ヘッダを参照しているのは分かるのですが、
for (int i = 0; i < 256; ++i) {
const int bmpidx = i * sizeof(RGBQUAD);
const int palidx = i * 3;
pBuffer[palidx + 2] = palette[bmpidx + 0]; // 赤
pBuffer[palidx + 1] = palette[bmpidx + 1]; // 緑
pBuffer[palidx + 0] = palette[bmpidx + 2]; // 青
}
からよく分からないです(GetPallete,SetPallete同様
BMPのパレットデータが青、緑、赤という順番にあわせて読んでパレット用データに入れてるのだと思いますけど
いまいち自身がないです
あとpBufferとpalletteによりどのように色が変換されているのかも良く分かりません
このままだと
・BMPからパレットデータを読み取り
・パレットデータをBMPへ
という作業であって
特定の色を検索→その色を変換
という作業ではないと思います
初心者のような質問ですいませんm(_ _)m
Re:カラーパレットの操作について
GPGAさんのコードを参考にして、パレット変更のプログラムを作成しました
以下ソースコードです
以下ソースコードです
#include "DxLib.h" #include <vector> bool GetPalette(const char* pBuffer, std::vector<unsigned char>& palette); bool SetPalette(char* pBuffer, const std::vector<unsigned char>& palette); bool ConvertPalette(std::vector<unsigned char>& palette); int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int) { // 初期化 ChangeWindowMode(TRUE); if (DxLib_Init() == -1) { return 1; } SetDrawScreen(DX_SCREEN_BACK); // 画像読み込み std::vector<char> bmpbuf; { int fh = FileRead_open("test.bmp"); bmpbuf.resize(FileRead_size("test.bmp")); FileRead_read(&bmpbuf[0], bmpbuf.size(), fh); FileRead_close(fh); } // 画像初期化 int iHandle[2]; std::vector<unsigned char> palette; GetPalette(&bmpbuf[0], palette); iHandle[0] = CreateGraphFromMem(&bmpbuf[0], bmpbuf.size()); ConvertPalette(palette); SetPalette(&bmpbuf[0], palette); iHandle[1] = CreateGraphFromMem(&bmpbuf[0], bmpbuf.size()); // 表示 DrawGraph(0, 0, iHandle[0], 0); DrawGraph(64, 0, iHandle[1], 0); ScreenFlip(); WaitKey(); DxLib_End(); return 0; } /*! * @brief BMPのパレットを取得 * * @param pBuffer BMP画像の先頭のアドレスを指定します。 * @param palette 取得するパレットバッファを指定します。 * * @return 正常に取得した場合は true を返します。 */ bool GetPalette(const char* pBuffer, std::vector<unsigned char>& palette) { BITMAPFILEHEADER header; BITMAPINFOHEADER info; std::memcpy(&header, pBuffer, sizeof(header)); pBuffer += sizeof(header); if (header.bfType != 0x4d42) { // ビットマップではない return false; } std::memcpy(&info, pBuffer, sizeof(info)); pBuffer += sizeof(info); if (info.biBitCount != 8) { // 256色ではない return false; } palette.resize(256 * 3); for (int i = 0; i < 256; ++i) { const int bmpidx = i * sizeof(RGBQUAD); const int palidx = i * 3; palette[palidx + 0] = pBuffer[bmpidx + 2]; // 赤 palette[palidx + 1] = pBuffer[bmpidx + 1]; // 緑 palette[palidx + 2] = pBuffer[bmpidx + 0]; // 青 } return true; } /*! * @brief BMPのパレットを設定 * * @param pBuffer BMP画像の先頭のアドレスを指定します。 * @param palette 設定するパレットバッファを指定します。 * * @return 正常に設定した場合は true を返します。 */ bool SetPalette(char* pBuffer, const std::vector<unsigned char>& palette) { BITMAPFILEHEADER header; BITMAPINFOHEADER info; std::memcpy(&header, pBuffer, sizeof(header)); pBuffer += sizeof(header); if (header.bfType != 0x4d42) { // ビットマップではない return false; } std::memcpy(&info, pBuffer, sizeof(info)); pBuffer += sizeof(info); if (info.biBitCount != 8) { // 256色ではない return false; } for (int i = 0; i < 256; ++i) { const int bmpidx = i * sizeof(RGBQUAD); const int palidx = i * 3; pBuffer[bmpidx + 2] = palette[palidx + 0]; // 赤 pBuffer[bmpidx + 1] = palette[palidx + 1]; // 緑 pBuffer[bmpidx + 0] = palette[palidx + 2]; // 青 } return true; } bool ConvertPalette(std::vector<unsigned char>& palette) { int ph; char palBuf[1024]; ph = FileRead_open("palette1.txt"); while(FileRead_eof(ph) == 0) { FileRead_gets(palBuf, 1023, ph); int original_R, original_G, original_B; int convert_R, convert_G, convert_B; sscanf_s(palBuf, "%d,%d,%d=%d,%d,%d;", &original_R, &original_G, &original_B, &convert_R, &convert_G, &convert_B); for(int i=0; i<256; i++){ if(palette[i * 3 + 0]==original_R && palette[i * 3 + 1]==original_G && palette[i * 3 + 2]==original_B){ palette[i * 3 + 0]=convert_R; palette[i * 3 + 1]=convert_G; palette[i * 3 + 2]=convert_B; } } } return true; }そのうち、ConvertPalette関数を指定したファイル名により読み取るパレットファイルを変更できるように直したいです