Преобразование растрового изображения в PNG в памяти на С++ (win32)
Можно ли преобразовать растровое изображение в PNG в память (т.е. без записи в файл), используя только Platform SDK? (т.е. нет libpng и т.д.).
Я также хочу иметь возможность определять прозрачный цвет (не альфа-канал) для этого изображения.
Решение GdiPlus, по-видимому, ограничено изображениями, делящимися на 4. Все остальное не работает во время вызова Save(). Кто-нибудь знает причину этого ограничения и как/я могу обойти его?
Обновление: Bounty
Я начинаю щедрость (я действительно хочу, чтобы это сработало). Я реализовал решение GDI +, но, как я уже сказал, он ограничивается изображениями с шириной квадрата. Щедрость будет доступна каждому, кто может решить эту проблему с шириной (без изменения размеров изображения) или может предложить альтернативное не-GDI + решение, которое работает.
Ответы
Ответ 1
Я читаю и пишу PNG с помощью libpng и, похоже, имеет дело со всем, что я бросаю на него (я использовал его в блоке -tests с такими вещами, как 257x255 изображений, и они не вызывают никаких проблем). Я полагаю, что API достаточно гибкий, чтобы не привязываться к файловому вводу/выводу (или, по крайней мере, вы можете переопределить его поведение по умолчанию, например, см. png_set_write_fn
в разделе настройка)
На практике я всегда использую его с помощью более чистого boost:: gil Расширение PNG IO, но, к сожалению, он принимает имена файлов char*
, и если вы его вставляете в классы png_writer
и file_mgr
, они, похоже, привязаны к FILE*
(хотя, если вы были на Linux версия с использованием fmemopen и буферов в памяти, вероятно, может быть легко подготовлена).
Ответ 2
LodePNG - это кодировщик/декодер PNG без lib.
Ответ 3
На этом сайте код показывает, как преобразовать растровое изображение в PNG, записывая его в файл: http://dotnet-snippets.de/dns/gdi-speichern-eines-png-SID814.aspx. Вместо записи в файл метод Save
Bitmap также поддерживает запись в IStream
(http://msdn.microsoft.com/en-us/library/ms535406%28VS.85%29.aspx). Вы можете создать поток, поддерживаемый памятью, с помощью функции API CreateStreamOnHGlobal
. (http://msdn.microsoft.com/en-us/library/aa378980%28VS.85%29.aspx). Используемая библиотека GDI + включена в Windows от WindowsXP и работает в Windows из Windows98. Я никогда с ним ничего не делал, просто гугл. Похоже, вы можете это использовать.
Ответ 4
Класс CImage (ATL/MFC) поддерживает сохранение в формате PNG. Как и решение GDI +, оно также поддерживает сохранение потока. Здесь некоторый код, который я использую, чтобы сохранить его в CByteArray:
CByteArray baPicture;
IStream *pStream = NULL;
if (CreateStreamOnHGlobal(NULL, TRUE, &pStream) == S_OK)
{
if (image.Save(pStream, Gdiplus::ImageFormatPNG) == S_OK)
{
ULARGE_INTEGER ulnSize;
LARGE_INTEGER lnOffset;
lnOffset.QuadPart = 0;
if (pStream->Seek(lnOffset, STREAM_SEEK_END, &ulnSize) == S_OK)
{
if (pStream->Seek(lnOffset, STREAM_SEEK_SET, NULL) == S_OK)
{
baPicture.SetSize(ulnSize.QuadPart);
ULONG ulBytesRead;
pStream->Read(baPicture.GetData(), ulnSize.QuadPart, &ulBytesRead);
}
}
}
}
pStream->Release();
Я не знаю, хотите ли вы использовать ATL или MFC.
Ответ 5
Я использовал GDI + для сохранения растрового изображения в виде PNG в файл. Вероятно, вы должны проверить информацию MSDN о GDI + здесь и, в частности, эту функцию GdipSaveImageToStream.
Этот учебник здесь, вероятно, также поможет вам.
Ответ 6
GDI (старая школа, не плюс) имеет метод GetDIBits
, который может быть запрошен для вывода битов с использованием сжатия PNG (BITMAPINFOHEADER::biCompression
== BI_PNG
). Интересно, можно ли это использовать для создания PNG файла? Использование GetDIBits
для записи стандартных файлов растровых изображений достаточно сложно - поэтому я подозреваю, что это будет еще сложнее.
Ответ 7
Если вы хотите использовать только API Windows, WIC - это способ сделать это, и он поддерживает как растровые изображения, так и PNG.
Ответ 8
Вероятно, лучше было бы использовать библиотеку, а не изобретать колесо самостоятельно.
Посмотрите freeImage