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

У меня есть приложение, написанное в настоящее время на C #, которое может взять строку в кодировке Base64 и превратить ее в изображение (в данном случае это изображение TIFF), и наоборот. В C # это на самом деле довольно просто.

    private byte[] ImageToByteArray(Image img)
    {
        MemoryStream ms = new MemoryStream();
        img.Save(ms, System.Drawing.Imaging.ImageFormat.Tiff);
        return ms.ToArray();
    }

    private Image byteArrayToImage(byte[] byteArrayIn)
    {
        MemoryStream ms = new MemoryStream(byteArrayIn);
        BinaryWriter bw = new BinaryWriter(ms);
        bw.Write(byteArrayIn);
        Image returnImage = Image.FromStream(ms, true, false);
        return returnImage;
    }

    // Convert Image into string
    byte[] imagebytes = ImageToByteArray(anImage);
    string Base64EncodedStringImage = Convert.ToBase64String(imagebytes);

    // Convert string into Image
    byte[] imagebytes = Convert.FromBase64String(Base64EncodedStringImage);
    Image anImage = byteArrayToImage(imagebytes);

(и теперь, когда я смотрю на это, можно упростить еще больше)

Теперь у меня есть бизнес-необходимость сделать это на C ++. Я использую GDI + для рисования графики (пока только для Windows), и у меня уже есть код для декодирования строки в C ++ (в другую строку). Однако я спотыкаюсь о получении информации в объект Image в GDI +.

На данный момент, я думаю, мне нужно либо

a) Способ преобразования этой строки, декодированной Base64, в IStream для подачи в функцию FromStream объекта Image

b) Способ преобразования строки в кодировке Base64 в IStream для подачи в функцию FromStream объекта Image (так, код, отличный от того, который я сейчас использую)

в) Каким-то совершенно другим способом, о котором я здесь не думаю.

Мои навыки C ++ очень ржавые, и я также избалован управляемой платформой .NET, поэтому, если я атакую ​​все это неправильно, я открыт для предложений.

ОБНОВЛЕНИЕ: В дополнение к решению, которое я опубликовал ниже, я также выяснил, как пойти другим путем , если кому-то это нужно.

Ответы [ 2 ]

8 голосов
/ 03 мая 2010

ОК, используя информацию из декодера Base64, которую я связал, и примера Бен Штрауба, я получил его на работу

using namespace Gdiplus; // Using GDI+

Graphics graphics(hdc); // Get this however you get this

std::string encodedImage = "<Your Base64 Encoded String goes here>";

std::string decodedImage = base64_decode(encodedImage); // using the base64 
                                                        // library I linked

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

graphics.DrawImage(&image, destRect);

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

Я уверен, что его можно значительно улучшить, но это работает.

4 голосов
/ 01 мая 2010

Это должен быть двухэтапный процесс. Во-первых, декодируйте base64 в чистый двоичный файл (биты, которые были бы у вас, если бы вы загружали TIFF из файла). первый результат Google выглядит довольно неплохо.

Во-вторых, вам нужно преобразовать эти биты в объект Bitmap. Я следовал этому примеру , когда мне приходилось загружать изображения из таблицы ресурсов.

...