Как создать строку в кодировке Base64 из образа GDI + в C ++? - PullRequest
0 голосов
/ 14 мая 2010

Я недавно задал вопрос, Как я могу создать образ в GDI + из строки с кодировкой Base64 в C ++? , который получил ответ, который привел меня к ответу.

Теперь мне нужно сделать обратное - у меня есть изображение в GDI +, данные изображения которого мне нужно превратить в строку в кодировке Base64. Из-за своей природы это не так просто.

Суть проблемы в том, что Image в GDI + может сохранять свои данные либо в файл, либо в IStream *. Я не хочу сохранять в файл, поэтому мне нужно использовать полученный поток. Проблема в том, что здесь мои знания рушатся.

Эта первая часть - то, что я понял в другом вопросе

// Initialize GDI+.
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

// I have this decode function from elsewhere
std::string decodedImage = base64_decode(Base64EncodedImage);

// Allocate the space for the stream
DWORD imageSize = decodedImage.length();
HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE, imageSize);
LPVOID pImage = ::GlobalLock(hMem);    
memcpy(pImage, decodedImage.c_str(), imageSize);

// Create the stream
IStream* pStream = NULL;
::CreateStreamOnHGlobal(hMem, FALSE, &pStream);

// Create the image from the stream
Image image(pStream);

// Cleanup
pStream->Release();
GlobalUnlock(hMem);
GlobalFree(hMem);

( Код Base64 )

А теперь я собираюсь выполнить операцию с результирующим изображением, в данном случае повернуть его, и теперь я хочу, чтобы строка, эквивалентная Base64, была завершена.

// Perform operation (rotate)
image.RotateFlip(Gdiplus::Rotate180FlipNone);

IStream* oStream = NULL;

CLSID tiffClsid;
GetEncoderClsid(L"image/tiff", &tiffClsid);  // Function defined elsewhere
image.Save(oStream, &tiffClsid);

// And here's where I'm stumped. 

(* 1 021 * GetEncoderClsid * * тысяча двадцать-дв) * * тысяча двадцать-три

Так что в итоге я получаю объект IStream *. Но здесь мои знания и Google разрушаются для меня. IStream не должен быть самим объектом, это интерфейс для других типов потоков. Я бы пошел по дороге от получения строки-> Изображение в обратном порядке, но я не знаю, как определить размер потока, который, по-видимому, является ключевым для этого маршрута.

Как я могу перейти от IStream * к строке (которую я затем буду Base64-Encode)? Или есть намного лучший способ перейти от GDI + Image к строке?

1 Ответ

0 голосов
/ 14 мая 2010

Понял

std::string RotateImage(const std::string &Base64EncodedImage)
{
    // Initialize GDI+.
    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    std::string decodedImage = base64_decode(Base64EncodedImage);

    DWORD imageSize = decodedImage.length();
    HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE, imageSize);
    LPVOID pImage = ::GlobalLock(hMem);
    memcpy(pImage, decodedImage.c_str(), imageSize);

    IStream* pStream = NULL;
    ::CreateStreamOnHGlobal(hMem, FALSE, &pStream);

    Image image(pStream);

    image.RotateFlip(Gdiplus::Rotate180FlipNone);

    pStream->Release();
    GlobalUnlock(hMem);
    GlobalFree(hMem);

    IStream* oStream = NULL;
    CreateStreamOnHGlobal(NULL, TRUE, (LPSTREAM*)&oStream);

    CLSID tiffClsid;
    GetEncoderClsid(L"image/tiff", &tiffClsid);
    image.Save(oStream, &tiffClsid);

    ULARGE_INTEGER ulnSize;
    LARGE_INTEGER lnOffset;
    lnOffset.QuadPart = 0;
    oStream->Seek(lnOffset, STREAM_SEEK_END, &ulnSize);
    oStream->Seek(lnOffset, STREAM_SEEK_SET, NULL);

    char *pBuff = new char[(unsigned int)ulnSize.QuadPart];
    ULONG ulBytesRead;
    oStream->Read(pBuff, (ULONG)ulnSize.QuadPart, &ulBytesRead);

    std::string rotated_string = base64_encode((const unsigned char*)pBuff, ulnSize.QuadPart);

    return rotated_string;
}

Хитрость, вдохновленная тем, что я получил из этой статьи , заключается в том, чтобы знать метод определения размера потока и его считывания в массив символов. Затем я могу передать этот массив функции base64_encode и вуаля.

...