2009-07-07 5 views
4

Dies ist mein erster Beitrag hier. Ich habe ein Problem. Ich muss einen Screenshot des Desktops machen, ihn in JPEG konvertieren, in einem Puffer speichern und dann manipulieren und über das Internet senden.Holen Sie sich die Größe von JPEG aus dem Speicher (konvertiert mit GDI ++)

Ich habe den Code dafür mit GetDC .... und GDI + für die Umwandlung der HBITMAP in JPEG geschrieben. Das Problem, das ich jetzt habe, ist, dass ich die Größe der JPEG nicht kenne, die in IStream gespeichert worden ist. Hier ist ein Teil des Codes, der die von der HBITMAP hBackBitmap referenzierte Bitmap in jpeg transformiert und in pStream speichert. Ich muss wissen, wie viele Bytes in pStream geschrieben wurden und wie ich pStream verwenden können (eine PVOID Griff bekommen):

Gdiplus::Bitmap bitmap(hBackBitmap, NULL);///loading the HBITMAP 
CLSID clsid; 
GetEncoderClsid(L"image/jpeg", &clsid); 
HGLOBAL hGlobal = GlobalAlloc(GMEM_FIXED, nBlockSize) ;//allocating memory, the size of the current bitmap size. i'm over allocating but i don't think there is any way to get the exact ammount I need to allocate, is there? 
if(!hGlobal) 
    return; 
IStream* pStream = NULL ; 
if(CreateStreamOnHGlobal(hGlobal, TRUE, &pStream) != S_OK) 
    return; 
bitmap.Save(pStream, &clsid); 

Was ich brauche, ist: 1. die Größe der JPEG-Finden Sie heraus, wie viele Bytes wurden in den Stream geschrieben 2. Wie verwendet man den Stream. Kann ich beispielsweise eine PVOID für die Daten im Stream erhalten?

Vielen Dank.

Antwort

5

Nach the CreateStreamOnHGlobal Dokumentation ist Ihre Verwendung davon nicht korrekt. Quote:

Der aktuelle Inhalt des Speicherblocks wird durch die Erstellung des neuen Stream-Objekts ungestört. Daher können Sie diese Funktion verwenden, um einen vorhandenen Stream im Speicher zu öffnen. Die anfängliche Größe des Streams entspricht der Größe des von der GlobalSize-Funktion zurückgegebenen Speicher-Handles.

Daher sollten Sie nBlockSize durch 0 ersetzen, um einen Puffer der Größe 0 zuzuweisen. Da der Speicherpuffer beweglich sein muss, werden Sie auch GMEM_FIXED mit GMEM_MOVEABLE ersetzen müssen:

HGLOBAL gGlobal = GlobalAlloc(GMEM_MOVEABLE, 0); 

zum Stream Nach dem Speichern wird die resultierende Größe als

verfügbar sein
size_t size = GlobalSize(hGlobal); 

die JPEG Für den Zugriff auf Für codierte Daten müssen Sie GlobalLock verwenden, um einen Zeiger auf den tatsächlichen Speicherort im Speicher zu erhalten.

Beachten Sie, dass globale und lokale Funktionen als veraltet markiert sind und nicht mehr verwendet werden sollten, aber ich kenne keine bessere IStream-Implementierung für Ihre Anforderungen, ohne die MSDN-Dokumentation zu crawlen. Vielleicht kann hier jemand anderes helfen !?

+0

Vielen Dank. Dies ist eine gute Lösung, da ich keinen zusätzlichen Speicher für den Stream reservieren muss. – Nemok

1

OK fand ich die Lösung für dieses Problem hier: http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/6dfc2e62-e2d1-4be3-a93b-a7d97d3f8469

Ich werde es auch hier für die Zukunft gestellt. Um herauszufinden, welche Größe in den Stream geschrieben wurde, kann man die Methode Seek des Streams verwenden. Um Zugriff auf den Puffer zu erhalten, können Sie Read verwenden.

// 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); 


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