Re: [NSBitmapImageRep getBitmapDataPlanes] copying data?
Re: [NSBitmapImageRep getBitmapDataPlanes] copying data?
- Subject: Re: [NSBitmapImageRep getBitmapDataPlanes] copying data?
- From: Jonathan Taylor <email@hidden>
- Date: Tue, 22 Feb 2011 10:49:09 +0000
On 21 Feb 2011, at 23:49, Ken Thomases wrote:
> What makes you think the data copy is "extra"?
>
> If you read that AppKit release note, you'll see that NSImage may not be decoding the file contents right off the bat. For example, it mentions that "[i]f you initialize a NSImage from a JPEG file, then draw it in a PDF, you should get a PDF of the same file size as the original JPEG". In other words, NSImage is keeping the image data in its original JPEG-compressed format, not as a rasterized bitmap.
That's a very good point. In this case, though, I think there probably is some excess stuff going on. Looking at what's going on with Shark, approx 1/5th of this thread's time is spent in 'read' (backed by disk cache), 1/4 in copyImageBlockSetTIFF, which seems to be done lazily but I presume is the decoding phase you allude to [although in this case it's pretty much just a memcpy], and 1/5 in imageProvider_getBytes, which copies the data *again*.
On 22 Feb 2011, at 00:05, Quincey Morris wrote:
>
> You know you're stuck with disk reads at some point in the process, which are going to be as slow as they're going to be. I'm going to go out on a limb and say that if your application can't swallow the additional cost of uncompressing and/or copying inside 'getBitmapDataPlanes' *once* per image**, your application design is broken*** -- or your Mac hardware is too slow for that application. :)
Very true, though as I mentioned the disk cache often works in my favour here. To be honest the specific issue of getBitmapDataPlanes is not really on the most critical realtime path in my code. As much as anything, it was a case of having spotted this issue I wanted to understand it thoroughly because there is GUI drawing (using NSImages/bitmaps etc) that is taking place in parallel with the main performance-critical stuff. Also, as Ken Ferry's reply revealed, there are evidently some "impedance matching" issues I should really understand better, so this is all extremely helpful.
On 22 Feb 2011, at 02:02, Ken Ferry wrote:
> However! ImageIO, the underlying home framework of all image file format reading and writing on Mac OS X, makes no promises about the relationship of the file to the in-memory pixel format. Certainly you know that many file formats are compressed, whereas the buffer you returned from the bitmapData method of NSBitmapImageRep is not. Further, there are many on-disk formats that are not supported by Quartz. Besides that, you might figure that the OS will never reduce the number of pixel formats, so if you're currently getting something tightly related to what you see in the file, you will expect to get that in the future. That's not the case though… CoreGraphics has talked about standardizing everything with less data than ARGB 32 host endian to ARGB 32 host endian right when its read in, to simplify and speedup later steps of the graphics pipeline. There are formats for which that happens today (I think maybe RGB JPEG data is coming in as as ARGB as of 10.6, perhaps?). That change was made as part of work in 10.6 to support decoding only rectangular blocks of an image throughout the graphics pipeline. Asking for the bitmapData also defeats that pipeline and forces everything into memory.
>
> Plus, it's pretty hard to write code that deals expressly with pixel data without putting things in a standard colorspace. RGBA (.3, .5, .6, 1.0) is a different color in sRGB vs generic RGB. For most pixel-processing algorithms, you'll get different visual results if you naively apply the same mathematics in different colorspaces.
>
> Anyway, point is, in all likelihood, you do need to draw your image to a bitmap in known format in order to work with the pixels. You probably only need to do this once though… if you're seeing repeated copying in bitmapData, that suggests that you're alternately drawing and asking for pixel data from the image. If you're never modifying the data, you could instead store the data on the side in addition to the rep. Storing can be done via subclass, wrapper object, global dictionary mapping rep object to data, objc associative storage, etc. Or, look at just drawing the image into a bitmap when you need to see the data. That's less work for you to implement, and may find that it performs well, depending on what was really costing you before. You could consider reusing one bitmap to draw in from multiple images to avoid malloc'ing and free'ing memory.
Thanks very much - lots of food for thought there. I think some of the issues you mention ~should~ be less severe because I am working with greyscale data, but maybe it's not guaranteed. The pattern I was following was at least previously a "recommended" approach I presume (see for example CocoaCreateMovie/CopyNSImageToGWorld). It sounds from what you're saying as if drawing the image into a bitmap may actually now be potentially more efficient and quite a nice solution.
However, in my case I would have to be extremely careful about matching formats etc. My code is doing analysis of scientific video data, and it is absolutely crucial that I can swap data between TIFF files and buffers in memory and leave the exact original greyscale values unchanged. From what you are saying, I'm starting to wonder whether there is any way at all that I can guarantee that, when using NSImage/BitmapImageRep. I like that approach because of the ease of working with other file types if necessary, and doing GUI display. I had assumed extracting the NSBitmapImageRep was safe (I do in fact check there is only one...), but it sounds like you're saying there's no promise of that? It may be that Cocoa's priorities/promises will never really be perfectly aligned to my needs here, but if you have any suggestions for a more appropriate approach I'd love to hear them!
Thanks again to everyone.
Jonny_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden