2012-12-23 50 views
1

這可能是一個很長的帖子,但我真的需要知道如何在24和32位位圖之間轉換。爲了這篇文章的長度,我刪除了我的問題的PNG部分。位圖24到32和後面

這裏所說:

我有這樣的一個低於一個結構保存了所有的像素信息:

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; 
} 

任何想法這兩個問題可能是什麼?我需要它,所以如果我調用位圖(24BmpBuff,W,H,32);它會保存爲32.如果我做位圖(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; 
     } 
    } 
} 

取像素的無符號字符*並將它們顛倒存儲在結構中。

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; 
    } 
} 

取像素的結構並將它們直立存儲在unsigned char *中。

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位)的:enter image description here

代碼:

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位):enter image description here 24至32結果在: enter image description here

+2

我只簡要地看了一下代碼,但是當轉換24-> 32位時,你可能想要設置alpha爲255而不是0,否則你會得到一個透明的圖像。 – interjay

+1

哪個函數產生錯誤的結果,以及哪些參數?那是什麼結果?期望的結果是什麼? –

+0

將該信息添加到第一篇文章。 – Brandon

回答

1

在您所有的代碼片段中

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

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

發生。我認爲這應該添加填充值到每一行。但它不是填充,它是每行%4的像素數。

正確的加法值是(4 - ((width * 3) % 4)) % 4。寬度* 3是該行中的字節數。 %4計算4字節填充的許多字節數,但填充我們需要的下一個更高的灰度數4 - 該值。如果不需要填充偏移,則再次爲4 - >%4以避免這種情況。

計算相同值的更快方法是(-width * 3) & 3。請參閱wiki

+0

嗯,仍然沒有墊。結果是完全相同的:S – Brandon

+1

對不起,我找不到其他東西。所有指數...都是正確的。看到結果,它是以字節爲單位的行長度的問題。您是否將寬度和高度參數設置爲正確? –

+1

我標記你的答案已解決,因爲這是一個很好的答案:)我最終改變了我的代碼,你提到的,它是填充正確。原來的錯誤是Info.bmiHeader.biSizeImage。謝謝您的幫助。您阻止了我的未來問題:D 以防萬一您想查看代碼:http://pastebin.com/ARJrYqYY – Brandon