9 Replies - 608 Views - Last Post: 04 September 2013 - 10:09 AM Rate Topic: -----

#1 retsgorf297  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 12
  • Joined: 03-September 13

Saving a bitmap in WinAPI

Posted 03 September 2013 - 05:02 PM

I am following a tutorial on saving bitmaps. It has gone well, but I am having a problem now. The program does compile successfully. It can save the file, but when I open the file it says:

Windows Live Photo Gallery:

Quote

Photo Gallery can't open this photo or video. The file may be unsupported, damaged or corrupt.


Here are some pieces of the code: Call to the functions in WndProc():

case SAVE_BM:
{
    BOOL result = SaveFileDlg(hwnd, filePath, "Save Bitmap");
    if (result)
    {
        PBITMAPINFO pbi = CreateBmpInfoStruct(hwnd, hBitmap);
        hdc = GetDC(hwnd);
        SaveBmpFile(hwnd, filePath, pbi, hBitmap, hdc);
    }
    return 0;
}

SaveBmpFile():

void SaveBmpFile(HWND hwnd, LPSTR file, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC)
{
    std::ofstream hF;
    BITMAPFILEHEADER bmfh;
    PBITMAPINFOHEADER pbmih;
    LPBYTE bits;
    DWORD total;
    DWORD cB;
    BYTE *hP;
    pbmih = (PBITMAPINFOHEADER) pbi;
    bits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbmih->biSizeImage);
    if (!bits)
        MessageBox(hwnd, "GlobalAlloc()", "Error", MB_OK);
    if (!GetDIBits(hDC, hBMP, 0, (WORD) pbmih->biHeight, bits, pbi, DIB_RGB_COLORS))
        MessageBox(hwnd, "GetDIBits()", "Error", MB_OK);
    hF.open(file, std::ios::binary);
    if (hF.fail())
        MessageBox(hwnd, "open()", "Error", MB_OK);
    bmfh.bfType = 0x4d42;
    bmfh.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + pbmih->biSize + pbmih->biClrUsed * sizeof(RGBQUAD) + pbmih->biSizeImage);
    bmfh.bfReserved1 = 0;
    bmfh.bfReserved2 = 0;
    bmfh.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + pbmih->biSize + pbmih->biClrUsed * sizeof(RGBQUAD);
    hF.write((char*) &bmfh, sizeof(BITMAPFILEHEADER));
    if (hF.fail())
        MessageBox(hwnd, "write() file header", "Error", MB_OK);
    hF.write((char*) pbmih, sizeof(BITMAPINFOHEADER) + pbmih->biClrUsed * sizeof(RGBQUAD));
    if (hF.fail())
        MessageBox(hwnd, "write() info header", "Error", MB_OK);
    total = cB = pbmih->biSizeImage;
    hP = bits;
    hF.write((char*) hP, (int) cB);
    if (hF.fail())
        MessageBox(hwnd, "write() data", "Error", MB_OK);
    hF.close();
    if (hF.fail())
        MessageBox(hwnd, "close()", "Error", MB_OK);
    GlobalFree((HGLOBAL) bits);
}

SaveBmpInfoStruct():

PBITMAPINFO CreateBmpInfoStruct(HWND hwnd, HBITMAP hBMP)
{
    BITMAP BMP;
    PBITMAPINFO pbmi;
    WORD clrBits;
    if (!GetObject(hBMP, sizeof(BITMAP), (LPSTR) &BMP))
        MessageBox(hwnd, "GetObject()", "Error", MB_OK);
    clrBits = (WORD) (BMP.bmPlanes * BMP.bmBitsPixel);
    if (clrBits == 1)
        clrBits = 1;
    else if (clrBits <= 4)
        clrBits = 4;
    else if (clrBits <= 8)
        clrBits = 8;
    else if (clrBits <= 16)
        clrBits = 16;
    else if (clrBits <= 24)
        clrBits = 24;
    else
        clrBits = 32;
    if (clrBits != 24)
        pbmi = (PBITMAPINFO) LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1<< clrBits));
    else
        pbmi = (PBITMAPINFO) LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER));
    pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    pbmi->bmiHeader.biWidth = BMP.bmWidth;
    pbmi->bmiHeader.biHeight = BMP.bmHeight;
    pbmi->bmiHeader.biPlanes = BMP.bmPlanes;
    pbmi->bmiHeader.biBitCount = BMP.bmBitsPixel;
    if (clrBits < 24)
        pbmi->bmiHeader.biClrUsed = (1<< clrBits);
    pbmi->bmiHeader.biCompression = BI_RGB;
    pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * clrBits + 31) & ~31) / 8 * pbmi->bmiHeader.biHeight;
    pbmi->bmiHeader.biClrImportant = 0;
    return pbmi;
    }

SaveFileDlg():

BOOL SaveFileDlg(HWND hwnd, LPSTR fileName, LPSTR titleName)
{
    ofn.lStructSize = sizeof(OPENFILENAME);
    ofn.hInstance = GetModuleHandle(NULL);
    ofn.lpstrCustomFilter = NULL;
    ofn.nMaxCustFilter = 0;
    ofn.nFilterIndex = 0;
    ofn.hwndOwner = hwnd;
    ofn.lpstrFile = fileName;
    ofn.lpstrFileTitle = NULL;
    ofn.lpstrTitle = titleName;
    ofn.Flags = OFN_EXPLORER | OFN_OVERWRITEPROMPT;
    ofn.lpstrFilter = "Bitmap Files (*.bmp)\0*.bmp\0\0";
    ofn.lpstrTitle = titleName;
    return GetSaveFileName(&ofn);
}

Let me know if you need to see more code. I have searched Google a few times, but I have not found anything. It is a little hard to find something for this exact condition. I have tried this on another forum, but it has not worked out, as you can tell by me asking this. I am new to this forum, so if I need to do something else or if you have any tips for me, please tell me.

Thanks for your help!

Is This A Good Question/Topic? 0
  • +

Replies To: Saving a bitmap in WinAPI

#2 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3160
  • View blog
  • Posts: 9,532
  • Joined: 05-May 12

Re: Saving a bitmap in WinAPI

Posted 03 September 2013 - 05:21 PM

Are you sure your bitmaps are 24-bits per pixel? If not then you have several opportunities for buffer overruns due to the following code:
21    if (clrBits != 24)
22        pbmi = (PBITMAPINFO) LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1<< clrBits));
23    else
24        pbmi = (PBITMAPINFO) LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER));
:
30    if (clrBits < 24)
31        pbmi->bmiHeader.biClrUsed = (1<< clrBits);

:
:

27    hF.write((char*) pbmih, sizeof(BITMAPINFOHEADER) + pbmih->biClrUsed * sizeof(RGBQUAD));


Was This Post Helpful? 1
  • +
  • -

#3 retsgorf297  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 12
  • Joined: 03-September 13

Re: Saving a bitmap in WinAPI

Posted 03 September 2013 - 05:24 PM

@Skydiver How can I fix this?
Was This Post Helpful? 0
  • +
  • -

#4 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3160
  • View blog
  • Posts: 9,532
  • Joined: 05-May 12

Re: Saving a bitmap in WinAPI

Posted 03 September 2013 - 06:13 PM

Have you even stepped through your code with a debugger to ensure that you are getting expected values? Have you cracked open your file to ensure that the bitmap file structures are written out correctly? (See http://en.wikipedia..../Windows_bitmap )
Was This Post Helpful? 0
  • +
  • -

#5 retsgorf297  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 12
  • Joined: 03-September 13

Re: Saving a bitmap in WinAPI

Posted 03 September 2013 - 06:34 PM

I am still new to working with bitmap, so I did not think of this. So can you please explain hwo to fix this.
Was This Post Helpful? 0
  • +
  • -

#6 snoopy11  Icon User is offline

  • Engineering ● Software
  • member icon

Reputation: 710
  • View blog
  • Posts: 2,033
  • Joined: 20-March 10

Re: Saving a bitmap in WinAPI

Posted 03 September 2013 - 07:12 PM

You have changed my original Tutorial.

Granted it was written while I was learning c/c++ and there are some glaring errors,

however it does work in saving a bitmap to file and I have built the Tutorial again to make sure.

If you change code, it may not work, especially if you are not sure how it works.

I have opened the saved bitmaps from the program in Windows Live Photo Gallery and they do open.

Regards

Snoopy.
Was This Post Helpful? 1
  • +
  • -

#7 retsgorf297  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 12
  • Joined: 03-September 13

Re: Saving a bitmap in WinAPI

Posted 03 September 2013 - 07:21 PM

@snoopy11 I have modified it to make sure I understand it. Which, apparently I don't. It is a great tutorial, and I have learned a lot from it.

@snoopy11 What did I change? I looked back and didn't noticed any thing that really stood out. I was also typing out everything, so I probably didn't type something right.
Was This Post Helpful? 1
  • +
  • -

#8 snoopy11  Icon User is offline

  • Engineering ● Software
  • member icon

Reputation: 710
  • View blog
  • Posts: 2,033
  • Joined: 20-March 10

Re: Saving a bitmap in WinAPI

Posted 04 September 2013 - 09:58 AM

View Postretsgorf297, on 04 September 2013 - 02:21 AM, said:

@snoopy11 I have modified it to make sure I understand it. Which, apparently I don't. It is a great tutorial, and I have learned a lot from it.

@snoopy11 What did I change? I looked back and didn't noticed any thing that really stood out. I was also typing out everything, so I probably didn't type something right.


Yeah it was an error in the code,

I didnt anticipate anyone not using a 24 bit bmp.

this line needs adjusting in the OPEN routine.

hBitmap = (HBITMAP)LoadImage(NULL,szFileName,IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION|LR_DEFAULTSIZE|LR_LOADFROMFILE|LR_VGACOLOR);


to

hBitmap = (HBITMAP)LoadImage(NULL,szFileName,IMAGE_BITMAP,0,0,LR_DEFAULTSIZE|LR_LOADFROMFILE|LR_VGACOLOR);


quite why I used LR_CREATEDIBSECTION I dont know,

I may have been drunk when I wrote all that :)

Regards

Snoopy.
Was This Post Helpful? 1
  • +
  • -

#9 retsgorf297  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 12
  • Joined: 03-September 13

Re: Saving a bitmap in WinAPI

Posted 04 September 2013 - 10:04 AM

@snoopy11 Thank you, that worked. I am going to start reading your image editor tutorial now.
Was This Post Helpful? 0
  • +
  • -

#10 snoopy11  Icon User is offline

  • Engineering ● Software
  • member icon

Reputation: 710
  • View blog
  • Posts: 2,033
  • Joined: 20-March 10

Re: Saving a bitmap in WinAPI

Posted 04 September 2013 - 10:09 AM

I should just add that the problem was if you loaded anything other than 24 bit bitmap

it would not save the correct color information to the bitmap,

this was because I had used the LR_CREATEDIBSECTION flag which does not map the color info to the device context,

removing the flag removes the problem, the color info is mapped and a new bitmap can be correctly saved.

Snoopy.
Was This Post Helpful? 1
  • +
  • -

Page 1 of 1