none
conver GDI::Bitmap to byte* RRS feed

  • Question

  • I have a Bitmap (bmp) object. Using save, i can save it to disk:
    image->Save(L"C:/test.bmp", &m_bmpClsid, NULL);

    When i try the same object to save it on a byte*, and then save this byte* on disk, this memory remains empty.

    IStream *buffer;
    CreateStreamOnHGlobal(NULL, true, &buffer);
    bitmap->Save(buffer,&m_bmpClsid,NULL);
    buffer->Read(m_szBuff,m_bmpBufferSize, &m_nRead);

    Any ideas on a better way to do this?

    I found this code on web (on C# though...),

        Rect rect(0, 0, bitmap->GetHeight(), bitmap->GetWidth());
        BitmapData* bData = new BitmapData;
          bitmap->LockBits(&rect,ImageLockModeRead,PixelFormat24bppRGB,bData);
        int byteCount = bData->Stride*bitmap->GetHeight();
        memcpy(m_szBuff,originalScanPtr,byteCount);
        bitmap->UnlockBits (bData);

    instead of memcpy they used a function named marshal.copy. Here, malloc throws exception but i cannot get any meaning out of it. Any ideas what i am doing wrong in ether case?
    Thank you guys, looking forward for an answer
    a.rongas
    Thursday, November 27, 2008 2:59 PM

Answers

  • Where's your Seek call?  This sample code created an exact duplicate of a bitmap:

    #include "stdafx.h"
    #include <atlimage.h>
    #include <assert.h>
    #include <stdio.h>

    int _tmain(int argc, _TCHAR* argv[])
    {
      CImage image;
      HRESULT hr;
      // Load sample image
      hr = image.Load(L"c:\\temp\\test.bmp");
      assert(hr == S_OK);

      // Calculate reasonably safe buffer size
      int stride = 4 * ((image.GetWidth() + 3) / 4);
      size_t safeSize = stride * image.GetHeight() * 4 + sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER) + 256 * sizeof(RGBQUAD);
      HGLOBAL mem = GlobalAlloc(GHND, safeSize);
      assert(mem);

      // Create stream and save bitmap
      IStream* stream = 0;
      hr = CreateStreamOnHGlobal(mem, TRUE, &stream);
      assert(hr == S_OK);
      hr = image.Save(stream, Gdiplus::ImageFormatBMP);
      assert(hr == S_OK);

      // Allocate buffer for saved image
      LARGE_INTEGER seekPos = {0};
      ULARGE_INTEGER imageSize;
      hr = stream->Seek(seekPos, STREAM_SEEK_CUR, &imageSize);
      assert(hr == S_OK && imageSize.HighPart == 0);
      BYTE* buffer = new BYTE[imageSize.LowPart];

      // Fill buffer from stream
      hr = stream->Seek(seekPos, STREAM_SEEK_SET, 0);
      assert(hr == S_OK);
      hr = stream->Read(buffer, imageSize.LowPart, 0);
      assert(hr == S_OK);

      // Save to disk
      FILE* fp = 0;
      errno_t err = _wfopen_s(&fp, L"c:\\temp\\copy.bmp", L"wb");
      assert(err == 0 && fp != 0);
      fwrite(buffer, 1, imageSize.LowPart, fp);
      fclose(fp);

      // Cleanup
      stream->Release();
      delete[] buffer;
      return 0;
    }



    Hans Passant.
    • Marked as answer by a.rongas Saturday, November 29, 2008 2:38 PM
    Friday, November 28, 2008 4:31 PM
    Moderator

All replies

  • Maybe it has sense to execute buffer->Seek(0, STREAM_SEEK_SET, NULL) before buffer->Read?

    Thursday, November 27, 2008 3:07 PM
  • Thank you for the answer, i tried this but to no avail I am afraid.

    Using the code:

        int byteCount = (bitmap->GetWidth()*bitmap->GetHeight()*3)+BMP_HEADER_LENGTH;
        LPBYTE   lpBits = (LPBYTE) GlobalAlloc(GMEM_MOVEABLE, byteCount);
        IStream *pStream;
        HRESULT res = ::CreateStreamOnHGlobal(lpBits,TRUE,&pStream);
        bitmap->Save(L"C:/testLoi.bmp",NULL, NULL);
        if(res == S_OK)
        bitmap->Save(pStream,NULL,NULL);
        HRESULT ret = pStream->Read(m_szBuff,m_bmpBufferSize, &m_nRead);
        ofstream fout("C:/log.bmp");
        fout <<m_szBuff;
        fout.close();

    i seen that i can write some bytes, but they are not bitmap's data.... :-(

    a.rongas
    Friday, November 28, 2008 2:45 PM
  • Where's your Seek call?  This sample code created an exact duplicate of a bitmap:

    #include "stdafx.h"
    #include <atlimage.h>
    #include <assert.h>
    #include <stdio.h>

    int _tmain(int argc, _TCHAR* argv[])
    {
      CImage image;
      HRESULT hr;
      // Load sample image
      hr = image.Load(L"c:\\temp\\test.bmp");
      assert(hr == S_OK);

      // Calculate reasonably safe buffer size
      int stride = 4 * ((image.GetWidth() + 3) / 4);
      size_t safeSize = stride * image.GetHeight() * 4 + sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER) + 256 * sizeof(RGBQUAD);
      HGLOBAL mem = GlobalAlloc(GHND, safeSize);
      assert(mem);

      // Create stream and save bitmap
      IStream* stream = 0;
      hr = CreateStreamOnHGlobal(mem, TRUE, &stream);
      assert(hr == S_OK);
      hr = image.Save(stream, Gdiplus::ImageFormatBMP);
      assert(hr == S_OK);

      // Allocate buffer for saved image
      LARGE_INTEGER seekPos = {0};
      ULARGE_INTEGER imageSize;
      hr = stream->Seek(seekPos, STREAM_SEEK_CUR, &imageSize);
      assert(hr == S_OK && imageSize.HighPart == 0);
      BYTE* buffer = new BYTE[imageSize.LowPart];

      // Fill buffer from stream
      hr = stream->Seek(seekPos, STREAM_SEEK_SET, 0);
      assert(hr == S_OK);
      hr = stream->Read(buffer, imageSize.LowPart, 0);
      assert(hr == S_OK);

      // Save to disk
      FILE* fp = 0;
      errno_t err = _wfopen_s(&fp, L"c:\\temp\\copy.bmp", L"wb");
      assert(err == 0 && fp != 0);
      fwrite(buffer, 1, imageSize.LowPart, fp);
      fclose(fp);

      // Cleanup
      stream->Release();
      delete[] buffer;
      return 0;
    }



    Hans Passant.
    • Marked as answer by a.rongas Saturday, November 29, 2008 2:38 PM
    Friday, November 28, 2008 4:31 PM
    Moderator
  • Thank you nobuz your solution works perfect and it was of great help to me to understand what i am doing wrong.  I used  something similar. Extra information for people needing help on the above, can also be found at
    http://www.microsoft.com/communities/newsgroups/en-us/default.aspx?dg=microsoft.public.win32.programmer.gdi&tid=e20262fa-923b-4edc-afdf-f83850036837&cat=&lang=en&cr=US&sloc=&p=1


    a.rongas
    Saturday, November 29, 2008 2:37 PM