mrEmpty
mrEmpty

Reputation: 841

Resizing a UIImage, or CIImage, before cropping, stretches the images?

OK, I've tried every single example I can find to do this, sadly most of them are from 2008-2009 and iOS5 seems to be very different. I simply want to resize and image so that the short edge is a size I specify, and it stays in proportion.

I am using AVFoundation to grab an image from the camera, I convert that through a UIImage to a CIImage so I can apply filters and fiddle with it, before converting back to a UIImage for saving.

- (void) startCamera {

session = [[AVCaptureSession alloc] init];
session.sessionPreset = AVCaptureSessionPresetPhoto;

AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
captureVideoPreviewLayer.frame = _cameraView.bounds;
[_cameraView.layer addSublayer:captureVideoPreviewLayer];
captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;

AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error = nil;

AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
if (!input) {
    //no cam, handle error - need to put up a nice happy note here
    NSLog(@"ERROR: %@", error);
}

[session addInput:input];

stillImage = [[AVCaptureStillImageOutput alloc] init];
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys:AVVideoCodecJPEG , AVVideoCodecKey, nil];
[stillImage setOutputSettings:outputSettings];

[session addOutput:stillImage];
[session startRunning];
}

- (IBAction) _cameraButtonPress:(id)sender {

AVCaptureConnection *videoConnection = nil;
for (AVCaptureConnection *connection in stillImage.connections)
{
    for (AVCaptureInputPort *port in [connection inputPorts])
    {
        if ([[port mediaType] isEqual:AVMediaTypeVideo] )
        {
            videoConnection = connection;
            break;
        }
    }
    if (videoConnection) {
        break;
    }
}

[stillImage captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:^(CMSampleBufferRef imageSampleBuffer, NSError *error) {

    NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
    UIImage *startImage = [[UIImage alloc] initWithData:imageData];

    //resizing of image to take place before anything else
    UIImage *image = [startImage imageScaledToFitSize:_exportSSize];  //resizes to the size given in the prefs

    //change the context to render using cpu, so on app exit renders get completed
    context = [CIContext contextWithOptions:
               [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES]
                                           forKey:kCIContextUseSoftwareRenderer]];

    //set up the saving library
    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];

    //create a new ciimage
    CIImage *greyImage = [[CIImage alloc] initWithCGImage:[image CGImage]];

    //create a CIMonochrome filter 
    desaturate = [CIFilter filterWithName:@"CIColorMonochrome" keysAndValues:kCIInputImageKey, greyImage, @"inputIntensity", [NSNumber numberWithFloat:0.00], nil];

    //[crop setValue:ciImage forKey:@"inputImage"];
    //[crop setValue:[CIVector vectorWithX:0.0f Y:0.0f Z:_exportSize W:_exportSize] forKey:@"inputRectangle"];

    CIImage *croppedColourImage = [desaturate valueForKey:@"outputImage"];
    //convert it to a cgimage for saving
    CGImageRef cropColourImage = [context createCGImage:croppedColourImage fromRect:[croppedColourImage extent]];

     //saving of the images         
     [library writeImageToSavedPhotosAlbum:cropColourImage metadata:[croppedColourImage properties] completionBlock:^(NSURL *assetURL, NSError *error){
     if (error) {
         NSLog(@"ERROR in image save: %@", error);
     } else
     {
         NSLog(@"SUCCESS in image save");
         //in here we'll put a nice animation or something
         CGImageRelease(cropColourImage);
     }

     }];
}];
}

This code is test code so will have all sorts of attempts in it, apologies for that.

The closest I've got is using Matt Gemmell's code here

But that, no matter what I try, always stretches the image. I want to resize the image then crop it to be 512 pixels square. If I just do a CICrop filter it takes the top left 512 pixels so I lose a lot of the image (grabbing a high res photo, as later I'll also want to export 1800x1800 images). My thinking was to resize the image first, then crop. But no matter what I do, the image gets stretched.

So my question is, is there a proper suggested recognised way to resize and image in iOS5+?

Thanks.

Upvotes: 0

Views: 4347

Answers (1)

mrEmpty
mrEmpty

Reputation: 841

I have found one way to do it:

UIGraphicsBeginImageContext( newSize );

[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];

UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

Upvotes: 1

Related Questions