NSImage and TIFF (Obj-C) questions

  • Supposing I was fairly new to Objective-C (but had read both
    CurrencyConverter and the book PDF) and wanted to write an Obj-C Cocoa
    app which can open up JPG or TIFF files, put them into an NSImage in
    their own window, and then draw polygons on top of (not in) them, where
    would be the best place to look for example code? For the moment I'm
    happy to ignore the polygon bit (as that involves mouse events etc.) and
    just be able to open / display them.

    Apple's site doesn't seem to have any example code, and the Public Beta
    Dev Tools don't seem to install too many relevant to this task. Stepwise
    doesn't seem to have any on this, and nor does the Vermont Recipes.

    Any help gratefully appreciated!
    Cheers,
    Ken

    ---------
    Ken Tabb.
    Mac & UNIX C/C++/Java developer (Health & Human Sciences),
    Machine Vision researcher/programmer (Computer Science),
    University of Hertfordshire, Herts AL10 9AB, England
    Tel: (+0044 / 0) 1707 286171    e-mail: <ken...>
    http://www.health.herts.ac.uk/ken/

    Created in a Microsoft-free environment
  • Ken Tabb wrote:
    > Supposing I was fairly new to Objective-C (but had read both
    > CurrencyConverter and the book PDF) and wanted to write an Obj-C Cocoa
    > app which can open up JPG or TIFF files, put them into an NSImage in
    > their own window, and then draw polygons on top of (not in) them, where
    > would be the best place to look for example code? For the moment I'm
    > happy to ignore the polygon bit (as that involves mouse events etc.) and
    > just be able to open / display them.
    >
    > Apple's site doesn't seem to have any example code, and the Public Beta
    > Dev Tools don't seem to install too many relevant to this task. Stepwise
    > doesn't seem to have any on this, and nor does the Vermont Recipes.

    A good part of a solution using the GraphicKit:
    #include <GraphicKit/GraphicKit.h>
    @interface MyImageView:GKGraphicView
    {
    NSImage* backgroundImage
    }
    @end

    @implementation MyImageView
    - (void)drawBackgroundInRect:(NSRect)rect
    {
    [backgroundImage compositeToPoint:rect.origin fromRect:rect operation:NSCompositeCopy];
    }
    - (void)setBackgroundImage:(NSImage*)anImage
    {
    [anImage retain];
    [backgroundImage release];
    backgroundImage=anImage;
    }
    @end

    @interface PolygonShape:GKLineShape
    @end

    @implementation PolygonShape
    - (void)reconstructPath
    {
    [super reconstructPath];
    [path closePath];
    }
    @end

    @interface PolygonTool:GKLineTool
    @end

    @implementation PolygonTool
    - (PolygonShape*)newShape
    {
        return [[[PolygonShape alloc] init] autorelease];
    }

    // ** Optional; the superclass implements this method, but uses a GKSimpleGraphic.
    - (GKGraphic*)graphicForShape:(GKShape*)shape inDocument:(NSDocument*)document
    {
        GKComplexGraphic* graphic = [[GKComplexGraphic alloc] init];

        // ** Create effect
        GKGraphicEffect* effect = [(GKGraphicEffect*)[GKGraphicEffect alloc] initWithShape:shape];

        // ** Create operations
        GKOutlineOperation* outlineOp=[[GKOutlineOperation alloc] init];

        // ** Set up the operations
        [outlineOp setColor:[NSColor redColor]];
        [outlineOp setLineWidth:1.0];

        // ** Set up the effect.
        [effect addOperation:outlineOp];

        // ** Set up the graphic.
        [graphic addGraphicEffect:effect];
        [graphic setDepth:[controller currentDepth]];
        // ** Insert the graphic

        [document addGraphic:graphic];
        [document selectGraphic: graphic];

        // ** Clean up
        [effect release];
        [outlineOp release];

    return [graphic autorelease];
    }

    @end

    To get an image to put in the view, use [[NSImage alloc] initWithContentsOfFile:...] or some other NSImage method. The code above and the GraphicKitDemoX source code would get you 99% of the way, I think. If you want to use predefined polygons, you may want to subclass GKRectangleShape instead.

    If you don't want to use the GraphicKit, look at NSBezierPath for the polygons, NSArray for a polyon store, NSImage for the background and build an NSView subclass + controller for the drawing/user interaction. Using the GraphicKit will be a whole lot easier, but possibly less instructive.

    Regards,
    John Hornkvist

    --
    ToastedMarshmallow, the perfect Cocoa companion
    http://www.toastedmarshmallow.com
  • Hi Ken

    > Supposing I was fairly new to Objective-C (but had read both
    > CurrencyConverter and the book PDF) and wanted to write an Obj-C Cocoa
    > app which can open up JPG or TIFF files, put them into an NSImage in
    > their own window, and then draw polygons on top of (not in) them, where
    > would be the best place to look for example code? For the moment I'm
    > happy to ignore the polygon bit (as that involves mouse events etc.) and
    > just be able to open / display them.
    >
    > Apple's site doesn't seem to have any example code, and the Public Beta
    > Dev Tools don't seem to install too many relevant to this task. Stepwise
    > doesn't seem to have any on this, and nor does the Vermont Recipes.

    Ignoring the polygons, for now, a simple approach would be to build a document-based cocoa app using ProjectBuilder to create the bare bones. Fleshing out the app is straightforward... each document will be an image so you could drag an image viewer in to your document window in InterfaceBuilder from the 'More-Views' palette. Create an imageViewer outlet in your MyDocument class in IB. Connect the file owner's imageViewer outlet to the image viewer in IB. Then all that's left is a little bit of code in MyDocument to make things work:

    In MyDocument.h

    @interface MyDocument : NSDocument
    {
    IBOutlet NSImageView *imageViewer;
    NSImage *myImage;
    }
    @end

    In MyDocument.m alter the following

    - (BOOL)loadDataRepresentation:(NSData *)data ofType:(NSString *)aType
    {
    myImage = [[NSImage alloc] initWithData:data];

    if (!myImage)
      return NO;

    // can't put this straight into the imageViewer at this point as
    // the nib hasn't loaded yet... hence the myImage instance variable
    return YES;
    }

    - (void)windowControllerDidLoadNib:(NSWindowController *) aController
    {
    [super windowControllerDidLoadNib:aController];

    // now have a change to load up the viewer, as the interface is now in place
    if (myImage)
      [imageViewer setImage:myImage];
    }

    and add this

    - (void)dealloc
    {
    [myImage release];
    [super dealloc];
    }

    So how will it know to open images? Well, you need to go to 'Document Types' within 'Application Settings' in the tedious Targets pane of PB. Edit the name to be 'Images' and the 'Extensions' to be 'tiff jpeg pdf TIFF JPEG PDF tif TIF' (or whatever) and you should be away.

    Two notes: the app will produce a blank untitled window when you launch it... you may want to change this. Also, I sometimes have trouble making PB register changes to the Document Types settings... pressing return in the field before you press Change seems to work!

    As to the polygons, you could add a transparent view over the top and then create paths in response to mouse events, perhaps storing in an NSBezierPath.

    Hope this helps

    -- Gideon
  • > From: Ken Tabb <ken...>

    > Supposing I was fairly new to Objective-C (but had read both
    > CurrencyConverter and the book PDF) and wanted to write an Obj-C Cocoa
    > app which can open up JPG or TIFF files, put them into an NSImage in
    > their own window, and then draw polygons on top of (not in) them,
    where
    > would be the best place to look for example code? For the moment I'm
    > happy to ignore the polygon bit (as that involves mouse events
    etc.) and
    > just be able to open / display them.

    -     create a document based application in ProjectBuilder
    -    create your own NSView subclass with an instance variable
    for the document
    from which it will obtain the image
    implementing the drawRect: method to composite the image
    and set the custom-view's class in the Document nib to your view
    -    in the generated Document class, add an instance variable
    for the image
    as well as the appropriate accessor
    implement the stubbed method  for reading a
    data-representation of a certain
    type by initializing an NSImage from this data and storing
    it in your instance var
    -    add information to the CustomInfo property list (was that
    what it's called?)
    specifying that you want to handle TIFF and JPG files

    Run and Enjoy

    Marcel