Perhaps relevant : there may be a big memory leak using DockItem? See <https://xojo.com/issue/17605>
BTW this is the standard way if you want to work with xojo picture object under MacOSX. You should keep this in mind if you
want to use filters and other fancy OSX stuff which opens doors…
[quote=202085:@Michael Diehr]Sam, thanks - it turns out in this case, it does work.
So here’s the latest version, which runs in 6 msec (which is about 230x as fast as the original code which took 1400+ msec):
Usual caveats apply : this is untested and may blow up your system, etc.
[code]
Protected Function GetDockImageFast4() As Picture
// Fastest way yet to convert App.DockItem.Graphics into a Xojo Picture
// as discussed https://forum.xojo.com/24237-why-no-simple-way-to-copy-a-graphics-object-into-another
// This version of code inspired by https://forum.xojo.com/9403-scale-quality-of-canvas-control/p5#p195272
//
// Note: needs a NSRect (or CGRect) structure (they are identical) which is defined as
// struct NSRect { x as single, y as single, width as single, height as single }
// Get the graphics of the picture as CGContext
dim g as graphics = app.dockItem.Graphics
dim w,h as integer
w = g.width
h = g.height
// make a new empty picture
dim pic as new Picture(w,h)
// get the CGContext from the dockItem
dim cntx as Ptr = ptr(g.Handle(Graphics.HandleTypeCGContextRef))
// sometimes you can get an image from a CGContext
Declare Function CGBitmapContextCreateImage Lib “CoreGraphics” (context as Ptr) As Ptr
Declare sub CGContextDrawImage lib “Cocoa” (cntxt As Ptr, r As NSRect, img As Ptr)
dim pSrc as ptr = CGBitmapContextCreateImage(cntx)
dim pDst as ptr = Ptr( pic.graphics.handle(Graphics.HandleTypeCGContextRef) )
// draw source into dest
dim r as NSRect
r.width = w
r.height = h
CGContextDrawImage(pDst,r,pSrc)
Return pic
End Function
[/code][/quote]
So from what I understand reading this, it should work for any graphic, right ? Not only DockIcon ?
No. It’ll only work for certain kinds of Graphics objects and the only place where the Xojo framework makes a guarantee of returning a bitmap graphics context is from a Picture’s Graphics’ handle.
[quote=202085:@Michael Diehr]Sam, thanks - it turns out in this case, it does work.
So here’s the latest version, which runs in 6 msec (which is about 230x as fast as the original code which took 1400+ msec):
Usual caveats apply : this is untested and may blow up your system, etc.
[code]
Protected Function GetDockImageFast4() As Picture
// Fastest way yet to convert App.DockItem.Graphics into a Xojo Picture
// as discussed https://forum.xojo.com/24237-why-no-simple-way-to-copy-a-graphics-object-into-another
// This version of code inspired by https://forum.xojo.com/9403-scale-quality-of-canvas-control/p5#p195272
//
// Note: needs a NSRect (or CGRect) structure (they are identical) which is defined as
// struct NSRect { x as single, y as single, width as single, height as single }
// Get the graphics of the picture as CGContext
dim g as graphics = app.dockItem.Graphics
dim w,h as integer
w = g.width
h = g.height
// make a new empty picture
dim pic as new Picture(w,h)
// get the CGContext from the dockItem
dim cntx as Ptr = ptr(g.Handle(Graphics.HandleTypeCGContextRef))
// sometimes you can get an image from a CGContext
Declare Function CGBitmapContextCreateImage Lib “CoreGraphics” (context as Ptr) As Ptr
Declare sub CGContextDrawImage lib “Cocoa” (cntxt As Ptr, r As NSRect, img As Ptr)
dim pSrc as ptr = CGBitmapContextCreateImage(cntx)
dim pDst as ptr = Ptr( pic.graphics.handle(Graphics.HandleTypeCGContextRef) )
// draw source into dest
dim r as NSRect
r.width = w
r.height = h
CGContextDrawImage(pDst,r,pSrc)
Return pic
End Function
[/code][/quote]
This code at the very least needs to check for getting Nil back from CGBitmapContextCreateImage. It also leaks memory because it’s missing a CFRelease at the end of the CGImage.
Indeed and that’s my bad! I forgot to mention that CGBitmapContextCreateImage requires a release of the image once you’ve finished with it, otherwise it leaks.
[code] CGContextDrawImage(pDst,r,pSrc)
declare sub CGImageRelease lib “CoreGraphics” ( CGImageRef as Ptr )
CGImageRelease( pSrc )
Return pic
End Function[/code]
Thanks Sam & Joe : here’s a slightly less dangerous version with those changes and some additional error-checking:
Protected Function GetDockImageFast5() As Picture
// Fastest way yet to convert App.DockItem.Graphics into a Xojo Picture
// as discussed https://forum.xojo.com/24237-why-no-simple-way-to-copy-a-graphics-object-into-another
// This version of code inspired by https://forum.xojo.com/9403-scale-quality-of-canvas-control/p5#p195272
// Note: needs a NSRect (or CGRect) structure (they are identical) which is defined as
// struct NSRect { x as single, y as single, width as single, height as single }
// Get the graphics of the picture as CGContext
dim g as graphics = app.dockItem.Graphics
if g = nil then
return nil
end if
dim w,h as integer
w = g.width
h = g.height
// make a new empty picture
dim pic as new Picture(w,h)
if pic = nil then
return nil
end if
// get the CGContext from the dockItem
dim cntx as Ptr = ptr(g.Handle(Graphics.HandleTypeCGContextRef))
if cntx = nil then
return nil
end if
// sometimes you can get an image from a CGContext
Declare Function CGBitmapContextCreateImage Lib "CoreGraphics" (context as Ptr) As Ptr
Declare sub CGContextDrawImage lib "Cocoa" (cntxt As Ptr, r As NSRect, img As Ptr)
dim pSrc as ptr = CGBitmapContextCreateImage(cntx)
if pSrc = nil then
return Nil
end if
dim pDst as ptr = Ptr( pic.graphics.handle(Graphics.HandleTypeCGContextRef) )
if pDst = nil then
return Nil
end if
// draw source into dest
dim r as NSRect
r.width = w
r.height = h
CGContextDrawImage(pDst,r,pSrc)
// clean up after ourself
Declare sub CGImageRelease lib "CoreGraphics" ( CGImageRef as Ptr )
CGImageRelease( pSrc )
Return pic
End Function