Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« : 06-09-2011 07:59 » |
|
Мне скоро потребуется сделать такую вещь - покадрово рисовать будущий гиф, затем собирать его в готовый стандартный анимированный файл
вот такой вопрос - в WINAPI, DirectX или GDI+ есть ли какой-то компонент, которы поможет в этом нелёгком деле, или весь формат придётся вручную лопатить ? Особенно вопрос про сжатие - что там используется ?
Пока только удочку закидываю, вдруг кто работал , сам я только вечером смогу порыться и поискать детали
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #1 : 06-09-2011 08:18 » |
|
Леш, думаю, что тебе нужно воспользоваться сторонней библиотекой. Только ищи ту, которая поддерживает многокадровость. http://ru.wikipedia.org/wiki/GIF
|
|
« Последнее редактирование: 06-09-2011 08:22 от RXL »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #2 : 06-09-2011 08:21 » |
|
ок, поищу
|
|
|
Записан
|
|
|
|
zubr
Гость
|
|
« Ответ #3 : 06-09-2011 10:22 » |
|
Алексей1153++, CDI+ вполне сгодится. Смотри в сторону class Image : public GdiplusBase, метод Image::SaveAdd, хидер GdiplusHeaders.h
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #4 : 06-09-2011 15:58 » |
|
zubr, спасибо.
|
|
|
Записан
|
|
|
|
baldr
|
|
« Ответ #5 : 07-09-2011 06:37 » |
|
|
|
|
Записан
|
Приличный компьютер всегда будет стоить дороже 1000 долларов, потому что 500 долларов - это не вполне прилично
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #6 : 07-09-2011 06:59 » |
|
baldr, спасибо, тоже пригодится )
Ещё не смотрел детально ничего - зак пока телится, выбирает кандидатов. Я другим заданием поэтому щас занят ))
|
|
|
Записан
|
|
|
|
RuNTiME
|
|
« Ответ #7 : 07-09-2011 07:32 » |
|
|
|
|
Записан
|
Любимая игрушка - debugger ...
|
|
|
RXL
|
|
« Ответ #8 : 07-09-2011 08:18 » |
|
Версия GIF87 не поддерживает анимацию - только GIF89.
Добавлено через 52 секунды: GIFLIB я первым делом осмотрел. Проект заморожен в 2005-2006 году. Качество и степень готовности не ясны.
|
|
« Последнее редактирование: 07-09-2011 08:19 от RXL »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #9 : 07-09-2011 09:50 » |
|
всё, он созрел ) Вечером приступаю к разбирательствам, потом отпишусь, что вышло для памяти ссылку оставлю http://www.rsdn.ru/article/gdi/gdiplus2mag.xmlhttp://www.w3.org/Graphics/GIF/spec-gif89a.txthttp://home.onego.ru/~chiezo/gif.htm (картинисто) Добавлено через 6 часов, 27 минут и 37 секунд:вот сразу какие-то невнятные проблемы #include "GdiplusHeaders.h"
Gdiplus::Image* I1=0; I1=I1->FromFile(L"1.gif"); // возвращает 0
Gdiplus::Image I2(L"1.gif"); //валится
файл 1.gif - лежит на диске рядом с экзешником (впрочем, полный путь тоже пробовал) второй вариант вылится здесь: Image::Image( IN const WCHAR* filename, IN BOOL useEmbeddedColorManagement ) { nativeImage = NULL; if(useEmbeddedColorManagement) { lastResult = DllExports::GdipLoadImageFromFileICM( filename, &nativeImage ); } else { lastResult = DllExports::GdipLoadImageFromFile( // <<<<<<<<<<<<<<<<<<<<<< ВОТ ТУТ filename, &nativeImage ); } }
при этом пищит про такое ощущение, что где-то неправильно описан экспорт из GdiPlus.dll (если правильно понимаю) Добавлено через 23 минуты и 17 секунд:попробовал вызвать функцию вручную - тот же результат! При этом адрес функции очень странный Gdiplus::GpStatus (WINGDIPAPI *_GdipLoadImageFromFile)(GDIPCONST WCHAR* filename, Gdiplus::GpImage **image)=0;
HMODULE h=::LoadLibrary(L"GdiPlus.dll");
((void*&)_GdipLoadImageFromFile)=::GetProcAddress(h,"GdipLoadImageFromFile"); //_GdipLoadImageFromFile==0x4ec1c8d8
Gdiplus::GpImage* nativeImage=0; Gdiplus::Status lastResult = _GdipLoadImageFromFile(L"1.gif",&nativeImage);
|
123.GIF (4.7 Кб - загружено 3026 раз.)
|
« Последнее редактирование: 08-09-2011 06:31 от Алексей1153++ »
|
Записан
|
|
|
|
zubr
Гость
|
|
« Ответ #10 : 07-09-2011 17:41 » |
|
А ты инициализацию GDI+ сделал? - GdiplusStartup
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #11 : 07-09-2011 17:45 » |
|
нет, откуда ж знать ) Щас попробую
Добавлено через 14 минут и 7 секунд: ага, оно самое
Добавлено через 16 минут и 35 секунд: А создать "чистый" экземпляр Image, выходит, нельзя ? То есть, только из существующего файла или стрима ?
|
|
« Последнее редактирование: 07-09-2011 18:16 от Алексей1153 »
|
Записан
|
|
|
|
zubr
Гость
|
|
« Ответ #12 : 07-09-2011 19:26 » |
|
Почему нельзя. 1. Создай объект Bitmap(IN INT width, IN INT height, IN PixelFormat format = PixelFormat32bppARGB); 2. Создай объект Graphics(IN Image* image) по битмапу. 3. Рисуешь, используя методы Graphics 4. Сохраняешь битмап Bitmap::Save
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #13 : 07-09-2011 19:53 » |
|
понятно, спасибо. А вот ещё проблема - не пойму, как добавить новые кадры (не содержимое, а именно в принципе ещё кадры) ? В примере http://msdn.microsoft.com/en-us/library/ms535408(v=VS.85).aspxиспользуется файл , у которого уже 4 кадра есть, их просто перерисовывают. Если же у меня гиф однокадровый, то SaveAdd для 2 кадра обламывается Gdiplus::Status st;
Gdiplus::EncoderParameters ep={0}; ULONG parameterValue=0; GUID dimension = Gdiplus::FrameDimensionPage;
// An EncoderParameters object has an array of // EncoderParameter objects. In this case, there is only // one EncoderParameter object in the array. ep.Count = 1;
// Initialize the one EncoderParameter object. ep.Parameter[0].Guid = Gdiplus::EncoderSaveFlag; ep.Parameter[0].Type = Gdiplus::EncoderParameterValueTypeLong; ep.Parameter[0].NumberOfValues = 1; ep.Parameter[0].Value = ¶meterValue;
Gdiplus::Image I1(L"1.gif"); Gdiplus::Image I2(L"2.gif");
// Get the CLSID of the GIF encoder. CLSID encoderClsid; GetEncoderClsid(L"image/gif", &encoderClsid);
//сохраняем новый гиф st=I2.Save(L"3.gif",&encoderClsid); //создаётся нормально
// пытаемся добавить ещё кадр parameterValue = Gdiplus::EncoderValueFrameDimensionPage; st=I2.SelectActiveFrame(&dimension, 1); //неудачно //st==Win32Error
st=I2.SaveAdd(&I1,&ep);
// Close the multiframe file. parameterValue = Gdiplus::EncoderValueFlush; st=I2.SaveAdd(&ep);
И ещё - не могу найти, где определена GetEncoderClsid (используется в примерах) , победил только взяв с левого сайта реализацию GetEncoderClsid http://d34dm4st3rs.narod.ru/hkc/gdi32_shpion.htmlДобавлено через 13 минут и 44 секунды:дело у меня в том, что кадров будет случайное количество. Их надо как-то на лету добавлять , Добавлено через 8 минут и 38 секунд:Более того, если загружаю многокадровый, сохраняю - там остаётся один кадр O_O
|
|
« Последнее редактирование: 07-09-2011 20:16 от Алексей1153 »
|
Записан
|
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #15 : 08-09-2011 05:19 » |
|
что же я не так делаю то какая-то головоломка ))) Gdiplus::Status st;
Gdiplus::EncoderParameters ep={0}; ULONG parameterValue=0; GUID dimension = Gdiplus::FrameDimensionPage;
// Initialize the one EncoderParameter object. ep.Count = 1; ep.Parameter[0].Guid = Gdiplus::EncoderSaveFlag; ep.Parameter[0].Type = Gdiplus::EncoderParameterValueTypeLong; ep.Parameter[0].NumberOfValues = 1; ep.Parameter[0].Value = ¶meterValue;
Gdiplus::Image I1(L"1.gif"); Gdiplus::Image I2(L"2.gif");
// Get the CLSID of the GIF encoder. CLSID encoderClsid; GetEncoderClsid(L"image/gif", &encoderClsid);
//сохраняем новый гиф parameterValue = Gdiplus::EncoderValueMultiFrame; st=I2.Save(L"3.gif",&encoderClsid,&ep); //создаётся нормально
//дальше ничего не работает
// пытаемся добавить ещё кадр parameterValue = Gdiplus::EncoderValueFrameDimensionPage; st=I2.SaveAdd(&ep); //работаем с новым кадром st=I2.SelectActiveFrame(&dimension, 1); //записываем туда I1 parameterValue = Gdiplus::EncoderValueFrameDimensionPage; st=I2.SaveAdd(&I1,&ep);
//заканчиваем работу с файлом parameterValue = Gdiplus::EncoderValueFlush; st=I2.SaveAdd(&ep);
Добавлено через 41 секунду:вместо второго и третьего "EncoderValueMultiFrame" также попробовал "EncoderValueFrameDimensionPage" - тоже без эффекта (код в посте я подправил) Добавлено через 19 минут и 38 секунд:вот отсюда беру готовый пример http://topic.csdn.net/u/20071129/09/2892016a-aafe-4743-862b-037f1279c054.htmlи только убираю инициализацию и один кадр, всё остальное без изменений. Добавление кадра всё равно не удаётся { Gdiplus::EncoderParameters encoderParameters; Gdiplus::Status stat; ULONG parameterValue;
// An EncoderParameters object has an array of // EncoderParameter objects. In this case, there is only // one EncoderParameter object in the array. encoderParameters.Count = 1;
// Initialize the one EncoderParameter object. encoderParameters.Parameter[0].Guid = Gdiplus::EncoderSaveFlag; encoderParameters.Parameter[0].Type = Gdiplus::EncoderParameterValueTypeLong; encoderParameters.Parameter[0].NumberOfValues = 1; encoderParameters.Parameter[0].Value = ¶meterValue;
// Get the CLSID of the TIFF encoder. CLSID encoderClsid; GetEncoderClsid(L"image/gif", &encoderClsid);
// Create four image objects. Gdiplus::Image* multi = new Gdiplus::Image(L"1.gif"); Gdiplus::Image* page2 = new Gdiplus::Image(L"2.gif"); Gdiplus::Image* page3 = new Gdiplus::Image(L"3.gif");
// Save the first page (frame). parameterValue = Gdiplus::EncoderValueMultiFrame; stat = multi->Save(L"123.gif", &encoderClsid, &encoderParameters);
//дальше - косяки
// Save the second page (frame). parameterValue = Gdiplus::EncoderValueFrameDimensionPage; stat = multi->SaveAdd(page2, &encoderParameters);
// Save the third page (frame). parameterValue = Gdiplus::EncoderValueFrameDimensionPage; stat = multi->SaveAdd(page3, &encoderParameters);
// Close the multiframe file. parameterValue = Gdiplus::EncoderValueFlush; stat = multi->SaveAdd(&encoderParameters);
delete multi; delete page2; delete page3; return; } блин, может что-то с версией GDIPLUS.DLL ? Добавлено через 22 минуты и 49 секунд:всё, пойду велосипед изобретать - вручную весь файл )))
|
|
« Последнее редактирование: 08-09-2011 06:07 от Алексей1153 »
|
Записан
|
|
|
|
zubr
Гость
|
|
« Ответ #16 : 08-09-2011 06:46 » |
|
Для первого кадра parameterValue должен быть EncoderValueMultiFrame, для последующих - EncoderValueFrameDimensionTime
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #17 : 08-09-2011 07:19 » |
|
zubr, с EncoderValueFrameDimensionTime ничего не поменялось Пока что разбираюсь с "ручным" форматом. Кстати - отличная для этого дока вот http://home.onego.ru/~chiezo/gif.htm
|
|
|
Записан
|
|
|
|
zubr
Гость
|
|
« Ответ #18 : 08-09-2011 07:40 » |
|
Алексей1153++, у себя проверил, в 7-ке получается, в xp нет. Видно надо более новая версия GdiPlus.dll
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #19 : 08-09-2011 07:52 » |
|
zubr, можешь копию прислать на почту? Только пароль единичку поставь, а то яндекс не пропустит. Заранее спасибо )
Если всё ок, я тогда к экзешнику приложу dll
|
|
« Последнее редактирование: 08-09-2011 14:19 от Алексей1153++ »
|
Записан
|
|
|
|
zubr
Гость
|
|
« Ответ #20 : 08-09-2011 08:23 » |
|
Алексей1153++, в xp с GdiPlus.dll от 7-ки все равно не работает.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #21 : 08-09-2011 08:23 » |
|
zubr, это заговор ) Ладно, всё равно уже копаюсь с форматом. Видать, это карма ))
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #22 : 09-09-2011 17:37 » |
|
ааа, запарка! Спасите ))) Вроде же разобрался с форматом вдоль и поперёк, а всё равно что-то не так... Вернее, на алгоритме LZW что-то у меня не так. По теории получается одна последовательность, а программы-просмотрщики не понимают, кроме того - если из программ сохранять точно такой же гиф, то у них сжатая часть совсем другая по содержанию - причём я совершенно не могу въехать, по какому принципу
сейчас примеры закину, может кто подскажет, в какую сторону копать (
|
|
|
Записан
|
|
|
|
RuNTiME
|
|
« Ответ #23 : 09-09-2011 18:01 » |
|
|
|
|
Записан
|
Любимая игрушка - debugger ...
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #24 : 09-09-2011 19:29 » |
|
рассказываю по порядку 1) пусть для примера имеем такую картинку fit1.gif 2*4 , 8 битную. В ней 6 белых пикселов сверху и 2 чёрных снизу. (она тут очень маленькая - плохо видно. Смотрите в аттаче) этот гиф создан графпрограммой и корректен до невозможности - на него равняемся. Содержимое гифа такое: длинная палитра, кстати, - 256 элементов, из них используются только первые 2. Хотя, это неважно в моём вопросе (ну, так захотелось программе, что ли) 2) теперь создаю в своей программе такой же битмап и засовываю его в формат гиф по инструкции http://home.onego.ru/~chiezo/gif.htm сохраняю в файл 1234.gif содержимое этот файл графпрограммы не понимают ( вернее, размер понимают правильно, а пикселы не те) несмотря на большое визуальное различие хексов, 1234.gif отличается от fit1.gif только блоком сжатой графики, всё остальное сделано корректно. доказательство: заменяем корявый блок графики файла 1234.gif ( 04 0B 0C 0D 01 , где 04 - длина данных) на соответствующий блок из fit1.gif ( 08 00 01 08 1C 18 20 40 40 , где 08 - длина данных)и графпрограмма сразу же начинает воспринимать и показывать гиф так, как нужно Вывод - я косячу в алгоритме сжатия. Но я его изучил хорошо, он несложный http://home.onego.ru/~chiezo/lzw.htmВ процессе упаковки получаю следующий словарь: 0 0, (индекс чёрного цвета) 1 1, (индекс белого цвета) 2 2, 3 3, 4 4, 5 5, 6 6, 7 7, 8 8, 9 9,==<CC> a a,==<EOI> b 0,0 c 0,0,0 d 0,1 архив у меня получился такой [0B 0C 0D 01] если согласно нему раскодировать, картинка должна получиться ЧТО ЖЕ я опять не учёл ? Добавлено через 3 минуты и 33 секунды:RuNTiME, щас гляну, спасибо. Я уже в отчаянии )) сроки горят Добавлено через 3 минуты и 5 секунд:RuNTiME, кстати, таких исходников на чистом Си я много находил, но за каждый страшно браться ) Видимо, придётся всё же
|
1__1.PNG (12.82 Кб - загружено 2993 раз.)
fit1.gif (0.78 Кб - загружено 3003 раз.)
1__3.PNG (2.73 Кб - загружено 2976 раз.)
|
« Последнее редактирование: 09-09-2011 19:33 от Алексей1153 »
|
Записан
|
|
|
|
RuNTiME
|
|
« Ответ #25 : 09-09-2011 19:37 » |
|
Я уже в отчаянии )) сроки горят Алексей1153++, Так может лучше взять готовую библиотеку? А потом, когда сроки перестанут гореть, можно и с форматами по разбираться в свое удовольствие....
|
|
|
Записан
|
Любимая игрушка - debugger ...
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #26 : 09-09-2011 19:44 » |
|
RuNTiME, да я не против, я не нашёл такую. Мне исходники нужны, так как это должна быть отдельная одинокая DLL Сейчас код по твоей ссылке скопировал - а там нумерация строк Хвала аллаху, что в студии макросы есть, за минуту убрал нумерацию Добавлено через 2 минуты и 8 секунд:тут вот тоже полезная, должно быть, функция, только там куча неизвестных типов, да и параметры не описаны - что к чему http://www.solidfluid.co.uk/sfsite.php/000000D6
|
|
« Последнее редактирование: 09-09-2011 19:50 от Алексей1153++ »
|
Записан
|
|
|
|
RuNTiME
|
|
« Ответ #27 : 09-09-2011 19:53 » |
|
Сейчас код по твоей ссылке скопировал - а там нумерация строк... Алексей1153++, эмм там все гораздо проще... когда наводишь мышку на исходники, в правом верхнем углу 3 кнопочки появляются одна из них View Source тут вот тоже полезная, должно быть, функция, только там куча неизвестных типов... Там примерчики есть: ToGIF, FromGIF...
|
|
|
Записан
|
Любимая игрушка - debugger ...
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #28 : 09-09-2011 20:01 » |
|
ок, понятно. Там, оказывается, по файлам раскидано, а я то думаю - что половины не хватает )
|
|
|
Записан
|
|
|
|
RuNTiME
|
|
« Ответ #29 : 09-09-2011 20:05 » |
|
Алексей1153++, А можно и в сторону giflib посмотреть, не знаю почему её сразу отклонили, она по умолчанию в последней ubuntu'шке используется и под винду её можно скомпилить...
|
|
|
Записан
|
Любимая игрушка - debugger ...
|
|
|
|