まっつぁんと申します。
開発環境は
windows10
VisualStudio2015
Dxライブラリを使用
当方、2Dゲームを制作しておりまして、キャラクターの色違いを作りたいと思い、png画像の色データを変更するプログラムを作っています。
経緯は、キャラクターの色違いをそれぞれ画像として持つと、データ容量が大きくなってしまったり、一部アニメーションなどを変更した場合、すべてのカラーに反映させなければならないので、基準の画像のカラーパレットから色を変更してゲーム画面に表示させたほうが効率的ではないのかと考えたからです。
まず最初はDxライブラリを使用して、GetPixelSoftImageやDrawPixelSoftImageを使って画像の色を取得し、自作パレットを参考に色を変更し、CreateGraphFromSoftImageで画像ハンドルを作って表示させるプログラムを作りました。
しかし、小さな画像ならまだしも、変更する画像のサイズが大きくなってくると処理にも時間がかかってしまうのでこれではだめだと思いました。
次に自分なりに調べて、libpngライブラリを使用すればいいと思ったのですが、どうも色の取得方法と変更方法がわからず、今に至ります。
#include "DxLib.h"
#include "png.h"
// プログラムは WinMain から始まります
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
FILE *fp;
png_structp png_ptr;
png_infop info_ptr;
png_uint_32 width, height;
int bit_depth, color_type, interlace_type;
unsigned char **image;
fopen_s(&fp, "number.png", "rb"); // まずファイルを開きます
png_ptr = png_create_read_struct( // png_ptr構造体を確保・初期化します
PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
info_ptr = png_create_info_struct(png_ptr); // info_ptr構造体を確保・初期化します
png_init_io(png_ptr, fp); // libpngにfpを知らせます
png_read_info(png_ptr, info_ptr); // PNGファイルのヘッダを読み込みます
png_get_IHDR(png_ptr, info_ptr, &width, &height, // IHDRチャンク情報を取得します
&bit_depth, &color_type, &interlace_type,
NULL, NULL);
//パレットがあれば、パレットを読み込む(PNGパレットは、libpng側で開放する)
int num_palette = 0; //色数
png_color *palette = 0; //PNGパレット
if (color_type == PNG_COLOR_TYPE_PALETTE) {
//PNGパレットを読み込む
png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
}
// チャンネル数
png_byte channels = png_get_channels(png_ptr, info_ptr);
// ビット深度
int pixel_depth = bit_depth * channels;
BYTE *byBmp = (BYTE*)::malloc(height * (((width * pixel_depth / 8) + 3) & ~3));
for (int i = 0; i < num_palette; i++)
{
byBmp[i * 4 + 0] = palette[i].blue;
byBmp[i * 4 + 1] = palette[i].green;
byBmp[i * 4 + 2] = palette[i].red;
}
free(byBmp);
image = (png_bytepp)malloc(height * sizeof(png_bytep)); // 以下3行は2次元配列を確保します
for (int i = 0; i < height; i++)
image[i] = (png_bytep)malloc(png_get_rowbytes(png_ptr, info_ptr));
png_read_image(png_ptr, image); // 画像データを読み込みます
for (int i = 0; i < height; i++) free(image[i]); // 以下2行は2次元配列を解放します
free(image);
png_destroy_read_struct( // 2つの構造体のメモリを解放します
&png_ptr, &info_ptr, (png_infopp)NULL);
fclose(fp); // ファイルを閉じます
return 0;
}
http://gmoon.jp/png/#program_writing
最終手段としてはキャラクター画像をそれぞれ作ったほうがいいのかなと考えています。
それと、キャラクターの色変更の考えとしてはこれでいいのでしょうか?
それとも効率のいい別の方法があるのでしょうか?
よろしくお願いいたします。