Преобразование растрового изображения в PNG в памяти в C ++ (win32)

Могу ли я преобразовать растровое изображение в PNG в памяти (то есть без записи в файл), используя только SDK платформы? (т.е. нет libpng и т. д.).

Я также хочу иметь возможность определить прозрачный цвет (не альфа-канал) для этого изображения.

Похоже, что решение GdiPlus ограничено изображениями шириной, кратной 4 . Все остальное терпит неудачу во время вызова Save (). Кто-нибудь знает причину этого ограничения и как / могу ли я обойти это?

Обновление: Баунти

Я начинаю вознаграждение (я действительно хочу, чтобы это работало). Я реализовал решение GDI +, но, как я уже сказал, оно ограничено изображениями с четырехугольной шириной. Награда будет предоставлена ​​любому, кто может решить эту проблему ширины (без изменения размеров изображения), или может предложить альтернативное решение без GDI +, которое работает.

14.12.2008 17:34:31
Для начала я нашел пример сохранения растрового изображения в формате png с помощью gdi +: dotnet-snippets.de/dns/gdi-speichern-eines-png-SID814.aspx, может быть, это полезно
Johannes Schaub - litb 14.12.2008 17:39:25
Это решение работает для меня даже с изображениями, ширина которых не делится на 4. Я работаю в Windows Vista и использую Visual C ++ 2008.
Gabriele D'Antona 11.02.2009 19:38:25
Почему вы не хотите использовать libpng? У него очень разрешительная лицензия.
Adam Rosenfield 11.02.2009 20:10:13
Libpng выполняет кодирование в памяти? (или только к файлам?)
Assaf Lavie 12.02.2009 11:20:46
Вы можете перехватить вывод libpng с помощью png_set_write_fn и делать с ним все, что захотите.
timday 12.02.2009 20:35:44
8 ОТВЕТОВ
РЕШЕНИЕ

Я читаю и пишу PNG с использованием libpng, и кажется, что он имеет дело со всем, что я к нему добавляю (я использовал его в модульных тестах с такими вещами, как изображения размером 257x255, и они не вызывают проблем) Я считаю, что API достаточно гибок, чтобы его нельзя было привязать к файловому вводу- выводу (или, по крайней мере, вы можете изменить его поведение по умолчанию, например, см. png_set_write_fnВ разделе о настройке )

На практике я всегда использую его через гораздо чище подталкивание :: Gil расширение PNG IO , но , к сожалению, принимает char*имена файлов , и если вы копаться в ней png_writerи file_mgrклассы в его реализации , кажется , довольно привязаны к FILE*(хотя , если вы были на Linux версия , использующая буферы fmemopen и in-memory, вероятно, могут быть созданы довольно легко).

15
11.02.2009 20:57:32
+1 спасибо. Могу ли я узнать, как использовать Boost :: GIL с PNG IO? Я понятия не имею об интеграции и использовании этого.
Viet 26.02.2010 14:12:50
Boost GIL включает в себя «расширение IO», которое в настоящее время включает в себя поддержку базового чтения и записи в файлы PNG, но не обеспечивает достаточного количества хуков для чтения / записи потоков в памяти, о чем просил оригинальный автор. Похоже, в разработке находится новое расширение ввода-вывода (например, «увеличить новое расширение ввода-вывода GIL» для поиска различных сообщений), которое, похоже, даст гораздо больше гибкости в этой области.
timday 2.03.2010 20:29:32
libpng, хотя и является хорошим решением, похоже, нарушает ограничение вопроса «использовать только Platform SDK».
Adrian McCarthy 31.10.2011 21:35:18
Как мне установить эту библиотеку, пожалуйста? Или мне нужно просто получить исходный код?
Lucie kulza 28.03.2014 00:21:26
@ Люси: я также боролся с поиском версии для Windows; см. мой другой вопрос stackoverflow.com/questions/8669163/… . Разработка Windows сводит меня с ума такими вещами, по сравнению с Linux, где вы можете просто apt-get install libpng-dev и хорошо поработать за считанные секунды.
timday 28.03.2014 12:55:39

Вероятно, было бы лучше использовать библиотеку, а не изобретать велосипед самостоятельно.

Посмотрите на freeImage

2
14.12.2008 17:51:11

На этом сайте код показывает, как преобразовать растровое изображение в 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 ). Вы можете создать поток, резервное копирование которого осуществляется с помощью памяти, с помощью CreateStreamOnHGlobalфункции API. ( http://msdn.microsoft.com/en-us/library/aa378980%28VS.85%29.aspx ). Используемая библиотека GDI + включена в Windows, начиная с WindowsXP, и работает в Windows, начиная с Windows98. Я никогда ничего с этим не делал, просто гуглил вокруг. Похоже, вы можете использовать это, хотя.

12
14.12.2008 17:54:49
Как насчет проблемы GDI +, о которой я упоминал в первоначальном вопросе?
Assaf Lavie 1.11.2011 05:50:01

Я использовал GDI + для сохранения растрового изображения в виде PNG в файл. Вам, вероятно, следует проверить информацию MSDN о GDI + здесь и, в частности, эту функцию GdipSaveImageToStream .

Этот учебник здесь , вероятно , предоставить некоторую помощь , а также.

5
14.12.2008 18:38:26

У GDI (старая школа, не плюс) есть GetDIBitsметод, который может быть запрошен для вывода битов с использованием сжатия PNG ( BITMAPINFOHEADER::biCompression == BI_PNG). Интересно, можно ли это использовать для создания файла PNG? Использование GetDIBitsдля записи стандартных растровых файлов достаточно сложно, поэтому я подозреваю, что это будет еще сложнее.

3
7.01.2012 03:48:10
Для тех, кто может подумать о том, чтобы пойти по этому пути, посмотрите ответ «GetDIBits () терпит неудачу со сжатием PNG» или « Расширения JPEG и PNG для определенных растровых функций и структур » в MSDN, на которые он ссылается.
Tamir Evan 11.09.2017 16:53:43

Если вы хотите использовать только API-интерфейсы Windows, WIC - это способ сделать это, и он поддерживает как растровые изображения, так и PNG.

3
7.01.2012 03:49:53
Вы уверены, что он не страдает от такого же странного ограничения ширины, как GDI +?
Assaf Lavie 12.02.2009 11:19:00
Нет, не уверен - но WIC определенно более современен и обновлен, чем GDI +
Ana Betts 12.02.2009 17:02:44

Класс 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.

7
12.02.2009 10:40:09
Увы, в моем проекте нет ATL / MFC.
Assaf Lavie 12.02.2009 11:14:38
хорошо ... может быть, часть сохранения потока может быть полезной, она должна быть похожа на ту, что использует GDI +
djeidot 12.02.2009 12:08:15
Это помогло мне за то, над чем я работал, +1 за это, по крайней мере.
Aardvark 12.02.2009 15:39:43
Я уверен, что это использует libpng
Adam Tegen 12.02.2009 23:42:26

LodePNG ( GitHub ) - это кодировщик / декодер PNG без библиотек .

19
9.11.2018 16:08:07