8

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.

Sergio
  • 28,539
  • 11
  • 85
  • 132
nutsmuggler
  • 1,707
  • 5
  • 21
  • 27

6 Answers6

5

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>
rmaddy
  • 314,917
  • 42
  • 532
  • 579
Aniket Kote
  • 541
  • 3
  • 9
2

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.

petert
  • 6,672
  • 3
  • 38
  • 46
2

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.

Mike Abdullah
  • 14,933
  • 2
  • 50
  • 75
1

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
}
mattdedek
  • 2,525
  • 2
  • 17
  • 19
0

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;
James Williams
  • 1,861
  • 1
  • 15
  • 21
-2

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
}
sebm
  • 1
  • 1
  • 1
    This isn't a solution. A png with no content (alpha 0 for everywhere) can still return a height and width – Allison Apr 24 '16 at 04:59