1. 程式人生 > >UIimage的縮放,馬賽克處理,CVPixelBufferRef 轉換為UIimage

UIimage的縮放,馬賽克處理,CVPixelBufferRef 轉換為UIimage

UIimage類別

點選下載demo
demo裡面還有一個計算檔案大小的方法

//裡面有5個方法
//1、 CVPixelBufferRef 轉換為UIimage
//2、UIimage 縮放指定倍數
//3、UIimage 縮放指定大小
//4、圖片馬賽克處理
//5、圖片馬賽克處理


#import "UIImage+ytt.h"

@implementation UIImage (ytt)
#define kBitsPerComponent (8)
#define kBitsPerPixel (32)
#define kPixelChannelCount (4)//每一行的畫素點佔用的位元組數,每個畫素點的ARGB四個通道各佔8個bit
#pragma mark - #pragma mark - CVPixelBufferRef 轉換 UIimage /** CVPixelBufferRef 轉換為UIimage @param pixelBufffer 圖片的CVPixelBufferRef @return UIimage */ +(UIImage*)pixelBufferToImage:(CVPixelBufferRef) pixelBufffer{ CVPixelBufferLockBaseAddress(pixelBufffer, 0);// 鎖定pixel buffer的基地址 void * baseAddress = CVPixelBufferGetBaseAddress(pixelBufffer);// 得到pixel buffer的基地址
size_t width = CVPixelBufferGetWidth(pixelBufffer); size_t height = CVPixelBufferGetHeight(pixelBufffer); size_t bufferSize = CVPixelBufferGetDataSize(pixelBufffer); size_t bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBufffer);// 得到pixel buffer的行位元組數 CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();// 建立一個依賴於裝置的RGB顏色空間
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, baseAddress, bufferSize, NULL); CGImageRef cgImage = CGImageCreate(width, height, kBitsPerComponent, kBitsPerPixel, bytesPerRow, rgbColorSpace, kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrderDefault, provider, NULL, true, kCGRenderingIntentDefault);//這個是建立一個CGImageRef物件的函式 UIImage *image = [UIImage imageWithCGImage:cgImage]; CGImageRelease(cgImage); //類似這些CG...Ref 在使用完以後都是需要release的,不然記憶體會有問題 CGDataProviderRelease(provider); CGColorSpaceRelease(rgbColorSpace); NSData* imageData = UIImageJPEGRepresentation(image, 1.0);//1代表圖片是否壓縮 image = [UIImage imageWithData:imageData]; CVPixelBufferUnlockBaseAddress(pixelBufffer, 0); // 解鎖pixel buffer return image; } #pragma mark - #pragma mark - 縮放處理 //縮放倍數 + (UIImage *)scaleImage:(UIImage *)image withScale:(float)scale { UIGraphicsBeginImageContext(CGSizeMake(image.size.width * scale, image.size.height * scale)); [image drawInRect:CGRectMake(0, 0, image.size.width * scale, image.size.height * scale)]; UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return scaledImage; } //指定縮放大小 + (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)size { UIGraphicsBeginImageContext(CGSizeMake(size.width, size.height)); [image drawInRect:CGRectMake(0, 0, size.width, size.height)]; UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return scaledImage; } #pragma mark - #pragma mark - 馬賽克處理 static CGContextRef CreateRGBABitmapContext (CGImageRef inImage) { CGContextRef context = NULL; CGColorSpaceRef colorSpace; void *bitmapData; //記憶體空間的指標,該記憶體空間的大小等於影象使用RGB通道所佔用的位元組數。 NSInteger bitmapByteCount; NSInteger bitmapBytesPerRow; size_t pixelsWide = CGImageGetWidth(inImage); //獲取橫向的畫素點的個數 size_t pixelsHigh = CGImageGetHeight(inImage); bitmapBytesPerRow = (pixelsWide * 4); //每一行的畫素點佔用的位元組數,每個畫素點的ARGB四個通道各佔8個bit(0-255)的空間 bitmapByteCount = (bitmapBytesPerRow * pixelsHigh); //計算整張圖佔用的位元組數 colorSpace = CGColorSpaceCreateDeviceRGB();//建立依賴於裝置的RGB通道 //分配足夠容納圖片位元組數的記憶體空間 bitmapData = malloc( bitmapByteCount ); //建立CoreGraphic的圖形上下文,該上下文描述了bitmaData指向的記憶體空間需要繪製的影象的一些繪製引數 context = CGBitmapContextCreate (bitmapData, pixelsWide, pixelsHigh, 8, bitmapBytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast); //Core Foundation中通過含有Create、Alloc的方法名字建立的指標,需要使用CFRelease()函式釋放 CGColorSpaceRelease( colorSpace ); return context; } static unsigned char *RequestImagePixelData(UIImage *inImage) { CGImageRef img = [inImage CGImage]; CGSize size = [inImage size]; //使用上面的函式建立上下文 CGContextRef cgctx = CreateRGBABitmapContext(img); CGRect rect = {{0,0},{size.width, size.height}}; //將目標影象繪製到指定的上下文,實際為上下文內的bitmapData。 CGContextDrawImage(cgctx, rect, img); unsigned char *data = CGBitmapContextGetData (cgctx); //釋放上面的函式建立的上下文 CGContextRelease(cgctx); return data; } + (UIImage *)mosaicImage:(UIImage *)image withLevel:(int)level { unsigned char *imgPixel = RequestImagePixelData(image); CGImageRef inImageRef = [image CGImage]; GLuint64 width = CGImageGetWidth(inImageRef); GLuint64 height = CGImageGetHeight(inImageRef); unsigned char prev[4] = {0}; NSInteger bytewidth = width*4; int i,j; int val = level; for(i=0;i<height;i++) { if (((i+1)%val) == 0) { memcpy(imgPixel+bytewidth*i, imgPixel+bytewidth*(i-1), bytewidth); continue; } for(j=0;j<width;j++) { if (((j+1)%val) == 1) { memcpy(prev, imgPixel+bytewidth*i+j*4, 4); continue; } memcpy(imgPixel+bytewidth*i+j*4, prev, 4); } } NSInteger dataLength = width*height* 4; //下面的程式碼建立要輸出的影象的相關引數 CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, imgPixel, dataLength, NULL); // prep the ingredients int bitsPerComponent = 8; int bitsPerPixel = 32; CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault; CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault; //建立要輸出的影象 CGImageRef imageRef = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytewidth, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent); UIImage *mosaicImage = [UIImage imageWithCGImage:imageRef scale:image.scale orientation:image.imageOrientation]; CFRelease(imageRef); CGColorSpaceRelease(colorSpaceRef); CGDataProviderRelease(provider); return mosaicImage; } /* *轉換成馬賽克,level代表一個點轉為多少level*level的正方形 */ + (UIImage *)transToMosaicImage:(UIImage*)orginImage blockLevel:(NSUInteger)level { //獲取BitmapData CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGImageRef imgRef = orginImage.CGImage; CGFloat width = CGImageGetWidth(imgRef); CGFloat height = CGImageGetHeight(imgRef); CGContextRef context = CGBitmapContextCreate (nil, width, height, kBitsPerComponent, //每個顏色值8bit width*kPixelChannelCount, //每一行的畫素點佔用的位元組數,每個畫素點的ARGB四個通道各佔8個bit colorSpace, kCGImageAlphaPremultipliedLast); CGContextDrawImage(context, CGRectMake(0, 0, width, height), imgRef); unsigned char *bitmapData = CGBitmapContextGetData (context); //這裡把BitmapData進行馬賽克轉換,就是用一個點的顏色填充一個level*level的正方形 unsigned char pixel[kPixelChannelCount] = {0}; NSUInteger index,preIndex; for (NSUInteger i = 0; i < height - 1 ; i++) { for (NSUInteger j = 0; j < width - 1; j++) { index = i * width + j; if (i % level == 0) { if (j % level == 0) { memcpy(pixel, bitmapData + kPixelChannelCount*index, kPixelChannelCount); }else{ memcpy(bitmapData + kPixelChannelCount*index, pixel, kPixelChannelCount); } } else { preIndex = (i-1)*width +j; memcpy(bitmapData + kPixelChannelCount*index, bitmapData + kPixelChannelCount*preIndex, kPixelChannelCount); } } } NSInteger dataLength = width*height* kPixelChannelCount; CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, bitmapData, dataLength, NULL); //建立要輸出的影象 CGImageRef mosaicImageRef = CGImageCreate(width, height, kBitsPerComponent, kBitsPerPixel, width*kPixelChannelCount , colorSpace, kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrderDefault, provider, NULL, NO, kCGRenderingIntentDefault); CGContextRef outputContext = CGBitmapContextCreate(nil, width, height, kBitsPerComponent, width*kPixelChannelCount, colorSpace, kCGImageAlphaPremultipliedLast); CGContextDrawImage(outputContext, CGRectMake(0.0f, 0.0f, width, height), mosaicImageRef); CGImageRef resultImageRef = CGBitmapContextCreateImage(outputContext); UIImage *resultImage = nil; if([UIImage respondsToSelector:@selector(imageWithCGImage:scale:orientation:)]) { // float scale = [[UIScreen mainScreen] scale]; // resultImage = [UIImage imageWithCGImage:resultImageRef scale:scale orientation:UIImageOrientationUp]; resultImage = [UIImage imageWithCGImage:resultImageRef scale:orginImage.scale orientation:orginImage.imageOrientation]; } else { resultImage = [UIImage imageWithCGImage:resultImageRef]; } //釋放 if(resultImageRef){ CFRelease(resultImageRef); } if(mosaicImageRef){ CFRelease(mosaicImageRef); } if(colorSpace){ CGColorSpaceRelease(colorSpace); } if(provider){ CGDataProviderRelease(provider); } if(context){ CGContextRelease(context); } if(outputContext){ CGContextRelease(outputContext); } // return [[resultImage retain] autorelease]; return resultImage; } @end