Этот формат картинок мне встречается очень давно, поэтому я решил разобраться с ним. Нашел примеры и долго искал libwebp.dll, на сайте попадаются только x64. Начал читать о формате и написал программу, которая выводит список порций(chunks):
f$="comment_temp5.webp"
;f$="meme-simpsons-google.webp"
;f$="tumblr_dfa085bb1a513f4508d05430d2e06d8a_2b18d8d2_540.webp"
If ReadFile(0,f$)
s1.a=ReadAsciiCharacter(0)
s2.a=ReadAsciiCharacter(0)
s3.a=ReadAsciiCharacter(0)
s4.a=ReadAsciiCharacter(0)
If s1=$52 And s2=$49 And s3=$46 And s4=$46
fs.l=ReadLong(0)
Debug "size="+Str(fs+8)
s1.a=ReadAsciiCharacter(0)
s2.a=ReadAsciiCharacter(0)
s3.a=ReadAsciiCharacter(0)
s4.a=ReadAsciiCharacter(0)
If s1=$57 And s2=$45 And s3=$42 And s4=$50
While Not Eof(0)
c$=""
For i=1 To 4
c$=c$+Chr(ReadAsciiCharacter(0))
Next i
cs.l=ReadLong(0)
Debug c$+"("+Str(cs)+")"
FileSeek(0,cs,#PB_Relative)
Wend
Else
MessageRequester("WebP","Not WebP")
EndIf
Else
MessageRequester("WebP","Not RIFF")
EndIf
CloseFile(0)
Else
MessageRequester("WebP","Error read "+f$)
EndIf
;f$="meme-simpsons-google.webp"
;f$="tumblr_dfa085bb1a513f4508d05430d2e06d8a_2b18d8d2_540.webp"
If ReadFile(0,f$)
s1.a=ReadAsciiCharacter(0)
s2.a=ReadAsciiCharacter(0)
s3.a=ReadAsciiCharacter(0)
s4.a=ReadAsciiCharacter(0)
If s1=$52 And s2=$49 And s3=$46 And s4=$46
fs.l=ReadLong(0)
Debug "size="+Str(fs+8)
s1.a=ReadAsciiCharacter(0)
s2.a=ReadAsciiCharacter(0)
s3.a=ReadAsciiCharacter(0)
s4.a=ReadAsciiCharacter(0)
If s1=$57 And s2=$45 And s3=$42 And s4=$50
While Not Eof(0)
c$=""
For i=1 To 4
c$=c$+Chr(ReadAsciiCharacter(0))
Next i
cs.l=ReadLong(0)
Debug c$+"("+Str(cs)+")"
FileSeek(0,cs,#PB_Relative)
Wend
Else
MessageRequester("WebP","Not WebP")
EndIf
Else
MessageRequester("WebP","Not RIFF")
EndIf
CloseFile(0)
Else
MessageRequester("WebP","Error read "+f$)
EndIf
Выходит, что это всего лишь RIFF со специальными порциями. Для файла omment_temp5.webp вышло:
size=80040
VP8X(10)
VP8 (76838)
EXIF(86)
XMP (3062)
VP8X(10)
VP8 (76838)
EXIF(86)
XMP (3062)
EXIF я еще не осилил, поэтому и не стал разбирать по частям.
На форуме MASM32 нашлись еще два примерчика:
UsePNGImageEncoder()
Prototype.i WebPGetInfo(*webp_data, data_size.i, *width, *height)
Prototype.i WebPDecodeRGBAInto(*webp_data, data_size.i, *output_buffer, output_buffer_size.i, output_stride.i)
Prototype.i WebPDecodeBGRAInto(*webp_data, data_size.i, *output_buffer, output_buffer_size.i, output_stride.i)
Global WebPGetInfo.WebPGetInfo
Global WebPDecodeRGBAInto.WebPDecodeRGBAInto
Global WebPDecodeBGRAInto.WebPDecodeBGRAInto
If OpenLibrary(0, "libwebp.dll")
WebPGetInfo.WebPGetInfo = GetFunction(0, "WebPGetInfo")
WebPDecodeRGBAInto.WebPDecodeRGBAInto= GetFunction(0, "WebPDecodeRGBAInto")
WebPDecodeBGRAInto.WebPDecodeBGRAInto = GetFunction(0, "WebPDecodeBGRAInto")
f$="comment_temp5.webp"
fs=FileSize(f$)
*m=AllocateMemory(fs)
If *m
If ReadFile(0,f$)
ReadData(0,*m,fs)
CloseFile(0)
WebPGetInfo(*m, fs, @dWidth, @dHeight)
CreateImage(0, dWidth, dHeight, 32)
StartDrawing(ImageOutput(0))
Pitch = DrawingBufferPitch()
Format = DrawingBufferPixelFormat()
Buffer = DrawingBuffer()
rr=WebPDecodeBGRAInto(*m, fs, Buffer, Pitch * dHeight, Pitch)
;flip orisontal
For y=0 To dHeight>>1
For x=0 To dWidth-1
p1=PeekL( Buffer+4*(x+y*dWidth) );Point(x,y)
p2=PeekL( Buffer+4*(x+(dHeight-1-y)*dWidth) );Point(x,dHeight-1-y)
PokeL(Buffer+4*(x+(dHeight-1-y)*dWidth),p1);Box(x,y,1,1,p2)
PokeL( Buffer+4*(x+y*dWidth),p2 );Box(x,dHeight-1-y,1,1,p1)
Next x
Next y
StopDrawing()
SaveImage(0,"hh.png",#PB_ImagePlugin_PNG)
Else
Debug "Read error:"+f$
EndIf
FreeMemory(*m)
Else
Debug "memory error:"+Str(fs)
EndIf
Else
MessageRequester("load DLL","Error")
EndIf
С декодированием файла вышел один косяк - картинка вышла вверх ногами, поэтому был написан индусский код, и позже исправлен. С созданием картинки вышла заморочка, поэтому я немного исправил найденный пример:
Prototype.i WebPGetEncoderVersion()
Prototype.i WebPFree(*p)
Prototype.i WebPEncodeRGBA(*gba, width, height, stride, quality_factor.f, *output);stride corresponds to the number of bytes needed to jump from one row to the next
If OpenLibrary(0, "libwebp.dll")
WebPGetEncoderVersion.WebPGetEncoderVersion = GetFunction(0, "WebPGetEncoderVersion")
WebPFree.WebPFree = GetFunction(0, "WebPFree")
WebPEncodeRGBA.WebPEncodeRGBA = GetFunction(0, "WebPEncodeRGBA")
;Debug Hex(WebPGetEncoderVersion())
*c=AllocateMemory(80004)
For y=0 To 99
For x=0 To 99
cc.a=x!y
PokeA(*c+y*400+x*4+3,255);alpha
PokeA(*c+y*400+x*4+1,x-y);green
PokeA(*c+y*400+x*4+2,y);blue
PokeA(*c+y*400+x*4,x);red
Next x
Next y
;ShowMemoryViewer(*c,1024)
;stride = ((((biWidth * biBitCount) + 31) & ~31) >> 3)
fl=WebPEncodeRGBA(*c, 100, 100, 400, 80.0, @webp_data)
;?var stride = (width * colorImageFrame.Format.BitsPerPixel + 7) / 8;
;ShowMemoryViewer(webp_data,fl)
If CreateFile(0,"huemae.webp")
WriteData(0,webp_data,fl)
Else
MessageRequester("Write file","Error")
EndIf
FreeMemory(*c)
WebPFree(webp_data)
CloseLibrary(0)
Else
MessageRequester("load DLL","Error")
EndIf
Косяк заключался в параметре stride для функции - это число байт, необходимых для перехода по линиям данных. В примере был 80, но правильнее будет 400.
Мне, как всегда, показалось мало, и я решил скомпилировать новую версию 1.5.0. На сайте есть описание, поэтому я скачал и установил VS 2013. Самое гнусное занятие - это компиляция.
Ярлык командной строки нашел тут: c:\Program Files\Microsoft Visual Studio 12.0\Common7\Tools\Shortcuts\
Потом набрал
d:
cd libwebp-1.5.0
nmake /f Makefile.vc CFG=release-static RTLIBCFG=static OBJDIR=output UNICODE=1
Часть предложенных опций не скомпилировалась, нужно разбираться с конфигурацией. Статичные библиотеки скомпилировались. но PureBasic заистерил при компиляции- Unresolved external.
В архиве есть картинки, исходники и пара версий библиотек. Хорошо бы разобраться с анимацией и прозрачностью.
Комментарии
Отправить комментарий