hyuni
1/31/2016 - 5:22 AM

UIImage scale using vImage

UIImage scale using vImage

-(UIImage*)mmg_imageScaledToFitSize:(CGSize)fitSize
{
	// Create a vImage_Buffer from the CGImage
	CGImageRef sourceRef = self.CGImage;
	vImage_Buffer srcBuffer;
	vImage_CGImageFormat format = {
		.bitsPerComponent = 8,
		.bitsPerPixel = 32,
		.colorSpace = NULL,
		.bitmapInfo = (CGBitmapInfo)kCGImageAlphaFirst,
		.version = 0,
		.decode = NULL,
		.renderingIntent = kCGRenderingIntentDefault,
	};
	vImage_Error ret = vImageBuffer_InitWithCGImage(&srcBuffer, &format, NULL, sourceRef, kvImageNoFlags);
	if (ret != kvImageNoError)
	{
		free(srcBuffer.data);
		return nil;
	}

	// Create dest buffer
	const NSUInteger scale = (NSUInteger)[[UIScreen mainScreen] scale];
	const NSUInteger dstWidth = (NSUInteger)fitSize.width * scale;
	const NSUInteger dstHeight = (NSUInteger)fitSize.height * scale;
	const NSUInteger bytesPerPixel = 4;
	const NSUInteger dstBytesPerRow = bytesPerPixel * dstWidth;
	uint8_t* dstData = (uint8_t*)calloc(dstHeight * dstWidth * bytesPerPixel, sizeof(uint8_t));
	vImage_Buffer dstBuffer = {
		.data = dstData,
		.height = dstHeight,
		.width = dstWidth,
		.rowBytes = dstBytesPerRow
	};

	// Scale
	ret = vImageScale_ARGB8888(&srcBuffer, &dstBuffer, NULL, kvImageHighQualityResampling);
	free(srcBuffer.data);
	if (ret != kvImageNoError)
	{
		free(dstData);
		return nil;
	}

	// Create CGImage from vImage_Buffer
	ret = kvImageNoError;
	CGImageRef destRef = vImageCreateCGImageFromBuffer(&dstBuffer, &format, NULL, NULL, kvImageNoFlags, &ret);
	free(dstData);

	// Create UIImage
	UIImage* destImage = [[UIImage alloc] initWithCGImage:destRef scale:0.0 orientation:self.imageOrientation];
	// Free up the remaining memory
	CGImageRelease(destRef);

	return destImage;
}