UIimage的縮放,馬賽克處理,CVPixelBufferRef 轉換為UIimage
阿新 • • 發佈:2019-01-09
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