Re: [Haskell-cafe] Drawing an existing image into a cairo surface?
Excerpts from Rafal Kolanski's message of Sun Sep 21 07:28:37 -0500 2008: The best I can find is withImageSurfaceFromPNG, but I can't make it work. Why not? Seems to me all you need to do is: withImageSurfaceFromPNG blah.png $ \surface - do ... Lots of code is written this way (create a resource, pass it to a function and then release it after the function is over.) I tried playing around with unsafePerformIO but that just gets me into: Without further context as to what you are doing, I really see no reason why you would have to use unsafePerformIO at all. Austin ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Drawing an existing image into a cairo surface?
Austin Seipp wrote: Excerpts from Rafal Kolanski's message of Sun Sep 21 07:28:37 -0500 2008: The best I can find is withImageSurfaceFromPNG, but I can't make it work. Why not? Seems to me all you need to do is: withImageSurfaceFromPNG blah.png $ \surface - do ... Lots of code is written this way (create a resource, pass it to a function and then release it after the function is over.) Well, but withImageSurfaceFromPNG only lets you work within that scope and wipes out the surface straight afterwards ... I tried playing around with unsafePerformIO but that just gets me into: Without further context as to what you are doing, I really see no reason why you would have to use unsafePerformIO at all. The context is, I want to render a multi-page PDF with a variety of things on it, so I have something like (very simplified): main :: IO () main = do withPDFSurface outputFile pdfWidth pdfHeight renderer renderer s = renderWith s renderPresentation renderPresentation = do myDraw1 showPage myDraw2 showPage myDraw1 = do setSourceRGB 1 0 0 setLineWidth 1 moveTo 0 0 lineTo 100 100 stroke so renderPresentation will have type Render () Now lets say I want to draw an image on page 2, that will only appear on page 2 ... with one image, your technique makes sense to me, but with multiple images on multiple pages, I don't understand how to make it scale. Perhaps this code is very naive, but I'm kinda new to the pure world of Haskell. Sincerely, Rafal Kolanski. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Drawing an existing image into a cairo surface?
I finally came up with a solution that suits my context. For those interested, I'm supplying it here. Safely get a surface containing your .png image (note that the surface has to be freed when you're done with it using surfaceFinish) imageSurfaceCreateFromPNG :: FilePath - IO Surface imageSurfaceCreateFromPNG file = withImageSurfaceFromPNG file $ \png - do w - renderWith png $ imageSurfaceGetWidth png h - renderWith png $ imageSurfaceGetHeight png surf - createImageSurface FormatRGB24 w h renderWith surf $ do setSourceSurface png 0 0 paint return surf Now the unsafe part (hack until I have an associative list storing my images to pull into relevant pages for rendering): unsafeLoadPNG file = unsafePerformIO $ imageSurfaceCreateFromPNG file This allows drawing an image directly in a Render () context: paintImage :: FilePath - Double - Double - Render () paintImage file x y = do surf - return $ unsafeLoadPNG file setSourceSurface surf x y paint Looking at this irc log from 2005: http://www.cse.unsw.edu.au/~dons/code/irc-logs/05.11.20 someone's had this problem before, and although they did not show their solution, I think it might've been similar to mine. Hope this helps the next person to get stuck. Sincerely, Rafal Kolanski. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re[2]: [Haskell-cafe] Drawing an existing image into a cairo surface?
Hello Rafal, Sunday, September 21, 2008, 5:43:14 PM, you wrote: withImageSurfaceFromPNG file $ \png - do w - renderWith png $ imageSurfaceGetWidth png h - renderWith png $ imageSurfaceGetHeight png this is very idiomatic Haskell, consider it as a sort of RAII. you may even omit additional tab here: withImageSurfaceFromPNG file $ \png - do w - renderWith png $ imageSurfaceGetWidth png h - renderWith png $ imageSurfaceGetHeight png ... afair, Render is a super-IO monad so you can just lift any IO operation to Render: x - liftIO$ imageSurfaceCreateFromPNG file -- Best regards, Bulatmailto:[EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Drawing an existing image into a cairo surface?
Bulat Ziganshin wrote: afair, Render is a super-IO monad so you can just lift any IO operation to Render: x - liftIO$ imageSurfaceCreateFromPNG file You are indeed correct. I feel really silly now, using unsafePerformIO in the IO monad. D'oh! Thank you very much! Rafal Kolanski. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Drawing an existing image into a cairo surface?
Sorry. In a hurry, and I don't have a lot of time to read the message, so if I'm offering a lot of info you already have, I apologize. The best thing to do is to allocate either a pixmap or Gtk.DrawingArea -- you can then use widgetGetDrawable to get the drawing context from it and newGC to take drawing context and get a graphics context. After you have a drawing and graphics context, you can use drawPixbuf to draw or update any image you want, then use the same DrawngArea for Cairo after you've drawing the image. If you need more help with it, let me know, and I can send some code that will do it later today. -- Jeff On Sun, Sep 21, 2008 at 10:09 AM, Rafal Kolanski [EMAIL PROTECTED] wrote: Bulat Ziganshin wrote: afair, Render is a super-IO monad so you can just lift any IO operation to Render: x - liftIO$ imageSurfaceCreateFromPNG file You are indeed correct. I feel really silly now, using unsafePerformIO in the IO monad. D'oh! Thank you very much! Rafal Kolanski. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- I try to take things like a crow; war and chaos don't always ruin a picnic, they just mean you have to be careful what you swallow. -- Jessica Edwards ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Drawing an existing image into a cairo surface?
Jefferson Heard wrote: Sorry. In a hurry, and I don't have a lot of time to read the message, so if I'm offering a lot of info you already have, I apologize. The best thing to do is to allocate either a pixmap or Gtk.DrawingArea -- you can then use widgetGetDrawable to get the drawing context from it and newGC to take drawing context and get a graphics context. After you have a drawing and graphics context, you can use drawPixbuf to draw or update any image you want, then use the same DrawngArea for Cairo after you've drawing the image. If you need more help with it, let me know, and I can send some code that will do it later today. I'd be very much interested, as I also want to load SVG files and my version of Gtk2Hs (Ubuntu Hardy) doesn't have Graphics.Rendering.Cairo.SVG ... Your method can get around this problem I think. Sincerely, Rafal Kolanski. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe