About Monkey 2 › Forums › Monkey 2 Programming Help › Some notes about Pixmap
Tagged: pixmap
This topic contains 7 replies, has 5 voices, and was last updated by
Gwenel
5 months, 2 weeks ago.
-
AuthorPosts
-
December 4, 2017 at 8:10 am #12101
Working on ImageTrimmer app I found one interesting thing:
If you use pixmap with PremultiplyAlpha=True – when loading or after making some changes with pixels, then save pixmap – and you get pixels artefacts in saved version!
I wanted to save on extra loading of pixmap and my steps were:
- Load pixmap with premultiply alpha
- Create image using our pixmap
- Processing pixmap pixels
- Save pixmap into file
- (I load and save PNG format)
Then I load just saved image and see artefacts in semi-transparent pixels.
Solution is:
To load an extra pixmap for processing without premultiply alpha.
See the GIF with artefacts – bordered version is wrong (don’t pay attention on red cross).
And see on the second image with sky blue background (I can’t remove incorrect attached file).
Attachments:
December 4, 2017 at 12:05 pm #12108I’ve had problems saving the pixmap to png too. I think it uses some png compression by default thus artifacts. It’s probably just a flag under the hood though.
December 4, 2017 at 12:58 pm #12111@abakobo try to just resave pixmap without touching pixelFormat and alpha:
Monkey12Local pix:=Pixmap.Load( srcPath ) 'format=none, calcAlpha=falsepix.Save( destPath )it is an artefacts-free for me.
December 4, 2017 at 7:57 pm #12112I think it uses some png compression by default thus artifacts.
PNG uses loseless compression – if there are artifacts it’s a bug (possibly mine or STBs).
December 5, 2017 at 3:49 am #12127mojo.Image uses Pixmap with premultiplied alpha.
If you’ll save such pixmap then you’ll get artifacts on next loading image – alpha will be premultiplied twice here.
I think this is the reason.
PNG loader itself works well.
December 5, 2017 at 4:24 am #12128According to the spec https://www.w3.org/TR/PNG-Rationale.html PNG should not contain premultiplied alpha pixels. Is it likely the SavePNG function needs to un-premultiply pixel data before saving?
December 5, 2017 at 4:31 pm #12146Can’t reproduce the artifacts I had at a time. All working good now! (not using alpha)
November 1, 2018 at 2:57 pm #15554You can unpremultiply before saving. This is a test using the basic pixellformat (RGBA8 which I think that’s Monkey2’s default format).
Sorry if it is a bit more lengthy than it needs to be at the moment.
Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124#Import "<std>"#Import "<mojo>"#Import "<sdl2>"#import "<openal>"Using std..Using mojo..Using sdl2..Const w:=800, h:=600Function Main()New AppInstanceNew Myapp(w,h)App.Run()End' improve png sizeClass Myapp Extends WindowField counter:Int = 1Field pixmap:PixmapField image:ImageMethod New( title:String="Myapp",width:Int=w,height:Int=h,flags:WindowFlags=WindowFlags.Resizable )Super.New(title,w,h,flags)App.FileDropped+=Lambda(path:String)Print pathpixmap = pixmap.Load(path,,False)If path.Slice(path.Length-4).ToLower()=".png"counter = counter + 1path = path.Slice(0,path.Length-4) + counter + ".png"Print pathEndif' A manual premultyplying routine.' If you don't wannat use the Premultiply flag in Pixmap.Load or pixmap.PremultiplyAlpha().Local p:=Cast<UInt Ptr>(pixmap.Data)Local w:Int = pixmap.WidthLocal x:Int,y:IntFor y=0 Until hFor x=0 Until w' Read the red, green, blue, and alpha from the pixmapLocal r:UInt = (p[y*w+x] & $ff)Local g:UInt = (p[y*w+x] Shr 8 & $ff)Local b:UInt = (p[y*w+x] Shr 16 & $ff)Local a:UInt = (p[y*w+x] Shr 24 & $ff)' The magicLocal rf:Float = r / 255.0Local gf:Float = g / 255.0Local bf:Float = b / 255.0Local af:Float = a / 255.0rf=rf*af ; gf=gf*af ; bf=bf*af' Now combine everything back into the pixmapr=UInt(rf*255.0)g=UInt(gf*255.0)b=UInt(bf*255.0)a=UInt(af*255.0)Local mixed:UInt = a Shl 24mixed=mixed + (b Shl 16)mixed=mixed + (g Shl 8)mixed=mixed + rp[y*w+x] = mixedNextNext' ----------------------------------------------------------------------------------------------------------------------------image = New Image(pixmap)Local savecanvas := New Canvas(image)Local savepixmap := savecanvas.CopyPixmap(savecanvas.Viewport)' Demultiply before savingp=Cast<UInt Ptr>(savepixmap.Data)w = savepixmap.WidthFor y=0 Until hFor x=0 Until w' Read the red, green, blue, and alpha from the pixmapLocal r:UInt = (p[y*w+x] & $ff)Local g:UInt = (p[y*w+x] Shr 8 & $ff)Local b:UInt = (p[y*w+x] Shr 16 & $ff)Local a:UInt = (p[y*w+x] Shr 24 & $ff)' The magicLocal rf:Float = r / 255.0Local gf:Float = g / 255.0Local bf:Float = b / 255.0Local af:Float = a / 255.0If af>0 Then rf=rf/af ; gf=gf/af ; bf=bf/af' Combine everything into the pixmapr=UInt(rf*255.0)g=UInt(gf*255.0)b=UInt(bf*255.0)a=UInt(af*255.0)Local mixed:UInt = a Shl 24mixed=mixed + (b Shl 16)mixed=mixed + (g Shl 8)mixed=mixed + rp[y*w+x] = mixedNextNextsavepixmap.Save(path+"")EndEndMethod OnRender(canvas:Canvas) OverrideApp.RequestRender()canvas.TextureFilteringEnabled = FalseIf imagecanvas.Color = Color.Bluecanvas.DrawOval(200,200,100,100)canvas.Color = Color.Whitecanvas.DrawImage(image,0,0)canvas.DrawImage(image,100,100)EndifEndEnd -
AuthorPosts
You must be logged in to reply to this topic.

