I am using Apple sample code to downsize the image.
I tested for two images. One image is 204kB and other image is 205kB. It is crashing for 204kB image giving error as Terminating app due to uncaught exception 'CALayerInvalidGeometry', reason: 'CALayer position contains NaN: [nan nan]'
I got the code from https://developer.apple.com/library/ios/samplecode/LargeImageDownsizing/Introduction/Intro.html#//apple_ref/doc/uid/DTS40011173
Link for the image which is crashing http://www.bluebell-railway.co.uk/bluebell/personal/jon-bowers/extension/17_3l.jpg
I could only get that destImageRef is coming NULL
Code to downsize the image:
-(void)downsize:(id)_arg {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
sourceImage = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:kImageFilename ofType:nil]];
if( sourceImage == nil ) NSLog(@"input image not found!");
sourceResolution.width = CGImageGetWidth(sourceImage.CGImage);
sourceResolution.height = CGImageGetHeight(sourceImage.CGImage);
sourceTotalPixels = sourceResolution.width * sourceResolution.height;
sourceTotalMB = sourceTotalPixels / pixelsPerMB;
imageScale = destTotalPixels / sourceTotalPixels;
destResolution.width = (int)( sourceResolution.width * imageScale );
destResolution.height = (int)( sourceResolution.height * imageScale );
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
int bytesPerRow = bytesPerPixel * destResolution.width;
void* destBitmapData = malloc( bytesPerRow * destResolution.height );
if( destBitmapData == NULL ) NSLog(@"failed to allocate space for the output image!");
destContext = CGBitmapContextCreate( destBitmapData, destResolution.width, destResolution.height, 8, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast );
if( destContext == NULL ) {
free( destBitmapData );
NSLog(@"failed to create the output bitmap context!");
}
CGColorSpaceRelease( colorSpace );
CGContextTranslateCTM( destContext, 0.0f, destResolution.height );
CGContextScaleCTM( destContext, 1.0f, -1.0f );
sourceTile.size.height = (int)( tileTotalPixels / sourceTile.size.width );
NSLog(@"source tile size: %f x %f",sourceTile.size.width, sourceTile.size.height);
sourceTile.origin.x = 0.0f;
destTile.size.width = destResolution.width;
destTile.size.height = sourceTile.size.height * imageScale;
destTile.origin.x = 0.0f;
NSLog(@"dest tile size: %f x %f",destTile.size.width, destTile.size.height);
sourceSeemOverlap = (int)( ( destSeemOverlap / destResolution.height ) * sourceResolution.height );
NSLog(@"dest seem overlap: %f, source seem overlap: %f",destSeemOverlap, sourceSeemOverlap);
CGImageRef sourceTileImageRef;
int iterations = (int)( sourceResolution.height / sourceTile.size.height );
int remainder = (int)sourceResolution.height % (int)sourceTile.size.height;
if( remainder ) iterations++;
float sourceTileHeightMinusOverlap = sourceTile.size.height;
sourceTile.size.height += sourceSeemOverlap;
destTile.size.height += destSeemOverlap;
NSLog(@"beginning downsize. iterations: %d, tile height: %f, remainder height: %d", iterations, sourceTile.size.height,remainder );
for( int y = 0; y < iterations; ++y ) {
NSAutoreleasePool* pool2 = [[NSAutoreleasePool alloc] init];
NSLog(@"iteration %d of %d",y+1,iterations);
sourceTile.origin.y = y * sourceTileHeightMinusOverlap + sourceSeemOverlap;
destTile.origin.y = ( destResolution.height ) - ( ( y + 1 ) * sourceTileHeightMinusOverlap * imageScale + destSeemOverlap );
sourceTileImageRef = CGImageCreateWithImageInRect( sourceImage.CGImage, sourceTile );
if( y == iterations - 1 && remainder ) {
float dify = destTile.size.height;
destTile.size.height = CGImageGetHeight( sourceTileImageRef ) * imageScale;
dify -= destTile.size.height;
destTile.origin.y += dify;
}
CGContextDrawImage( destContext, destTile, sourceTileImageRef );
CGImageRelease( sourceTileImageRef );
[sourceImage release];
// free all objects that were sent -autorelease within the scope of this loop.
[pool2 drain];
if( y < iterations - 1 ) {
sourceImage = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:kImageFilename ofType:nil]];
[self performSelectorOnMainThread:@selector(updateScrollView:) withObject:nil waitUntilDone:YES];
}
}
NSLog(@"downsize complete.");
[self performSelectorOnMainThread:@selector(initializeScrollView:) withObject:nil waitUntilDone:YES];
CGContextRelease( destContext );
[pool drain];
and in the following method it is giving "destImageRef is null"
-(void)createImageFromContext {
// create a CGImage from the offscreen image context
CGImageRef destImageRef = CGBitmapContextCreateImage( destContext );
if( destImageRef == NULL ) NSLog(@"destImageRef is null.");
// wrap a UIImage around the CGImage
self.destImage = [UIImage imageWithCGImage:destImageRef scale:1.0f orientation:UIImageOrientationDownMirrored];
// release ownership of the CGImage, since destImage retains ownership of the object now.
CGImageRelease( destImageRef );
if( destImage == nil ) NSLog(@"destImage is nil.");
}