简体   繁体   中英

How to check if a uiimage is blank? (empty, transparent)

which is the best way to check whether a UIImage is blank?
I have this painting editor which returns a UIImage ; I don't want to save this image if there's nothing on it.

Try this code:

BOOL isImageFlag=[self checkIfImage:image];

And checkIfImage method:

- (BOOL) checkIfImage:(UIImage *)someImage {
    CGImageRef image = someImage.CGImage;
    size_t width = CGImageGetWidth(image);
    size_t height = CGImageGetHeight(image);
    GLubyte * imageData = malloc(width * height * 4);
    int bytesPerPixel = 4;
    int bytesPerRow = bytesPerPixel * width;
    int bitsPerComponent = 8;
    CGContextRef imageContext =
    CGBitmapContextCreate(
                          imageData, width, height, bitsPerComponent, bytesPerRow, CGImageGetColorSpace(image),
                          kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big
                          );

    CGContextSetBlendMode(imageContext, kCGBlendModeCopy);
    CGContextDrawImage(imageContext, CGRectMake(0, 0, width, height), image);
    CGContextRelease(imageContext);

    int byteIndex = 0;

    BOOL imageExist = NO;
    for ( ; byteIndex < width*height*4; byteIndex += 4) {
        CGFloat red = ((GLubyte *)imageData)[byteIndex]/255.0f;
        CGFloat green = ((GLubyte *)imageData)[byteIndex + 1]/255.0f;
        CGFloat blue = ((GLubyte *)imageData)[byteIndex + 2]/255.0f;
        CGFloat alpha = ((GLubyte *)imageData)[byteIndex + 3]/255.0f;
        if( red != 1 || green != 1 || blue != 1 || alpha != 1 ){
            imageExist = YES;
            break;
        }
    }

    free(imageData);        
    return imageExist;
}

You will have to add OpenGLES framework and import this in the .m file:

#import <OpenGLES/ES1/gl.h>

One idea would be to call UIImagePNGRepresentation to get an NSData object then compare it with a pre-defined 'empty' version - ie: call:

- (BOOL)isEqualToData:(NSData *)otherData

to test?

Not tried this on large data; might want to check performance, if your image data is quite large, otherwise if it's small it is probably just like calling memcmp() in C.

Something along these lines:

  1. Create a 1 px square CGContext
  2. Draw the image so it fills the context
  3. Test the one pixel of the context to see if it contains any data. If it's completely transparent, consider the picture blank

Others may be able to add more details to this answer.

Here's a solution in Swift that does not require any additional frameworks.

Thanks to answers in a related question here: Get Pixel Data of ImageView from coordinates of touch screen on xcode?

func imageIsEmpty(_ image: UIImage) -> Bool {
    guard let cgImage = image.cgImage,
          let dataProvider = cgImage.dataProvider else
    {
        return true
    }

    let pixelData = dataProvider.data
    let data: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)
    let imageWidth = Int(image.size.width)
    let imageHeight = Int(image.size.height)
    for x in 0..<imageWidth {
        for y in 0..<imageHeight {
            let pixelIndex = ((imageWidth * y) + x) * 4
            let r = data[pixelIndex]
            let g = data[pixelIndex + 1]
            let b = data[pixelIndex + 2]
            let a = data[pixelIndex + 3]
            if a != 0 {
                if r != 0 || g != 0 || b != 0 {
                    return false
                }
            }
        }
    }

    return true
}

I'm not at my Mac, so I can't test this (and there are probably compile errors). But one method might be:

//The pixel format depends on what sort of image you're expecting. If it's RGBA, this should work
typedef struct
{
   uint8_t red;
   uint8_t green;
   uint8_t blue;
   uint8_t alpha;
} MyPixel_T;

UIImage *myImage = [self doTheThingToGetTheImage];
CGImageRef myCGImage = [myImage CGImage];

//Get a bitmap context for the image
CGBitmapContextRef *bitmapContext = 
CGBitmapContextFreate(NULL, CGImageGetWidth(myCGImage), CGImageGetHeight(myCGImage), 
                      CGImageGetBitsPerComponent(myCGImage), CGImageGetBytesPerRow(myCGImage),
                      CGImageGetColorSpace(myCGImage), CGImageGetBitmapInfo(myCGImage));

//Draw the image into the context
CGContextDrawImage(bitmapContext, CGRectMake(0, 0, CGImageGetWidth(myCGImage), CGImageGetHeight(myCGImage)), myCGImage);

//Get pixel data for the image
MyPixel_T *pixels = CGBitmapContextGetData(bitmapContext);
size_t pixelCount = CGImageGetWidth(myCGImage) * CGImageGetHeight(myCGImage);

for(size_t i = 0; i < pixelCount; i++)
{
   MyPixel_T p = pixels[i];
   //Your definition of what's blank may differ from mine
   if(p.red > 0 && p.green > 0 && p.blue > 0 && p.alpha > 0)
      return NO;
}

return YES;

I just encountered the same problem. Solved it by checking the dimensions:

Swift example:

let image = UIImage()

let height = image.size.height
let width = image.size.height

if (height > 0 && width > 0) {
    // We have an image
} else {
    // ...and we don't
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM