Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2 3  Все   Вниз
  Печать  
Автор Тема: Как сделать GIF вручную (вернее - программно)  (Прочитано 62783 раз)
0 Пользователей и 3 Гостей смотрят эту тему.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« : 06-09-2011 07:59 » 

Мне скоро потребуется сделать такую вещь - покадрово рисовать будущий гиф, затем собирать его в готовый стандартный анимированный файл


вот такой вопрос - в WINAPI, DirectX или GDI+ есть ли какой-то компонент, которы поможет в этом нелёгком деле, или весь формат придётся вручную лопатить ? Особенно вопрос про сжатие - что там используется ?  

Пока только удочку закидываю, вдруг кто работал , сам я только вечером смогу порыться и поискать детали
Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 06-09-2011 08:18 » 

Леш, думаю, что тебе нужно воспользоваться сторонней библиотекой. Только ищи ту, которая поддерживает многокадровость.

http://ru.wikipedia.org/wiki/GIF
« Последнее редактирование: 06-09-2011 08:22 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #4 : 06-09-2011 15:58 » 

zubr, спасибо.
Записан

baldr
Команда клуба

cy
Offline Offline
Пол: Мужской
Дорогие россияне


WWW
« Ответ #5 : 07-09-2011 06:37 » 

http://habrahabr.ru/blogs/algorithm/127083/
Записан

Приличный компьютер всегда будет стоить дороже 1000 долларов, потому что 500 долларов - это не вполне прилично
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #6 : 07-09-2011 06:59 » 

baldr, спасибо, тоже пригодится )

Ещё не смотрел детально ничего - зак пока телится, выбирает кандидатов. Я  другим заданием поэтому щас занят ))
Записан

RuNTiME
Помогающий

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 07-09-2011 07:32 » 

Библиотека для работы с GIF, ос Linux / Windows:
http://sourceforge.net/projects/giflib/

И небольшое описание её возможностей:
http://rus-linux.net/nlib.php?name=/MyLDP/BOOKS/BLFS-ru/09/blfs-ru-09-04.html
Записан

Любимая игрушка - debugger ...
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #8 : 07-09-2011 08:18 » 

Версия GIF87 не поддерживает анимацию - только GIF89.

Добавлено через 52 секунды:
GIFLIB я первым делом осмотрел. Проект заморожен в 2005-2006 году. Качество и степень готовности не ясны.
« Последнее редактирование: 07-09-2011 08:19 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #9 : 07-09-2011 09:50 » 

всё, он созрел ) Вечером приступаю к разбирательствам, потом отпишусь, что вышло


для памяти ссылку оставлю
http://www.rsdn.ru/article/gdi/gdiplus2mag.xml
http://www.w3.org/Graphics/GIF/spec-gif89a.txt

http://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
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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 = &parameterValue;

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 » Записан

zubr
Гость
« Ответ #14 : 07-09-2011 20:50 » 

Первый кадр Save надо делать, последующие SaveAdd, также EncoderParameters надо менять.
Посмотри здесь http://forum.sources.ru/index.php?showtopic=328573
Там вроде пример есть, правда на ваське.
Также вот еще по теме:
http://www.rsdn.ru/article/gdi/gdiplus2mag.xml#EMLAC
http://www.foxclub.ru/vfpbook/texts/tiff.htm
« Последнее редактирование: 07-09-2011 20:52 от zubr » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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 = &parameterValue;

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 = &parameterValue;

// 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
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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-ки все равно не работает.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #21 : 08-09-2011 08:23 » 

zubr, это заговор ) Ладно, всё равно уже копаюсь с форматом. Видать, это карма ))
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #22 : 09-09-2011 17:37 » 

ааа, запарка! Спасите ))) Вроде же разобрался с форматом вдоль и поперёк, а всё равно что-то не так... Вернее, на алгоритме LZW что-то у меня не так. По теории получается одна последовательность, а программы-просмотрщики не понимают, кроме того - если из программ сохранять точно такой же гиф, то у них сжатая часть совсем другая по содержанию - причём я совершенно не могу въехать, по какому принципу

сейчас примеры закину, может кто подскажет, в какую сторону копать (
Записан

RuNTiME
Помогающий

ru
Offline Offline
Пол: Мужской

« Ответ #23 : 09-09-2011 18:01 » new

Алексей1153++, Возможно поможет Улыбаюсь http://www.solidfluid.co.uk/sfsite.php/000000CF
Записан

Любимая игрушка - debugger ...
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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 Кб - загружено 3004 раз.)
* 1__3.PNG (2.73 Кб - загружено 2977 раз.)
« Последнее редактирование: 09-09-2011 19:33 от Алексей1153 » Записан

RuNTiME
Помогающий

ru
Offline Offline
Пол: Мужской

« Ответ #25 : 09-09-2011 19:37 » 

Цитата
Я уже в отчаянии )) сроки горят

Алексей1153++, Так может лучше взять готовую библиотеку? А потом, когда сроки перестанут гореть, можно и с форматами по разбираться в свое удовольствие....
Записан

Любимая игрушка - debugger ...
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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
Помогающий

ru
Offline Offline
Пол: Мужской

« Ответ #27 : 09-09-2011 19:53 » 

Цитата
Сейчас код по твоей ссылке скопировал - а там нумерация строк...

Алексей1153++, эмм там все гораздо проще... когда наводишь мышку на исходники, в правом верхнем углу 3 кнопочки появляются одна из них View Source Улыбаюсь

Цитата
тут вот тоже полезная, должно быть, функция, только там куча неизвестных типов...

Там примерчики есть: ToGIF, FromGIF...
Записан

Любимая игрушка - debugger ...
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #28 : 09-09-2011 20:01 » 

ок, понятно. Там, оказывается, по файлам раскидано, а я то думаю - что половины не хватает )
Записан

RuNTiME
Помогающий

ru
Offline Offline
Пол: Мужской

« Ответ #29 : 09-09-2011 20:05 » 

Алексей1153++, А можно и в сторону giflib посмотреть, не знаю почему её сразу отклонили, она по умолчанию в последней ubuntu'шке используется и под винду её можно скомпилить...
Записан

Любимая игрушка - debugger ...
Страниц: [1] 2 3  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines