Форум программистов, компьютерный форум, киберфорум
Visual Basic
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.70/30: Рейтинг темы: голосов - 30, средняя оценка - 4.70
 Аватар для fireday
307 / 138 / 6
Регистрация: 17.04.2013
Сообщений: 1,943

Разбивка GIF на PNG с сохранением альфа канала

30.10.2013, 00:37. Показов 6665. Ответов 25
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Собственно в названии темы и сама суть вопроса

Нашел алгоритм разбивки GIF
но одно большое НО - изображения (отличные от первого) получают размер не GIF, а самой картинки, обрезанной по краям до первых цветных пикселей (т.е. лишний фон без содержания удаляется)
Это алгоритм формата GIF для уменьшения размера файла?
Или алгоритм изъятия имеет свои минусы ? (хотя я не увидел там обрезки лишнего...)
исходники прилагаю
Вложения
Тип файла: rar GIF_play_on_vb6_my_version.rar (49.2 Кб, 77 просмотров)
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
30.10.2013, 00:37
Ответы с готовыми решениями:

Редактирование альфа канала (для png)
Доброго времени суток. :wall:Возник вопрос: как можно редактировать альфа канал(слой)(например в изображениях формата PNG). Конкретней:...

*.png файл загружается без альфа-канала
Всем привет! У меня проблема, при загрузке *.png файла с альфа каналом он не распознаётся. Для загрузки изображений использую SDL_image....

Какое расширение выбрать JPG/GIF/PNG-8/PNG-24
Применение их

25
Модератор
10057 / 3902 / 884
Регистрация: 22.02.2013
Сообщений: 5,853
Записей в блоге: 79
30.10.2013, 00:53
А не легче использовать для этого GDI+? Если я правильно понял вопрос, то что надо сохранить секвенцию (раскадровку) в каждый файл отдельно.
1
 Аватар для fireday
307 / 138 / 6
Регистрация: 17.04.2013
Сообщений: 1,943
30.10.2013, 01:17  [ТС]
The trick, да, ты все верно понял
Мне не хватает знаний что бы разбить GIF
Если подскажешь куда копать (примерчики какие?), буду благодарен
0
Модератор
10057 / 3902 / 884
Регистрация: 22.02.2013
Сообщений: 5,853
Записей в блоге: 79
30.10.2013, 01:58
Лучший ответ Сообщение было отмечено Памирыч как решение

Решение

По идее, для получения ClsID кодеков надо вызывать GdipGetImageEncodersSize и GdipGetImageEncoders. Я сделал константно. А так сохраняет с прозрачностью в PNG раскадровку в папку с программой.
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
Private Type GdiplusStartupInput
    GdiplusVersion As Long
    DebugEventCallback As Long
    SuppressBackgroundThread As Long
    SuppressExternalCodecs As Long
End Type
Private Type CLSID
   Data1 As Long
   Data2 As Integer
   Data3 As Integer
   Data4(0 To 7) As Byte
End Type
Private Declare Function GdipLoadImageFromFile Lib "gdiplus" (ByVal FileName As String, image As Long) As Long
Private Declare Function GdiplusShutdown Lib "gdiplus" (ByVal token As Long) As Long
Private Declare Function GdiplusStartup Lib "gdiplus" (token As Long, inputbuf As GdiplusStartupInput, Optional ByVal outputbuf As Long = 0) As Long
Private Declare Function GdipImageGetFrameCount Lib "gdiplus" (ByVal image As Long, dimensionID As CLSID, Count As Long) As Long
Private Declare Function GdipSaveImageToFile Lib "gdiplus" (ByVal image As Long, ByVal FileName As String, clsidEncoder As CLSID, encoderParams As Any) As Long
Private Declare Function CLSIDFromString Lib "ole32.dll" (ByVal lpszProgID As Long, pCLSID As CLSID) As Long
Private Declare Function GdipDisposeImage Lib "gdiplus" (ByVal image As Long) As Long
Private Declare Function GdipImageSelectActiveFrame Lib "gdiplus" (ByVal image As Long, dimensionID As CLSID, ByVal frameIndex As Long) As Long
 
Private Const FrameDimensionTime As String = "{6AEDBD6D-3FB5-418A-83A6-7F45229DC872}"
Private Const PngClsID As String = "{557CF406-1A04-11D3-9A73-0000F81EF32E}"
Dim token As Long
 
Private Sub Form_Load()
    Dim GpInput As GdiplusStartupInput
    Dim img As Long, ctfrm As Long, frm As Long
    Dim fName As String
    
    fName = App.Path & "\anim.gif"
    
    GpInput.GdiplusVersion = 1
    If GdiplusStartup(token, GpInput) <> 0 Then MsgBox "Gdi+ error": End
    If GdipLoadImageFromFile(StrConv(fName, vbUnicode), img) = 0 Then
        GdipImageGetFrameCount img, DEFINE_GUID(FrameDimensionTime), ctfrm
        For frm = 0 To ctfrm - 1
            GdipImageSelectActiveFrame img, DEFINE_GUID(FrameDimensionTime), frm
            fName = App.Path & "\Frame" & Format$(frm, "0000\.png")
            GdipSaveImageToFile img, StrConv(fName, vbUnicode), DEFINE_GUID(PngClsID), ByVal 0&
        Next
        GdipDisposeImage img
    End If
    
    GdiplusShutdown token
End Sub
Private Function DEFINE_GUID(ByVal sGuid As String) As CLSID
    Call CLSIDFromString(StrPtr(sGuid), DEFINE_GUID)
End Function
Вложения
Тип файла: rar SplitGif.rar (212.0 Кб, 46 просмотров)
2
 Аватар для fireday
307 / 138 / 6
Регистрация: 17.04.2013
Сообщений: 1,943
30.10.2013, 01:59  [ТС]
The trick, Спасибо большое
0
 Аватар для fireday
307 / 138 / 6
Регистрация: 17.04.2013
Сообщений: 1,943
02.11.2013, 15:52  [ТС]
Еще вопрос, как с помощью gdiplus узнать размер (width, height) кадров гифки?
0
Модератор
10057 / 3902 / 884
Регистрация: 22.02.2013
Сообщений: 5,853
Записей в блоге: 79
02.11.2013, 15:58
Visual Basic
1
2
Private Declare Function GdipGetImageWidth Lib "gdiplus" (ByVal image As Long, Width As Long) As Long
Private Declare Function GdipGetImageHeight Lib "gdiplus" (ByVal image As Long, Height As Long) As Long
1
 Аватар для fireday
307 / 138 / 6
Регистрация: 17.04.2013
Сообщений: 1,943
02.11.2013, 16:08  [ТС]
The trick, благодарю
з.ы. где ты айпишки так быстро ищешь?
0
02.11.2013, 16:10

Не по теме:

Цитата Сообщение от fireday Посмотреть сообщение
где ты айпишки так быстро ищешь?
У меня куча кода, проектов за все время программирования, из них смотрю.

1
 Аватар для fireday
307 / 138 / 6
Регистрация: 17.04.2013
Сообщений: 1,943
02.11.2013, 17:53  [ТС]
Цитата Сообщение от The trick Посмотреть сообщение

Не по теме:


У меня куча кода, проектов за все время программирования, из них смотрю.

Не по теме:

Вот как,)

0
es geht mir gut
 Аватар для SoftIce
11274 / 4760 / 1183
Регистрация: 27.07.2011
Сообщений: 11,439
02.11.2013, 21:43
Лучший ответ Сообщение было отмечено как решение

Решение

The trick, по мотивам Вашего кода набросал программку для просмотра Gif.
Вложения
Тип файла: rar GIF.rar (723.8 Кб, 81 просмотров)
3
 Аватар для fireday
307 / 138 / 6
Регистрация: 17.04.2013
Сообщений: 1,943
03.11.2013, 02:20  [ТС]
SoftIce,
Visual Basic
1
Me.Controls!GIF.Picture = ImgGIF(nFrame).Picture
Me.Controls!GIF.Picture - что за синтаксис такой?
0
Модератор
10057 / 3902 / 884
Регистрация: 22.02.2013
Сообщений: 5,853
Записей в блоге: 79
03.11.2013, 02:29
Цитата Сообщение от fireday Посмотреть сообщение
Me.Controls!GIF.Picture - что за синтаксис такой?
Устаревший способ обращения к элементу коллекции, являющейся свойством по умолчанию.
0
Модератор
10057 / 3902 / 884
Регистрация: 22.02.2013
Сообщений: 5,853
Записей в блоге: 79
03.11.2013, 02:55
Лучший ответ Сообщение было отмечено как решение

Решение

SoftIce, Решил взять Вашу мысль и немного усовершенствовать . Теперь можно просматривать анимацию, в любом окне, у которого есть свойство hWnd. Также соблюдены скорость и количество повторов (как в оригинальном GIF'е), также значимые параметры выводятся на экран. В принципе, если еще немного доработать, то можно засунуть в класс и уже можно работать с анимациями на уровне ООП. Можно приостанавливать, воспроизводить и останавливать "в начало". Отрисовку сделал с "двойной буферизацией", благодаря чему не будет мерцания. Для использования в проекте, просто подключить и вызывать одноименные методы, никаких дополнительных контролов не надо, разумеется кроме контейнера.
Кликните здесь для просмотра всего текста
Модуль:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
Option Explicit
 
Private Type GdiplusStartupInput                                                                ' Структура инициализации GDI+
    GdiplusVersion As Long
    DebugEventCallback As Long
    SuppressBackgroundThread As Long
    SuppressExternalCodecs As Long
End Type
Private Type CLSID
   Data1 As Long
   Data2 As Integer
   Data3 As Integer
   Data4(0 To 7) As Byte
End Type
Public Type PropertyItem                                                                        ' Свойство изображения
   propId As Long
   Length As Long
   type As Long
   value As Long
End Type
Private Type RECT
  iLeft As Long
  iTop As Long
  iRight As Long
  iBottom As Long
End Type
Private Type PAINTSTRUCT
  hdc As Long
  fErase As Long
  rcPaint As RECT
  fRestore As Long
  fIncUpdate As Long
  rgbReserved(31) As Byte
End Type
 
Private Declare Function GdipLoadImageFromFile Lib "gdiplus" (ByVal FileName As String, image As Long) As Long
Private Declare Function GdiplusShutdown Lib "gdiplus" (ByVal token As Long) As Long
Private Declare Function GdiplusStartup Lib "gdiplus" (token As Long, inputbuf As GdiplusStartupInput, Optional ByVal outputbuf As Long = 0) As Long
Private Declare Function GdipImageGetFrameCount Lib "gdiplus" (ByVal image As Long, dimensionID As CLSID, Count As Long) As Long
Private Declare Function CLSIDFromString Lib "ole32.dll" (ByVal lpszProgID As Long, pCLSID As CLSID) As Long
Private Declare Function GdipDisposeImage Lib "gdiplus" (ByVal image As Long) As Long
Private Declare Function GdipImageSelectActiveFrame Lib "gdiplus" (ByVal image As Long, dimensionID As CLSID, ByVal frameIndex As Long) As Long
Private Declare Function GdipGetPropertyItemSize Lib "gdiplus" (ByVal image As Long, ByVal propId As Long, size As Long) As Long
Private Declare Function GdipGetPropertyItem Lib "gdiplus" (ByVal image As Long, ByVal propId As Long, ByVal propSize As Long, buffer As Any) As Long
Private Declare Function GdipGetPropertySize Lib "gdiplus" (ByVal image As Long, totalBufferSize As Long, numProperties As Long) As Long
Private Declare Function GdipDrawImage Lib "gdiplus" (ByVal Graphics As Long, ByVal image As Long, ByVal x As Single, ByVal y As Single) As Long
Private Declare Function GdipCreateFromHDC Lib "gdiplus" (ByVal hdc As Long, Graphics As Long) As Long
Private Declare Function GdipDeleteGraphics Lib "gdiplus" (ByVal Graphics As Long) As Long
Private Declare Function GdipGetImageWidth Lib "gdiplus" (ByVal image As Long, Width As Long) As Long
Private Declare Function GdipGetImageHeight Lib "gdiplus" (ByVal image As Long, Height As Long) As Long
Private Declare Function GdipGraphicsClear Lib "gdiplus" (ByVal Graphics As Long, ByVal lColor As Long) As Long
Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Private Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
Private Declare Function GetClientRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
 
Private Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Private Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function GetMem2 Lib "msvbvm60" (pSrc As Any, pDst As Any) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function BeginPaint Lib "user32" (ByVal hwnd As Long, lpPaint As PAINTSTRUCT) As Long
Private Declare Function EndPaint Lib "user32" (ByVal hwnd As Long, lpPaint As PAINTSTRUCT) As Long
Private Declare Function RedrawWindow Lib "user32" (ByVal hwnd As Long, lprcUpdate As Any, ByVal hrgnUpdate As Long, ByVal fuRedraw As Long) As Long
  
Private Const GWL_WNDPROC = (-4)                                                                ' Для замены оконной процедуры
Private Const WM_PAINT = &HF                                                                    ' Сообщение отрисовки
Private Const RDW_INVALIDATE = &H1                                                              ' Объявить недействительно область
 
Private Const FrameDimensionTime As String = "{6AEDBD6D-3FB5-418A-83A6-7F45229DC872}"
Private Const PropertyTagFrameDelay = &H5100                                                    ' Идентификатор значения длительности кадров
Private Const PropertyTagLoopCount = &H5101                                                     ' Идентификатор значения количества повторов анимации
 
' Локальные переменные уровня модуля
Dim mHwnd As Long, Init As Boolean, token As Long, img As Long, frames As Long, gr As Long, prevwndproc As Long
Dim tInit As Boolean, frame() As Long, loops As Long, index As Long, cycle As Long, isplay As Boolean
 
' Хендл окна в котором будем рисовать анимацию
Public Property Get hwnd() As Long
    hwnd = mHwnd
End Property
Public Property Let hwnd(ByVal value As Long)
    StopAnim                                                                                    ' Останавливаем анимацию
    If hwnd Then UnHook                                                                         ' Если до этого сабклассили, то отключаем сабклассинг
    mHwnd = value
    Hook                                                                                        ' Сабклассим новое окно
End Property
' Ширина кадра анимации
Public Property Get Width() As Long
    GdipGetImageWidth img, Width
End Property
' Высота кадра анимации
Public Property Get Height() As Long
    GdipGetImageHeight img, Height
End Property
' Текущий кадр
Public Property Get CurrentFrame() As Long
    CurrentFrame = index
End Property
' Количество кадров
Public Property Get FramesCount() As Long
    FramesCount = frames
End Property
' Сколько циклов анимации
Public Property Get LoopCount() As Long
    LoopCount = loops
End Property
' Проигрывается ли анимация
Public Property Get IsPlaying() As Boolean
    IsPlaying = isplay
End Property
' Загрузка файла анимации
Public Function LoadAnimation(ByVal FileName As String) As Boolean
    Dim GpInput As GdiplusStartupInput                                                          ' Для инициализации GDI+
    Dim pc As Long, sz As Long, pi As PropertyItem
    Dim buf() As Byte                                                                           ' Буффер для свойств
    
    If Not Init Then                                                                            ' Если не инициализирован GDI+
        GpInput.GdiplusVersion = 1
        If GdiplusStartup(token, GpInput) Then Exit Function Else Init = True                   ' Инициализируем, при неудаче выходим
    End If
    Clear                                                                                       ' Очистка, если до этого что-то загружали
    If GdipLoadImageFromFile(StrConv(FileName, vbUnicode), img) Then Exit Function              ' Загружаем картинку
    If GdipImageGetFrameCount(img, DEFINE_GUID(FrameDimensionTime), frames) Then                ' Проверяем кол-во кадров
        GdipDisposeImage img                                                                    ' При неудаче удаляем картинку и выходим (возможно что не GIF)
        Exit Function
    End If
    ' Узнаем время каждого кадра
    GdipGetPropertyItemSize img, PropertyTagFrameDelay, sz                                      ' Получаем размер свойства в байтах
    If sz > 0 And frames > 1 Then                                                               ' Имеет смысл только если кадров>1
        ReDim buf(sz - 1)                                                                       ' Выделяем буфер
        GdipGetPropertyItem img, PropertyTagFrameDelay, sz, buf(0)                              ' Копируем свойство в буфер
        CopyMemory pi, buf(0), Len(pi)                                                          ' Копируем в описатель
        ReDim frame(frames - 1)                                                                 ' Выделяем кадровый буфер (длительности)
        CopyMemory frame(0), buf(Len(pi)), pi.Length                                            ' Копируем значения длительностей
    End If
    ' Узнаем зациклена ли анимация
    GdipGetPropertyItemSize img, PropertyTagLoopCount, sz
    If sz > 0 And frames > 1 Then
        ReDim buf(sz - 1)
        GdipGetPropertyItem img, PropertyTagLoopCount, sz, buf(0)
        CopyMemory pi, buf(0), Len(pi)
        GetMem2 buf(Len(pi)), loops
    End If
    index = 0: cycle = 0                                                                        ' Очистка счетчиков
    LoadAnimation = True                                                                        ' Успешно
End Function
' Проигрыш анимации
Public Function PlayAnim() As Boolean
    If Init And hwnd <> 0 And img <> 0 And Not isplay Then
        If frames > 1 Then                                                                      ' Смысл запускать таймер если кадров > 1
            If SetTimer(mHwnd, 1, frame(index) * 10, AddressOf TimerProc) = 0 Then _
                                                    Exit Function                               ' Не удалось запустить таймер
        End If
        tInit = True                                                                            ' Таймер инициализирован
        isplay = True                                                                           ' Включен проигрыш
        PlayAnim = True                                                                         ' Возвращаем успешное значение
        RedrawWindow mHwnd, ByVal 0, 0, RDW_INVALIDATE                                          ' Перерисовываем
    End If
End Function
' Пауза
Public Function Pause() As Boolean
    If isplay Then                                                                              ' Если играем
        isplay = False                                                                          ' то останавливаем
        Pause = True                                                                            ' Возвращаем успешное значение
        StopTimer                                                                               ' Останавливаем таймер
    End If
End Function
' Остановка анимации
Public Sub StopAnim()
    isplay = False                                                                              ' Останавливаем проигрывание
    index = 0                                                                                   ' Обнуляем текущий кадр
    cycle = 0                                                                                   ' Обнуляем счетчик циклов
    StopTimer                                                                                   ' Останавливаем таймер
    RedrawWindow mHwnd, ByVal 0, 0, RDW_INVALIDATE                                              ' Перерисовываем
End Sub
' Завершение работы
Public Sub ShutDown()
    Clear                                                                                       ' Очистка ресурсов
    If mHwnd Then UnHook                                                                        ' Если сабклассили то выключаем сабклассинг
    GdiplusShutdown token                                                                       ' Выключаем GDI+
End Sub
' Очистка ресурсов
Private Sub Clear()
    frames = 0                                                                                  ' Обнуляем количество кадров
    Erase frame()                                                                               ' Удаляем массив длительностей кадров
    If img Then GdipDisposeImage img                                                            ' Удаляем картинку
    StopAnim                                                                                    ' Останавливаем анимацию
End Sub
' Остановка таймера
Private Sub StopTimer()
    If tInit Then                                                                               ' Если таймер инициализирован
        KillTimer mHwnd, 1                                                                      ' Удаляем его
        tInit = False                                                                           ' Таймер не инициализирован
    End If
End Sub
' Из строки в GUID
Private Function DEFINE_GUID(ByVal sGuid As String) As CLSID
    Call CLSIDFromString(StrPtr(sGuid), DEFINE_GUID)                                            ' GUID из строкового параметра
End Function
' Сабклассинг
Private Sub Hook()
    prevwndproc = SetWindowLong(mHwnd, GWL_WNDPROC, AddressOf WndProc)                          ' Назначаем свою оконную процедуру
End Sub
Private Sub UnHook()
    SetWindowLong mHwnd, GWL_WNDPROC, prevwndproc                                               ' Возвращаем оконную процедуру
End Sub
' Оконная процедура
Private Function WndProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Dim ps As PAINTSTRUCT, tdc As Long, tbmp As Long, obmp As Long, rc As RECT
    Select Case Msg
    Case WM_PAINT                                                                               ' Отрисовка
        If index = -1 Or Not Init Then
            WndProc = CallWindowProc(prevwndproc, hwnd, Msg, wParam, lParam)                    ' Если нет активной анимации рисуем как было
        Else
            ' Для предотвращения мерцания, например анимаций с черным фоном, я решилл использовать двойную буфферизацию
            GetClientRect hwnd, rc                                                              ' Узнаем размер ко контрола
            BeginPaint hwnd, ps
            tdc = CreateCompatibleDC(ps.hdc)                                                    ' Буфферный DC
            tbmp = CreateCompatibleBitmap(ps.hdc, rc.iRight, rc.iBottom)                        ' Буфферная картинка
            obmp = SelectObject(tdc, tbmp)
            GdipCreateFromHDC tdc, gr                                                           ' Создаем Graphics
            GdipGraphicsClear gr, &HFFFFFFFF                                                    ' Заливаем белым цветом
            GdipImageSelectActiveFrame img, DEFINE_GUID(FrameDimensionTime), index              ' Выбираем текущий кадр
            GdipDrawImage gr, img, 0, 0                                                         ' Рисуем его
            GdipDeleteGraphics gr                                                               ' Удаляем Graphics
            BitBlt ps.hdc, 0, 0, rc.iRight - rc.iLeft, _
                   rc.iBottom - rc.iTop, tdc, 0, 0, vbSrcCopy                                   ' Отрисовка из буфера
            SelectObject tdc, obmp                                                              ' Восстанавливаем и удаляем ....
            DeleteObject tbmp
            DeleteDC tdc
            EndPaint hwnd, ps
        End If
    Case Else
        WndProc = CallWindowProc(prevwndproc, hwnd, Msg, wParam, lParam)                        ' Остальное нас не интересует
    End Select
End Function
' Процедура таймера
Private Sub TimerProc(ByVal hwnd As Long, ByVal Msg As Long, idEvent As Long, ByVal dwTime As Long)
    index = index + 1                                                                           ' Кадр увеличился
    If index >= frames Then                                                                     ' Если переаолнение кадров
        index = 0                                                                               ' В начало
        cycle = cycle + 1                                                                       ' Увеличиваем циклы
        If cycle > loops And CBool(loops) Then StopAnim: Exit Sub                               ' Если переполнение циклов то выключаем анимацию
    End If
    RedrawWindow mHwnd, ByVal 0, 0, RDW_INVALIDATE                                              ' Перерисовываем
    If SetTimer(mHwnd, 1, frame(index) * 10, AddressOf TimerProc) = 0 Then                      ' Устанавливаем новую задержку
        StopAnim                                                                                ' Не удалось запустить таймер
    End If
End Sub
Форма:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
Private Sub cmdPlay_Click()
    If modGif.IsPlaying Then
        modGif.Pause
        cmdPlay.Caption = "4"                                                                   ' Webdings - символ проигрывания
    Else
        modGif.PlayAnim
        cmdPlay.Caption = ";"                                                                   ' Webdings - символ паузы
    End If
End Sub
Private Sub cmdStop_Click()
    modGif.StopAnim                                                                             ' Остановка анимации
    cmdPlay.Caption = "4"                                                                       ' Webdings - символ проигрывания
End Sub
Private Sub fleFile_Click()
    LoadGif                                                                                     ' Загржаем анимацию
End Sub
Private Sub Form_Load()
    fleFile.Path = App.Path                                                                     ' По умолчанию папка с программой
    fleFile.Pattern = "*.gif"                                                                   ' Фильтр по "гифкам"
    modGif.hwnd = picGif.hwnd                                                                   ' Отрисовываем в PictureBox'е
End Sub
Private Sub LoadGif()
    Dim w As Long, h As Long
    
    If modGif.LoadAnimation(fleFile.Path & "\" & fleFile.FileName) Then
        w = modGif.Width
        h = modGif.Height
        lblInfo.Caption = "Width: " & w & "; Height: " & h & vbNewLine & _
                        "FrameCount: " & modGif.FramesCount & vbNewLine & _
                        "LoopCount: " & format(modGif.LoopCount, "####0;;Inf")
        picGif.Move (picCont.ScaleWidth - w) / 2, _
                    (picCont.ScaleHeight - h) / 2, w, h
        picGif.Visible = True
        If modGif.PlayAnim Then
            cmdPlay.Caption = ";"                                                               ' Webdings - символ паузы
        Else
            cmdPlay.Caption = "4"                                                               ' Webdings - символ проигрывания
        End If
    End If
End Sub
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
    modGif.ShutDown                                                                             ' Не забываем, а то возможен крах!!!
End Sub

P.S. При отладке желательно, останавливать проект закрытием формы, а не кнопкой стоп, иначе может "рухнуть" среда.
Миниатюры
Разбивка GIF на PNG с сохранением альфа канала  
Вложения
Тип файла: rar GifViewer.rar (1.65 Мб, 226 просмотров)
5
 Аватар для fireday
307 / 138 / 6
Регистрация: 17.04.2013
Сообщений: 1,943
16.11.2013, 09:41  [ТС]
The trick, сложный код, даже с комментариями не догоняю
Спасибо, буду разбираться
0
Модератор
Эксперт .NET
 Аватар для Yury Komar
4359 / 3429 / 512
Регистрация: 27.01.2014
Сообщений: 6,258
21.02.2014, 22:08
The Trick - красавчик... То что надо )) а то надоело анимировать картинки, лишний загруз для приложения
1
 Аватар для Антихакер32
1201 / 473 / 46
Регистрация: 06.01.2014
Сообщений: 1,797
Записей в блоге: 19
22.02.2014, 05:46
The Trick, а я всю тему оценил на отлично, оссобенно этот пост, до недавнего времени, гифками я особо не интерисовался
и в своих программах не ставил, а теперь осознал, как это может быть эффективно !
0
 Аватар для Pro_grammer
6807 / 2839 / 527
Регистрация: 24.04.2011
Сообщений: 5,308
Записей в блоге: 10
22.02.2014, 08:02
Показывать готовую анимацию - идея не нова и реализована с десяток раз. Я вот ни разу на VB6 не встречал решение обратной задачи - из PNG собрать анимацию GIF. Обычный GIF при помощи GDI+сохранить можно, а вот анимацию из нескольких кадров как сделать, кто знает?
0
Модератор
10057 / 3902 / 884
Регистрация: 22.02.2013
Сообщений: 5,853
Записей в блоге: 79
22.02.2014, 13:40
Цитата Сообщение от Pro_grammer Посмотреть сообщение
Показывать готовую анимацию - идея не нова и реализована с десяток раз. Я вот ни разу на VB6 не встречал решение обратной задачи - из PNG собрать анимацию GIF. Обычный GIF при помощи GDI+сохранить можно, а вот анимацию из нескольких кадров как сделать, кто знает?
Это делается почти также, если ты знаешь работу с GDI+ или System.Drawing из .NET. Позже выложу пример.
0
 Аватар для Pro_grammer
6807 / 2839 / 527
Регистрация: 24.04.2011
Сообщений: 5,308
Записей в блоге: 10
22.02.2014, 14:30
Цитата Сообщение от The trick Посмотреть сообщение
System.Drawing из .NET.
Это не интересует
Цитата Сообщение от The trick Посмотреть сообщение
работу с GDI+
А вот это было бы интересно посмотреть именно в контексте создания анимационного GIF.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
22.02.2014, 14:30
Помогаю со студенческими работами здесь

Совместить изображения с соблюдением Альфа канала
Как совместить изображения соблюдая альфа канал???

Иконки разделов без альфа канала
и так собственно сабж, 2gif изображения без альфа канала http://cyberstatic.net/images/statusicon/subforum_new.gif ...

полупрозрачный куб (альфа канала в вершинах)
Здравствуйте! Хотел создать куб на плоскости, при этом чтобы куб был полупрозрачным. Куб с плоскостью делал на основе урока книжки...

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

Баг с цветом при настройке альфа-канала
Здравствуйте. Столкнулся с такой проблемой. Написал простой шейдер для света и задал такие настройки для альфа-канала: ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Жизнь в неопределённости
kumehtar 23.03.2026
Жизнь — это постоянное существование в неопределённости. Например, даже если у тебя есть список дел, невозможно дойти до точки, где всё окончательно завершено и больше ничего не осталось. В принципе,. . .
Модель здравоСохранения: работники работают быстрее после её введения.
anaschu 23.03.2026
geJalZw1fLo Корпорация до введения программа здравоохранения имела много невыполненных работниками заданий, после введения программы количество заданий выросло. Но на выплатах по больничным это. . .
1С: Контроль уникальности заводского номера
Maks 23.03.2026
Алгоритм контроля уникальности заводского (или серийного) номера на примере документа выдачи шин для спецтехники с табличной частью. Данные берутся из регистра сведений, по которому настроено. . .
Хочу заставить корпорации вкладываться в здоровье сотрудников: делаю мат модель здравосохранения
anaschu 22.03.2026
e7EYtONaj8Y Z4Tv2zpXVVo https:/ / github. com/ shumilovas/ med2. git
1С: Программный отбор элементов справочника по группе
Maks 22.03.2026
Установка программного отбора элементов справочника "Номенклатура" из модуля формы документа. В качестве фильтра для отбора справочника служит группа номенклатуры. Отбор по наименованию группы. . .
Как я обхитрил таблицу Word
Alexander-7 21.03.2026
Когда мигает курсор у внешнего края таблицы, и нам надо перейти на новую строку, а при нажатии Enter создается новый ряд таблицы с ячейками, то мы вместо нервных нажатий Энтеров мы пишем любые буквы. . .
Krabik - рыболовный бот для WoW 3.3.5a
AmbA 21.03.2026
без регистрации и смс. Это не торговля, приложение не содержит рекламы. Выполняет свою непосредственную задачу - автоматизацию рыбалки в WoW - и ничего более. Однако если админы будут против -. . .
1С: Программный отбор элементов справочника по значению перечисления
Maks 21.03.2026
Установка программного отбора элементов справочника "Сотрудники" из модуля формы документа. В качестве фильтра для отбора служит значение перечислений. / / Событие "НачалоВыбора" реквизита на форме. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru