代码之家  ›  专栏  ›  技术社区  ›  Victor Engel

从图像文件中确定颜色顺序

  •  1
  • Victor Engel  · 技术社区  · 11 年前

    我的应用程序有几种方法,部分基于 this article .

    我需要在某个位置找到颜色的图像可以来自相机、库、应用程序包,也可以在应用程序中生成。我刚刚遇到一个问题,通道的顺序不同(碰巧不同的是由应用程序生成并以jpeg格式保存以用于缓存的通道)。

    所以我的问题是,最好以链接为起点,如何确定CGImage的颜色顺序?我确信这是在某个地方记录的,但在哪里?

    使用我称之为+imageDump:的方法,灵感来自 this article 我从一张图片中提取了以下信息:

    CGImageGetHeight: 120
    CGImageGetWidth:  120
    CGImageGetColorSpace: <CGColorSpace 0x1c562050> (kCGColorSpaceDeviceRGB)
    CGImageGetBitsPerPixel:     32
    CGImageGetBitsPerComponent: 8
    CGImageGetBytesPerRow:      480
    CGImageGetBitmapInfo: 0x00002002
      kCGBitmapAlphaInfoMask     = YES
      kCGBitmapFloatComponents   = NO
      kCGBitmapByteOrderMask     = YES
      kCGBitmapByteOrderDefault  = NO
      kCGBitmapByteOrder16Little = NO
      kCGBitmapByteOrder32Little = YES
      kCGBitmapByteOrder16Big    = YES
      kCGBitmapByteOrder32Big    = NO
    

    以及从另一个图像,其中通道以不同的顺序:

    CGImageGetHeight: 120
    CGImageGetWidth:  120
    CGImageGetColorSpace: <CGColorSpace 0x1c562050> (kCGColorSpaceDeviceRGB)
    CGImageGetBitsPerPixel:     32
    CGImageGetBitsPerComponent: 8
    CGImageGetBytesPerRow:      480
    CGImageGetBitmapInfo: 0x00000001
      kCGBitmapAlphaInfoMask     = YES
      kCGBitmapFloatComponents   = NO
      kCGBitmapByteOrderMask     = NO
      kCGBitmapByteOrderDefault  = NO
      kCGBitmapByteOrder16Little = NO
      kCGBitmapByteOrder32Little = NO
      kCGBitmapByteOrder16Big    = NO
      kCGBitmapByteOrder32Big    = NO
    

    这些信息似乎以某种方式指定了通道顺序,但我不知道如何解释这些常量。还是我看错了东西?

    2 回复  |  直到 8 年前
        1
  •  2
  •   Victor Engel    10 年前

    我发布这个答案主要是为了回答对我的问题的评论。这是我使用的解决方案:

    - (UIColor*)colorFromImage:(UIImage*)image sampledAtPoint:(CGPoint)p {
       // from http://stackoverflow.com/questions/144250/how-to-get-the-rgb-values-for-a-pixel-on-an-image-on-the-iphone
       //DLog(@"Image dump call from colorFromImage:sampledAtPoint:");
       //[Utilities imageDump:image];
       int radius = 3;
       CGImageRef cgImage = [image CGImage];
       CGDataProviderRef provider = CGImageGetDataProvider(cgImage);
       CFDataRef bitmapData = CGDataProviderCopyData(provider);
       const UInt8* data = CFDataGetBytePtr(bitmapData);
       size_t bytesPerRow = CGImageGetBytesPerRow(cgImage);
       size_t width = CGImageGetWidth(cgImage);
       size_t height = CGImageGetHeight(cgImage);
       CGBitmapInfo info = CGImageGetBitmapInfo(cgImage);
    
       long col = p.x*(width-1);
       long row = p.y*(height-1);
       long cnt = 0;long redval=0,greenval=0,blueval=0;
       for (int rrow = row - radius; rrow < row + radius; rrow++) {
          for (int ccol = col - radius; ccol < col + radius; ccol++) {
             if ((rrow >= 0) && (ccol >= 0)) {
                if ((rrow < height) && (ccol < width)) {
                   const UInt8* pixel = data + rrow*bytesPerRow+ccol*4;
                   int tempred,tempgreen,tempblue,tempalpha;
                   if (info & kCGBitmapByteOrder32Little) {
                      tempred = pixel[2];
                      tempgreen = pixel[1];
                      tempblue = pixel[0];
                      tempalpha = pixel[3];
                   } else {
                      tempred = pixel[0];
                      tempgreen = pixel[1];
                      tempblue = pixel[2];
                      tempalpha = pixel[3];
                   }
                   //DLog(@"%d %d %d %d",tempred,tempgreen,tempblue,tempalpha);
                   if (tempalpha==255) {
                      redval += tempred;
                      greenval += tempgreen;
                      blueval += tempblue;
                      cnt++;
                   }
                }
             }
          }
       }
       UIColor *returnColor = [UIColor colorWithRed:1.0f*redval/(cnt*255) green:1.0f*greenval/(cnt*255) blue:1.0f*blueval/(cnt*255) alpha:1.0];
       CFRelease(bitmapData);//take care of memory leak
       return returnColor;
    }
    

    我似乎记得这不是一个完整的解决方案,但对我自己来说已经足够了。

        2
  •  0
  •   rmaddy    11 年前

    您需要使用 CGImageGetAlphaInfo , CGImageGetBitmapInfo , CGImageGetBitsPerComponent CGImageGetBitsPerPixel 函数来确定数据的布局。这些值的组合将允许您确定有哪些组件、它们的大小和顺序。