A.M. Hoornweg 153 Posted June 19 Hello all, I have a 32-bit Windows application (it is an Intraweb based ISAPI dll) and I try to write images in losslessly compressed webp format. The bitmap that I want to convert to webp is a 32-bit tBitmap containing some 2-D graphics. My problem: The generated output image is totally broken when I use Delphi 12's SKIA routines for the conversion. Graphics programs render it only partially, then give up. This is the code that I wrote; The compression factor that I pass is 100. Did I do anything wrong? ... uses system.skia, vcl.skia; procedure SaveAsWebP(aBitmap: tbitmap; aOutputfilename: string; Compressionfactor: integer;Out MimeContentType:String); begin var skimage:=aBitmap.ToSKImage; skimage.encodetofile(aOutputfilename, tskEncodedImageFormat.WebP, compressionfactor); MimeContentType:='image/webp'; end ; broken_webpfile.webp Share this post Link to post
Anders Melander 2015 Posted June 19 1 hour ago, A.M. Hoornweg said: The generated output image is totally broken FWIW, this is what it looks like in Firefox, so not totally broken: Share this post Link to post
A.M. Hoornweg 153 Posted June 19 I have a workaround that works: procedure SaveAsWebP(aBitmap: tbitmap; aOutputfilename: string; Compressionfactor: integer; out MimeContentType: string); var lStream: tMemorystream; skimage: iSkImage; begin lStream := tMemorystream.Create; try aBitmap.SaveToStream(lStream); lStream.Position := 0; skimage := tskimage.MakeFromEncodedStream(lStream); skimage.encodetofile(aOutputfilename, tskEncodedImageFormat.WebP, Compressionfactor); MimeContentType := 'image/webp'; finally lStream.Free; end; end; So it appears that it is really the following code that is broken: var skimage:=aBitmap.ToSKImage; Share this post Link to post
Kas Ob. 142 Posted June 19 Open your file in browser and clearly something went wrong and this foggy text is definitely AlphaChannel problem, i copied it by clicking copy the image then pasted it in our faithful Windows Paint, the copy is done by the browser itself (the one showing foggy image), and here is the result confirming my doubts It is AlphaChennel multiplexed (premultiplied) in wrong way. See VP8L which is the one responsible for lossless WebP encoding does support AlphaChennel in limited way, not sure i do recall reading a lot about this, but i remember that it is supported in specific modes and color space. In all cases make sure you are encoding an image without Alpha or make sure to request Alpha dropping, ( don't know if there is setting for the encoder itself though), but if your image originally didn't have AlphaChannel then you should not have a problem, if there is alpha then and want to stick to 32bit images then overwrite the AlphaChannel to opaque. Share this post Link to post
A.M. Hoornweg 153 Posted June 19 16 minutes ago, Kas Ob. said: It is AlphaChennel multiplexed (premultiplied) in wrong way. See VP8L which is the one responsible for lossless WebP encoding does support AlphaChennel in limited way, not sure i do recall reading a lot about this, but i remember that it is supported in specific modes and color space. In all cases make sure you are encoding an image without Alpha or make sure to request Alpha dropping, ( don't know if there is setting for the encoder itself though), but if your image originally didn't have AlphaChannel then you should not have a problem, if there is alpha then and want to stick to 32bit images then overwrite the AlphaChannel to opaque. The bitmap is created like this, the 32-bits is just for alignment (speed) reasons: ResultBitmap := tbitmap.Create; ResultBitmap.pixelformat := pf32bit; ResultBitmap.Alphaformat := TAlphaFormat.afIgnored; and function TSkBitmapHelper.ToSkImage (found in Unit vcl.skia) explicitly handles that 32bit/afIgnored case, so there's probably a bug there somewhere: if PixelFormat = TPixelFormat.pf32bit then begin case AlphaFormat of TAlphaFormat.afIgnored: LAlphaType := TSkAlphaType.Opaque; TAlphaFormat.afDefined: LAlphaType := TSkAlphaType.Unpremul; TAlphaFormat.afPremultiplied: LAlphaType := TSkAlphaType.Premul; else LAlphaType := TSkAlphaType.Unknown; end; ...... Saving the tBitmap to a stream and then creating the tSkImage from that stream works, but this still seems a bug to me. Share this post Link to post
Kas Ob. 142 Posted June 19 I never used Skia for images like that, so i can provide zero help with that (i mean code) But to emphasize what o wrote above, the generated WebP you attached is high quality mask of the image you need, is it a bug ? i don't think so, Skia can't have bugs like that, Skia is tested and vetted enough, is the Delphi/Pascal Helper wrong ?, i can't say. What i am saying is just drop all Alpha operation if you performing any, and make sure it is not Premultiplied, switch to ignore or Opaque as they appear, also it could be a simple default value somewhere, something to do with most frequent operation for WebP which is SVG handling, and SVG by design is transparent by default. Share this post Link to post
Anders Melander 2015 Posted June 19 I'm pretty sure Skia's BMP handling isn't bug-free but it's way more likely that this problem is caused by the Delphi side of things; The alpha handling in VCL's TBitmap is such a horrible mess that it should be deprecated and reimplemented from scratch. See also: Share this post Link to post