ryanmcgrath / cacao

Rust bindings for AppKit (macOS) and UIKit (iOS/tvOS). Experimental, but working!
MIT License
1.79k stars 65 forks source link

Capability to resize Images #119

Open EstebanBorai opened 4 weeks ago

EstebanBorai commented 4 weeks ago

It would be nice to have support to set a fixed height and width for an image.

Im using cacao::image::Image instance with Image::with_data to set an image from bytes into a view, but I don't seem to find a way to set image dimensions.

I have found the following snippet on StackOverflow on how could it be done:

- (NSImage *)imageResize:(NSImage*)anImage newSize:(NSSize)newSize {
    NSImage *sourceImage = anImage;
    [sourceImage setScalesWhenResized:YES];

    // Report an error if the source isn't a valid image
    if (![sourceImage isValid]){
        NSLog(@"Invalid Image");
    } else {
        NSImage *smallImage = [[NSImage alloc] initWithSize: newSize];
        [smallImage lockFocus];
        [sourceImage setSize: newSize];
        [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
        [sourceImage drawAtPoint:NSZeroPoint fromRect:CGRectMake(0, 0, newSize.width, newSize.height) operation:NSCompositingOperationCopy fraction:1.0];
        [smallImage unlockFocus];
        return smallImage;
    }
    return nil;
}

https://stackoverflow.com/questions/11949250/how-to-resize-nsimage

But given that Im not very familiar with Objective-C Im not pretty sure if there could be a simpler approach.

Thanks in advance!

ryanmcgrath commented 4 weeks ago

Hmm, does using ResizeBehavior::Stretch not hit the behavior you're after?

https://github.com/ryanmcgrath/cacao/blob/e3bbb9366c8cf5a5474c5b134ae60e9641da3b7b/src/image/image.rs#L18-L32

(Alternatively, you could implement a custom draw closure - maybe that'd help?)

EstebanBorai commented 4 weeks ago

Thanks for the quick reply @ryanmcgrath!

Im trying with Image::draw this time.

        let img = Image::draw(DrawConfig {
            source: (512., 512.), // Original Image Size
            target: (64., 64.),   // Expected Size
            resize: ResizeBehavior::AspectFit, // Maintain Aspect Ratio
        }, |cg_rect, ctx| {
            // My understanding is that here I could attempt load my Image bytes into
            // a `CGImage` instance but I didn't found any `from_bytes` like method
            // in `core-graphics`
            ctx.draw_image(cg_rect, /* need a CGImage instance representing my file */);
            true
        });

Any suggestions?

ryanmcgrath commented 3 weeks ago

Hmmm, yeah, you'd need to dig around in Core Graphics to find an equivalent for drawing the image directly - it's been a bit since I've had to spelunk that low so my memory is unfortunately hazy there.

One odd path you could also consider: creating a cacao::image::Image and calling CGImageForProposedRect:context:hints: to get a CGImageRef from the underlying NSImage, then taking that into a new image (or custom draw handler).