Re: Scheme for efficiently archiving images.
Re: Scheme for efficiently archiving images.
- Subject: Re: Scheme for efficiently archiving images.
- From: Graham Cox <email@hidden>
- Date: Thu, 27 Nov 2008 17:54:51 +1100
On 27 Nov 2008, at 2:00 pm, Ken Thomases wrote:
First, it seems to me like you don't want an NSImage in your model.
You want the original source of the image. Either a file path or a
blob of data with some meta-data (e.g. UTI) describing it and what
it is. You'd use NSImage as a view-enabling technology.
Yep, this is precisely how I'm coming to see it. One kink is that I
need to keep old-format stuff working, which isn't too hard, but it
means I need to be a little careful about how I eliminate NSImage from
the archived model. One minor difficulty is that for old-format files,
all I get is an archived NSImage, with no original data. That means
that it's probably going to be impossible to convert those files to a
more efficient approach. But for new files, I can do things
differently - it won't be readable by an older version of the app but
I can live with that.
If you get a file from the user, you might want to copy it to a
temporary file of your own, to protect against the original file
being deleted.
For now I think I'm going to work this by locally caching the data
content of the file. It's less memory efficient but easier. Maybe if I
can get that working smoothly I can move to the next step of not
keeping the data in memory but read from disk as needed. By
centralising this image cache in one class, I can extend it to work
with on-disk images transparently. The reason for centralising the
image cache in this way (per document) is that it also solves the
several copies of the same image problem - it only ever keeps one data
object for each image how ever many instances are created from it.
Each instance just keeps a unique key that refers to the image data in
the central cache.
Some possibilities of where to go from there:
Approach 1: This is a bit of a kludge. Don't have your model
archive its image. Instead, have your NSDocument-subclass writing
method directly query your model for the image information, so it
can store it separately from the archived model object. This
supports putting it in a file in a package-style document.
This seems like a good idea, doesn't seem too kludgey to me actually.
Since I'm already overriding NSDocument to build my package, adding a
step to write out the image cache up front would be straightforward.
Approach 2: This is a refinement of approach 1 which makes it less
kludgy. Create a custom archiver class, subclassing
NSKeyedArchiver. Your NSDocument subclass would use that to archive
your model. It would be initialized with information about where to
store image data out-of-band -- that is, not in the data object it
creates as part of the archiving step. In your image-holding model
class, encodeWithCoder: would check for that special type of coder.
If it's the special type, use methods of your own design to pass the
image data to the archiver for out-of-band storage. If it's a
normal coder, just store the image data in the naive way.
With either approach, you'd do the complement for reading the
document, of course.
Some interesting ideas. What I've started with so far is to stick with
standard keyed archiving, but the very first thing that gets archived
by the root object is the image cache object. Clients of this then
just archive the image keys safe in the knowledge that the archive has
been written already. If they have a key, it means they *must* have
initialised their images from the cache - a nil key means the image
data was given to them already created so they have no choice but to
archive it wholesale. That way old-format files can still be saved
without losing their images. Currently there's not much risk that the
client objects could be archived without being part of the complete
model, so they can assume the existence of the image cache. I guess I
could add a check in encodeWithCoder: that it's part of a complete
model archiving operation, or as you suggest, use a special archiver
subclass to flag this.
Using a special archiver/dearchiver does address another issue too,
which make it attractive, and that is the reachability of the image
cache during dearchiving. Currently it works OK for the main object I
need to adapt to this, since the object graph is complete enough at
that point to reach the image cache owned by the root. But for another
object type the cache is currently unreachable without a big kludge,
so if it could be simply pulled out of the dearchiver that would solve
that problem well.
In -initWithCoder: I can also assume that if there's no key, just
unarchive the image as before.
So far, so good, with the exception of the strange NSImage behaviour I
mentioned earlier. If I can solve that, I'll be home and dry, I think.
Thanks for your input - very valuable and much appreciated :)
cheers, Graham
_______________________________________________
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