简体   繁体   English

如何检测图像是灰度的

[英]How to detect image is grayscale

I need to determine whether the image is grayscale (contains only black, white or shades of grey) or contains any color. 我需要确定图像是灰度(仅包含黑色,白色或灰色阴影)还是包含任何颜色。

What libraries should I use for this? 我应该使用哪些库?

This information is present in any CGImageRef object. 此信息存在于任何CGImageRef对象中。 You can get this object from any UIImage . 您可以从任何UIImage获取此对象。 In particular, the thing you would be interested in is CGImageGetColorSpace . 特别是,您感兴趣的是CGImageGetColorSpace Once you have that, you can call CGColorSpaceGetNumberOfComponents on the color space. 完成后,可以在颜色空间上调用CGColorSpaceGetNumberOfComponents There should only be three possibilities 应该只有三种可能性

CGColorSpaceGetNumberOfComponents returns 1: This image is grayscale, finished (one exception: It could be alpha-only, but I doubt you'll be sending any images like that. If you are, there is a way to determine whether an image is alpha only through its CGAlphaInfo ) CGColorSpaceGetNumberOfComponents返回1:这个图像是灰度,完成(一个例外:它可能只有alpha,但我怀疑你会发送任何类似的图像。如果你是,有一种方法可以确定图像是否只有alpha通过它的CGAlphaInfo

CGColorSpaceGetNumberOfComponents returns 3: This image is RGB, and further analysis is needed to determine if it is grayscale or not (as the other answer states, loop over the pixels and if you find one where !(R == G == B) then it is not grayscale. CGColorSpaceGetNumberOfComponents返回3:这个图像是RGB,需要进一步分析以确定它是否是灰度(正如其他答案所述,循环像素,如果你找到一个在哪里!(R == G == B)那么它不是灰度。

CGColorSpaceGetNumberOfComponents returns 4: This image is CMYK, and further analysis is needed. CGColorSpaceGetNumberOfComponents返回4:此图像为CMYK,需要进一步分析。 All grayscales in CMYK should be C == M == Y (usually they will be 0, as anything otherwise would be a waste of ink [this format was developed specifically with printers in mind]) with K equal to any value. CMYK中的所有灰度应为C == M == Y(通常它们将为0,否则将浪费墨水[此格式是专门针对打印机开发的]),K等于任何值。

CGColorSpaceGetNumberOfComponents returns something else: ...well...cry CGColorSpaceGetNumberOfComponents返回其他内容:......好吧......哭

UPDATE UPDATE

As pointed out in the comments, there is a more convenient function for figuring out the color model. 正如评论中指出的那样,有一个更方便的功能来确定颜色模型。 CGColorSpaceGetModel will return values like kCGColorSpaceModelMonochrome or kCGColorSpaceModelRGB . CGColorSpaceGetModel将返回kCGColorSpaceModelMonochromekCGColorSpaceModelRGB This will take the ambiguity out of the above. 这将带来上述模糊性。 After that you can check the same way for RGB or CMYK. 之后,您可以检查RGB或CMYK的相同方式。

Here is @borrrden answer in code: 这是代码中的@borrrden答案:

- (BOOL)isGrayScale{
    CGImageRef imageRef = [self CGImage];
    CGColorSpaceRef colorSpace = CGImageGetColorSpace(imageRef);
    if (CGColorSpaceGetModel(colorSpace) == kCGColorSpaceModelRGB) {
        CGDataProviderRef dataProvider = CGImageGetDataProvider(imageRef);
        CFDataRef imageData = CGDataProviderCopyData(dataProvider);
        const UInt8 *rawData = CFDataGetBytePtr(imageData);

        size_t width = CGImageGetWidth(imageRef);
        size_t height = CGImageGetHeight(imageRef);

        int byteIndex = 0;
        BOOL allPixelsGrayScale = YES;
        for(int ii = 0 ; ii <width*height; ++ii)
        {
            int r = rawData[byteIndex];
            int g = rawData[byteIndex+1];
            int b = rawData[byteIndex+2];
            if (!((r == g)&&(g == b))) {
                allPixelsGrayScale = NO;
                break;
            }
            byteIndex += 4;
        }
        CFRelease(imageData);
        CGColorSpaceRelease(colorSpace);
        return allPixelsGrayScale;
    }
    else if (CGColorSpaceGetModel(colorSpace) == kCGColorSpaceModelMonochrome){
        CGColorSpaceRelease(colorSpace); return YES;}
    else {CGColorSpaceRelease(colorSpace); return NO;}
}

The concept behind the grayscale is that for a pixel with Red, Green and Blue values, if the Amount of Red = Amount of Green = Amount of Blue , then you have an pixel with grayscale. 灰度背后的概念是对于具有红色,绿色和蓝色值的像素,如果Amount of Red = Amount of Green = Amount of Blue ,则您有一个带灰度的像素。 If all pixels of your image is under this condition, it means you have a grayscale bitmap. 如果图像的所有像素都处于此条件下,则表示您具有灰度位图。

So, everything you gotta do is to loop over the RGB values of your bitmap. 所以,你要做的就是循环遍历位图的RGB值。 On iOS you can access the pixels of your image using the code below. 在iOS上,您可以使用下面的代码访问图像的像素。

CFDataRef pixelData = CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));
const UInt8 * data = CFDataGetBytePtr(pixelData);

Swift Version of approved answer Swift版本的批准答案

extension UIImage {
    func isGrayScale() -> Bool {
        let imageRef = self.cgImage
        let colorSpace = imageRef?.colorSpace
        if colorSpace?.model == .rgb {
            let dataProvider = imageRef?.dataProvider
            let imageData = dataProvider?.data
            let rawData = CFDataGetBytePtr(imageData!)
            let width = imageRef?.width
            let height = imageRef?.height

            var byteIndex = 0
            var allPixelsGrayScale = true
            for _ in 0...width!*height! {
                let red = rawData![byteIndex]
                let green = rawData![byteIndex + 1]
                let blue = rawData![byteIndex + 2]
                if !((red == green) && (green == blue)) {
                    allPixelsGrayScale = false
                    break
                }
                byteIndex += 4
            }
            return allPixelsGrayScale
        } else if colorSpace?.model == .monochrome {
            return true
        }
        return false
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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