123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526 |
- //
- // FUImageHelper.m
- // FULiveDemo
- //
- // Created by L on 2018/8/3.
- // Copyright © 2018年 L. All rights reserved.
- //
- #import "FUImageHelper.h"
- @implementation FUImageHelper
- + (void) convertUIImageToBitmapRGBA8:(UIImage *) image completionHandler:(void (^)(int32_t size, unsigned char * bits))completionHandler {
-
- CGImageRef imageRef = image.CGImage;
-
- // Create a bitmap context to draw the uiimage into
- CGContextRef context = [self newBitmapRGBA8ContextFromImage:imageRef];
-
- if(!context) {
- return ;
- }
-
- int32_t width = (int32_t)CGImageGetWidth(imageRef);
- int32_t height = (int32_t)CGImageGetHeight(imageRef);
-
- CGRect rect = CGRectMake(0, 0, width, height);
-
- // Draw image into the context to get the raw image data
- CGContextDrawImage(context, rect, imageRef);
-
- // Get a pointer to the data
- unsigned char *bitmapData = (unsigned char *)CGBitmapContextGetData(context);
-
- // Copy the data and release the memory (return memory allocated with new)
- size_t bytesPerRow = CGBitmapContextGetBytesPerRow(context);
- size_t bufferLength = bytesPerRow * height;
-
- unsigned char *newBitmap = NULL;
-
- union i32c{
- int32_t i32v;
- unsigned char bytes[4];
- };
-
- union i32c cwidth;
- cwidth.i32v = width;
- union i32c cheight;
- cheight.i32v = height;
- if(bitmapData) {
- newBitmap = (unsigned char *)malloc(sizeof(unsigned char) * bytesPerRow * height + 8);
- newBitmap[0] =cwidth.bytes[0];
- newBitmap[1] =cwidth.bytes[1];
- newBitmap[2] =cwidth.bytes[2];
- newBitmap[3] =cwidth.bytes[3];
- newBitmap[4]=cheight.bytes[0];
- newBitmap[5] =cheight.bytes[1];
- newBitmap[6] =cheight.bytes[2];
- newBitmap[7] =cheight.bytes[3];
-
- if(newBitmap) { // Copy the data
- for(int i = 8; i < bufferLength+8; ++i) {
- newBitmap[i] = bitmapData[i - 8];
- }
- }
-
- free(bitmapData);
-
- } else {
- NSLog(@"Error getting bitmap pixel data\n");
- }
-
- CGContextRelease(context);
-
- completionHandler((size_t)bufferLength +8,newBitmap);
- }
- + (CGContextRef) newBitmapRGBA8ContextFromImage:(CGImageRef) image {
- CGContextRef context = NULL;
- CGColorSpaceRef colorSpace;
- uint32_t *bitmapData;
-
- size_t bitsPerPixel = 32;
- size_t bitsPerComponent = 8;
- size_t bytesPerPixel = bitsPerPixel / bitsPerComponent;
-
- size_t width = CGImageGetWidth(image);
- size_t height = CGImageGetHeight(image);
-
- size_t bytesPerRow = width * bytesPerPixel;
- size_t bufferLength = bytesPerRow * height;
-
- colorSpace = CGColorSpaceCreateDeviceRGB();
-
- if(!colorSpace) {
- NSLog(@"Error allocating color space RGB\n");
- return NULL;
- }
-
- // Allocate memory for image data
- bitmapData = (uint32_t *)malloc(bufferLength);
-
- if(!bitmapData) {
- NSLog(@"Error allocating memory for bitmap\n");
- CGColorSpaceRelease(colorSpace);
- return NULL;
- }
-
- //Create bitmap context
-
- context = CGBitmapContextCreate(bitmapData,
- width,
- height,
- bitsPerComponent,
- bytesPerRow,
- colorSpace,
- kCGImageAlphaPremultipliedLast); // RGBA
- if(!context) {
- free(bitmapData);
- NSLog(@"Bitmap context not created");
- }
-
- CGColorSpaceRelease(colorSpace);
-
- return context;
- }
- + (unsigned char *)getRGBAWithImage:(UIImage *)image
- {
- int RGBA = 4;
-
- CGImageRef imageRef = [image CGImage];
-
- size_t width = CGImageGetWidth(imageRef);
- size_t height = CGImageGetHeight(imageRef);
-
- CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
- unsigned char *rawData = (unsigned char *) malloc(width * height * sizeof(unsigned char) * RGBA);
- NSUInteger bytesPerPixel = RGBA;
- NSUInteger bytesPerRow = bytesPerPixel * width;
- NSUInteger bitsPerComponent = 8;
- CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
-
- CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
-
- CFRelease(imageRef);
- CGColorSpaceRelease(colorSpace);
- CGContextRelease(context);
- return rawData;
- }
- + (unsigned char *)getRGBAWithImageName:(NSString *)imageName width:(int *)width height:(int *)height{
- //获取图片文件路径
- NSString * path = [[NSBundle mainBundle]pathForResource:imageName ofType:@"png"];
- NSURL * url = [NSURL fileURLWithPath:path];
- CGImageRef imageRef = NULL;
- CGImageSourceRef myImageSource;
- //通过文件路径创建CGImageSource对象
- myImageSource = CGImageSourceCreateWithURL((CFURLRef)url, NULL);
- //获取第一张图片
- imageRef = CGImageSourceCreateImageAtIndex(myImageSource,
- 0,
- NULL);
-
- size_t width0 = CGImageGetWidth(imageRef);
- size_t height0 = CGImageGetHeight(imageRef);
- *width = (int)width0;
- *height = (int)height0;
-
- int RGBA = 4;
- CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
- unsigned char *rawData = (unsigned char *) malloc(width0 * height0 * sizeof(unsigned char) * RGBA);
- memset(rawData, 0, width0 * height0 * sizeof(unsigned char) * RGBA);
- NSUInteger bytesPerPixel = RGBA;
- NSUInteger bytesPerRow = bytesPerPixel * width0;
- NSUInteger bitsPerComponent = 8;
- CGContextRef context = CGBitmapContextCreate(rawData, width0, height0, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
-
- CGContextDrawImage(context, CGRectMake(0, 0, width0, height0), imageRef);
-
- CFRelease(imageRef);
- CGColorSpaceRelease(colorSpace);
- CGContextRelease(context);
-
- CFRelease(myImageSource);
- return rawData;
-
- }
- + (UIImage *) convertBitmapRGBA8ToUIImage:(unsigned char *) buffer
- withWidth:(int) width
- withHeight:(int) height{
-
- /* 一些到blend完,带上了素材alpha,导致保存效果不对,强行将alpha = 1.0 */
- int length = height * width * 4;
- for (int i=0; i<length; i+=4)
- {
- buffer[i+3] = 255;
- }
-
- CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
- CGContextRef context = CGBitmapContextCreate(buffer,
- width,
- height,
- 8,
- width * 4,
- colorSpace,
- kCGImageAlphaPremultipliedLast);
-
- CGContextSetAlpha(context, 1.0);
- CGImageRef imageRef = CGBitmapContextCreateImage(context);
- CGContextRelease(context);
- CGColorSpaceRelease(colorSpace);
-
- UIImage *image = [UIImage imageWithCGImage:imageRef];
- CGImageRelease(imageRef);
- return image;
- }
- +(CVPixelBufferRef) pixelBufferFromImage:(UIImage *)image {
-
- NSDictionary *options = @{
- (NSString*)kCVPixelBufferCGImageCompatibilityKey : @YES,
- (NSString*)kCVPixelBufferCGBitmapContextCompatibilityKey : @YES,
- (NSString*)kCVPixelBufferIOSurfacePropertiesKey: [NSDictionary dictionary]
- };
-
- CVPixelBufferRef pxbuffer = NULL;
- CGFloat frameWidth = CGImageGetWidth(image.CGImage);
- CGFloat frameHeight = CGImageGetHeight(image.CGImage);
- CVReturn status = CVPixelBufferCreate(
- kCFAllocatorDefault,
- frameWidth,
- frameHeight,
- kCVPixelFormatType_32BGRA,
- (__bridge CFDictionaryRef)options,
- &pxbuffer);
-
- NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL);
-
- CVPixelBufferLockBaseAddress(pxbuffer, 0);
-
- void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
-
- NSParameterAssert(pxdata != NULL);
-
- CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
-
- CGContextRef context = CGBitmapContextCreate(
- pxdata,
- frameWidth,
- frameHeight,
- 8,
- CVPixelBufferGetBytesPerRow(pxbuffer),
- rgbColorSpace, kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little);
- NSParameterAssert(context);
-
- CGContextConcatCTM(context, CGAffineTransformIdentity);
-
- CGContextDrawImage(context, CGRectMake(0, 0, frameWidth, frameHeight), image.CGImage);
-
- CGColorSpaceRelease(rgbColorSpace);
- CGContextRelease(context);
- CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
- // CFRelease(rgbColorSpace) ;
-
- return pxbuffer;
- }
- +(UIImage *)imageFromPixelBuffer:(CVPixelBufferRef)pixelBufferRef {
-
- CVPixelBufferLockBaseAddress(pixelBufferRef, 0);
-
- float width = CVPixelBufferGetWidth(pixelBufferRef);
- float height = CVPixelBufferGetHeight(pixelBufferRef);
-
- CIImage *ciImage = [CIImage imageWithCVPixelBuffer:pixelBufferRef];
-
- CIContext *temporaryContext = [CIContext contextWithOptions:nil];
- CGImageRef videoImage = [temporaryContext
- createCGImage:ciImage
- fromRect:CGRectMake(0, 0,
- width,
- height)];
-
- UIImage *image = [UIImage imageWithCGImage:videoImage];
- CGImageRelease(videoImage);
- CVPixelBufferUnlockBaseAddress(pixelBufferRef, 0);
-
- return image;
- }
- + (UIImage *)imageFromPixelBuffer2:(CVPixelBufferRef)pixelBufferRef {
- CVPixelBufferLockBaseAddress(pixelBufferRef, 0);
-
- float width = CVPixelBufferGetWidth(pixelBufferRef);
- float height = CVPixelBufferGetHeight(pixelBufferRef);
- CIImage *ciImage = [CIImage imageWithCVPixelBuffer:pixelBufferRef];
-
- CIContext *temporaryContext = [CIContext contextWithOptions:nil];
- CGImageRef videoImage = [temporaryContext
- createCGImage:ciImage
- fromRect:CGRectMake(0, 0,
- width,
- height)];
-
- UIImage *image = [UIImage imageWithCGImage:videoImage];
- CGImageRelease(videoImage);
- CVPixelBufferUnlockBaseAddress(pixelBufferRef, 0);
-
- return image;
- }
- /**
- 获取屏幕截图
- @return 返回屏幕截图
- */
-
- //+(UIImage *)fullScreenshots{
- // UIWindow *screenWindow = [[UIApplication sharedApplication] keyWindow];
- // UIGraphicsBeginImageContext(screenWindow.frame.size);//全屏截图,包括window
- // [screenWindow.layer renderInContext:UIGraphicsGetCurrentContext()];
- // UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
- // return viewImage;
- //}
- + (UIImage *)fullScreenshots
- {
- CGSize imageSize = CGSizeZero;
- UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
- if (UIInterfaceOrientationIsPortrait(orientation)) {
- imageSize = [UIScreen mainScreen].bounds.size;
- } else {
- imageSize = CGSizeMake([UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width);
- }
- // 传入的View.frame.size是0的话,直接返回nil,防止 UIGraphicsBeginImageContext() 传入0,导致崩溃
- if (CGSizeEqualToSize(imageSize, CGSizeZero)) {
- return nil;
- }
- UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
- CGContextRef context = UIGraphicsGetCurrentContext();
- for (UIWindow *window in [[UIApplication sharedApplication] windows]) {
- CGContextSaveGState(context);
- CGContextTranslateCTM(context, window.center.x, window.center.y);
- CGContextConcatCTM(context, window.transform);
- CGContextTranslateCTM(context, -window.bounds.size.width * window.layer.anchorPoint.x, -window.bounds.size.height * window.layer.anchorPoint.y);
- if (orientation == UIInterfaceOrientationLandscapeLeft) {
- CGContextRotateCTM(context, M_PI_2);
- CGContextTranslateCTM(context, 0, -imageSize.width);
- } else if (orientation == UIInterfaceOrientationLandscapeRight) {
- CGContextRotateCTM(context, -M_PI_2);
- CGContextTranslateCTM(context, -imageSize.height, 0);
- } else if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
- CGContextRotateCTM(context, M_PI);
- CGContextTranslateCTM(context, -imageSize.width, -imageSize.height);
- }
- if ([window respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)]) {
- [window drawViewHierarchyInRect:window.bounds afterScreenUpdates:YES];
- } else {
- [window.layer renderInContext:context];
- }
- CGContextRestoreGState(context);
- }
- UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
- UIGraphicsEndImageContext();
- return image;
- }
- /**
- 获取点击的颜色
- @param point 点击的位置
- @return 返回点击地方的颜色
- */
- +(UIColor*)getPixelColorScreenWindowAtLocation:(CGPoint)point{
- UIColor* color = nil;
- UIImage *image = [self fullScreenshots];
- CGImageRef inImage = image.CGImage;
- // Create off screen bitmap context to draw the image into. Format ARGB is 4 bytes for each pixel: Alpa, Red, Green, Blue
- CGContextRef cgctx = [self createARGBBitmapContextFromImage:inImage];
- if (cgctx == NULL) { return nil; }
- size_t w = CGImageGetWidth(inImage);
- size_t h = CGImageGetHeight(inImage);
- CGRect rect = {{0,0},{w,h}};
- // Draw the image to the bitmap context. Once we draw, the memory
- // allocated for the context for rendering will then contain the
- // raw image data in the specified color space.
- CGContextDrawImage(cgctx, rect, inImage);
- // Now we can get a pointer to the image data associated with the bitmap
- // context.
- unsigned char* data = CGBitmapContextGetData (cgctx);
- CGFloat scale = [UIScreen mainScreen].scale;
- if (data != NULL) {
- //offset locates the pixel in the data from x,y.
- //4 for 4 bytes of data per pixel, w is width of one row of data.
- @try {
- int offset = 4*((w*round(point.y * scale))+round(point.x * scale));
- int alpha = (int)data[offset];
- int red = (int)data[offset+1];
- int green = (int)data[offset+2];
- int blue = (int)data[offset+3];
- color = [UIColor colorWithRed:(red/255.0f) green:(green/255.0f) blue:(blue/255.0f) alpha:(alpha/255.0f)];
-
- free(data);
- }
- @catch (NSException * e) {
- NSLog(@"%@",[e reason]);
- }
- @finally {
- }
-
- }
-
-
- return color;
- }
- + (UIColor*) getColorImage:(UIImage *)image withPoint:(CGPoint)point{
- UIColor *color = nil;
-
- CGImageRef inImage = image.CGImage;
- // Create off screen bitmap context to draw the image into. Format ARGB is 4 bytes for each pixel: Alpa, Red, Green, Blue
- CGContextRef cgctx = [self createARGBBitmapContextFromImage:inImage];
- if (cgctx == NULL) { return nil; }
- size_t w = CGImageGetWidth(inImage);
- size_t h = CGImageGetHeight(inImage);
- CGRect rect = {{0,0},{w,h}};
- // Draw the image to the bitmap context. Once we draw, the memory
- // allocated for the context for rendering will then contain the
- // raw image data in the specified color space.
- CGContextDrawImage(cgctx, rect, inImage);
- // Now we can get a pointer to the image data associated with the bitmap
- // context.
- unsigned char* data = CGBitmapContextGetData (cgctx);
- CGFloat scale = [UIScreen mainScreen].scale;
- if (data != NULL) {
- //offset locates the pixel in the data from x,y.
- //4 for 4 bytes of data per pixel, w is width of one row of data.
- @try {
- int offset = 4*((w*round(point.y))+round(point.x));
- int alpha = (int)data[offset];
- int red = (int)data[offset+1];
- int green = (int)data[offset+2];
- int blue = (int)data[offset+3];
- color = [UIColor colorWithRed:(red/255.0f) green:(green/255.0f) blue:(blue/255.0f) alpha:(alpha/255.0f)];
-
- free(data);
- }
- @catch (NSException * e) {
- NSLog(@"%@",[e reason]);
- }
- @finally {
- }
-
- }
- return color;
- }
-
- +(CGContextRef) createARGBBitmapContextFromImage:(CGImageRef) inImage {
- CGContextRef context = NULL;
- CGColorSpaceRef colorSpace;
- void * bitmapData;
- int bitmapByteCount;
- int bitmapBytesPerRow;
- // Get image width, height. We'll use the entire image.
- size_t pixelsWide = CGImageGetWidth(inImage);
- size_t pixelsHigh = CGImageGetHeight(inImage);
- // Declare the number of bytes per row. Each pixel in the bitmap in this
- // example is represented by 4 bytes; 8 bits each of red, green, blue, and
- // alpha.
- bitmapBytesPerRow = (pixelsWide * 4);
- bitmapByteCount = (bitmapBytesPerRow * pixelsHigh);
- // Use the generic RGB color space.
- colorSpace = CGColorSpaceCreateDeviceRGB();
- if (colorSpace == NULL) {
- fprintf(stderr, "Error allocating color spacen");
- return NULL;
- }
- // Allocate memory for image data. This is the destination in memory
- // where any drawing to the bitmap context will be rendered.
- bitmapData = malloc( bitmapByteCount );
- if (bitmapData == NULL) {
- fprintf (stderr, "Memory not allocated!");
- CGColorSpaceRelease( colorSpace );
- return NULL;
- }
- // Create the bitmap context. We want pre-multiplied ARGB, 8-bits
- // per component. Regardless of what the source image format is
- // (CMYK, Grayscale, and so on) it will be converted over to the format
- // specified here by CGBitmapContextCreate.
- context = CGBitmapContextCreate (bitmapData,
- pixelsWide,
- pixelsHigh,
- 8, // bits per component
- bitmapBytesPerRow,
- colorSpace,
- kCGImageAlphaPremultipliedFirst);
- if (context == NULL) {
- free (bitmapData);
- fprintf (stderr, "Context not created!");
- }
- // Make sure and release colorspace before returning
- CGColorSpaceRelease( colorSpace );
- return context;
- }
- ////点击获取点击位置的颜色
- //-(IBAction)onClik:(UITapGestureRecognizer*)tap{
- // CGPoint point = [tap locationInView:self];
- // UIColor* color = [self getPixelColorAtLocation:point withImage:[self fullScreenshots]];
- //}
- @end
|