1

これは長い投稿かもしれませんが、24ビットと32ビットのビットマップを変換する方法を本当に知る必要があります。この投稿の長さのために、質問のPNG部分を削除しました。

ここに行きます:

私はすべてのピクセル情報を保持する以下のような構造体を持っています:

typedef union RGB
{
    uint32_t Color;
    struct
    {
        unsigned char B, G, R, A;
    } RGBA;
} *PRGB;

std::vector<RGB> Pixels;   //Holds all pixels.

24から32に、またはその逆の場合を除いて、すべてのビットマップ書き込みが機能します。何が間違っているのか、なぜ24〜32変換が機能しないのかわかりません。私のビットマップの読み取りと書き込みのコードは次のとおりです。

Bitmap(const void* Pointer, int Width, int Height, uint32_t BitsPerPixel) //Constructor initialization here...
{
    Pixels.clear();
    if (Pointer == nullptr) {throw std::logic_error("Null Pointer Exception. Pointer is NULL.");}
    if (Width < 1 || Height < 1) {throw std::invalid_argument("Invalid Arguments. Width and Height cannot equal 0.");}
    std::memset(&Info, 0, sizeof(BITMAPINFO));
    size = ((width * BitsPerPixel + 31) / 32) * 4 * height;

    Info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    Info.bmiHeader.biWidth = width;
    Info.bmiHeader.biHeight = height;
    Info.bmiHeader.biPlanes = 1;
    Info.bmiHeader.biBitCount = BitsPerPixel;
    Info.bmiHeader.biCompression = BI_RGB;
    Info.bmiHeader.biSizeImage = size;
    bFileHeader.bfType = 0x4D42;
    bFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(Info.bmiHeader);
    bFileHeader.bfSize = bFileHeader.bfOffBits + size;

    const unsigned char* BuffPos = static_cast<const unsigned char*>(Pointer);
    height = (height < 0 ? -height : height);
    Pixels.resize(width * height);

    for (int I = 0; I < height; I++)
    {
        for (int J = 0; J < width; J++)
        {
            Pixels[(height - 1 - I) * width + J].RGBA.B = *(BuffPos++);
            Pixels[(height - 1 - I) * width + J].RGBA.G = *(BuffPos++);
            Pixels[(height - 1 - I) * width + J].RGBA.R = *(BuffPos++);
            Pixels[(height - 1 - I) * width + J].RGBA.A = (Info.bmiHeader.biBitCount > 24 ? *(BuffPos++) : 0);
        }
        if(Info.bmiHeader.biBitCount == 24)
            BuffPos += width % 4;
    }
}

bool SaveBitmap(const char* FilePath)
{
    std::vector<unsigned char> ImageData(size);
    unsigned char* BuffPos = ImageData.data();

    for (int I = 0; I < height; ++I)
    {
        for (int J = 0; J < width; ++J)
        {
            *(BuffPos++) = Pixels[(height - 1 - I) * width + J].RGBA.B;
            *(BuffPos++) = Pixels[(height - 1 - I) * width + J].RGBA.G;
            *(BuffPos++) = Pixels[(height - 1 - I) * width + J].RGBA.R;

            if (Info.bmiHeader.biBitCount > 24)
                *(BuffPos++) = Pixels[(height - 1 - I) * width + J].RGBA.A;
        }
        if(Info.bmiHeader.biBitCount == 24)
            BuffPos += width % 4;
    }

    std::fstream hFile(FilePath, std::fstream::out | std::ofstream::binary);
    if (!hFile.is_open()) return false;

    hFile.write(reinterpret_cast<char*>(&bFileHeader), sizeof(BITMAPFILEHEADER));
    hFile.write(reinterpret_cast<char*>(&Info.bmiHeader), sizeof (BITMAPINFOHEADER));
    hFile.write(reinterpret_cast<char*>(&ImageData[0]), Size());
    hFile.close();

    return true;
}

2つの問題が何であるかについて何か考えはありますか?Bitmap(24BmpBuff、W、H、32);を呼び出した場合にそれが必要です。32として保存されます。Bitmap(32BmpBuff、W、H、24)を実行すると、24ビットとして保存されます。見えないので、よろしくお願いします。

また、ヘルパー関数を作成してみました。

24ビットから32ビットに変換します。

void T24To32(std::vector<RGB> &Input, std::vector<RGB> &Output, int Width, int Height)
{
    Output.resize(Input.size());
    for (int I = 0; I < Height; ++I)
    {
        for (int J = 0; J < Width; ++J)
        {
            Output[J].RGBA.B = Input[J].RGBA.B;
            Output[J].RGBA.G = Input[J].RGBA.G;
            Output[J].RGBA.R = Input[J].RGBA.R;
            Output[J].RGBA.A = 0;
        }
    }
}

ピクセルのunsignedchar*を取得し、構造体内に逆さまに格納します。

void Pack(int width, int height, int BPP, unsigned char* Input, std::vector<RGB> &Pixels)
{
    unsigned char* BuffPos = Input;
    height = (height < 0 ? -height : height);
    Pixels.resize(width * height);

    for (int I = 0; I < height; I++)
    {
        for (int J = 0; J < width; J++)
        {
            Pixels[(height - 1 - I) * width + J].RGBA.B = *(BuffPos++);
            Pixels[(height - 1 - I) * width + J].RGBA.G = *(BuffPos++);
            Pixels[(height - 1 - I) * width + J].RGBA.R = *(BuffPos++);
            Pixels[(height - 1 - I) * width + J].RGBA.A = (BPP > 24 ? *(BuffPos++) : 0);
        }
        if(BPP == 24)
            BuffPos += width % 4;
    }
}

ピクセルの構造体を取り、それらをunsignedchar*に直立して格納します。

void Unpack(int width, int height, int BPP, std::vector<RGB> Pixels, unsigned char* &Output)
{
    unsigned char* BuffPos = Output;

    for (int I = 0; I < height; ++I)
    {
        for (int J = 0; J < width; ++J)
        {
            *(BuffPos++) = Pixels[(height - 1 - I) * width + J].RGBA.B;
            *(BuffPos++) = Pixels[(height - 1 - I) * width + J].RGBA.G;
            *(BuffPos++) = Pixels[(height - 1 - I) * width + J].RGBA.R;

            if (BPP > 24)
                *(BuffPos++) = Pixels[(height - 1 - I) * width + J].RGBA.A;
        }
        if(BPP == 24)
            BuffPos += width % 4;
    }
}

私は上記のすべてをそのように使用します..入力画像(32ビット):ここに画像の説明を入力してください

コード:

void Bitmap32ToBitmap24(int Width, int Height)
{
    Bitmap Image("C:/Images/Bitmap32.bmp");
    std::vector<unsigned char> Pixels(((Width * 32 + 31) / 32) * 4 * Height);   //Array large enough to hold 32 bit bmp.
    unsigned char* BuffPos = Pixels.data();

    Unpack(Width, Height, 32, Image.Get(), BuffPos);                            //Fill the array of unsigned char with image pixels being upright

    Bitmap BMP(Pixels.data(), Width, Height, 24);                               //Convert image to 24 bit bmp and save it.
    BMP.Save("C:/Images/Output/Bitmap32ToBitmap24.png");
}

出力画像(24ビット):ここに画像の説明を入力してください 24〜32の結果: ここに画像の説明を入力してください

4

1 に答える 1

1

すべてのコード スニペットで

if(Info.bmiHeader.biBitCount == 24)
        BuffPos += width % 4;

また

if(BPP == 24)
        BuffPos += width % 4;

発生する。これにより、各行にパディング値が追加されるはずです。しかし、これはパディングではなく、1 行あたりのピクセル数 %4 です。

正しい加算値は(4 - ((width * 3) % 4)) % 4です。width*3 は、その行のバイト数です。は%4、4 バイトのパディングでは多すぎるバイト数を計算しますが、次に高いライムまで埋めるには、4この値が必要です。パディングオフセットが必要ない場合、これも4です->%4それを避けるため。

同じ値を計算するより高速な方法は、 です(-width * 3) & 3ウィキを参照してください。

于 2012-12-23T14:52:14.750 に答える