【问题标题】:Determining color order from an image file从图像文件中确定颜色顺序
【发布时间】:2013-10-01 17:03:03
【问题描述】:

我的应用有几种方法,部分基于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

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

【问题讨论】:

  • 你发现了吗?我无法确定我的像素是 ARGB、RGBA、RGB、BGR、BGRA 等。
  • 对不起,我已经很久没有参与这个项目了,我不记得我做了什么。不过,快速浏览一下引用这篇堆栈溢出文章的代码。也许它会帮助你。 stackoverflow.com/questions/144250/…仅供参考,我添加了自己的答案主要是为了回答您的问题。

标签: ios cgimage


【解决方案1】:

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

- (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;
}

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

【讨论】:

  • 在判断它是 BGRA 还是 RGBA 的 if 条件下,你有 info &amp; kCGBitmapByteOrder32Little -- 你的意思是 (bitmapInfo &amp; kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Little 吗?
  • 没有变量名bitmapInfo。但是,有一个变量名 info,它是 CGBitmapInfo 类型。
  • 抱歉,我在评论的第一个 sn-p 中将其命名正确,但在第二个 sn-p 中拼写错误。应该读过:(info &amp; kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Little)——所以我的问题是你不需要在掩码上使用按位运算符,然后将其与常量进行比较以检查条件吗?
  • 嗯——我不这么认为。我认为 kCGBitmapByteOrder32Little 常量只能解析为一位。因此,与任何事情都只是一点点。我们只是检查位的值是什么。您的检查首先从信息中提取掩码,然后检查它是否与常量匹配。它通过两步而不是一步得出相同的结论。
  • 啊...我认为我的问题是我将按位运算的结果存储到 BOOL 中,以便我可以给它一个有意义的变量名来描述其使用背后的意图。转换为 BOOL 真是太棒了。谢谢!
【解决方案2】:

您需要使用CGImageGetAlphaInfoCGImageGetBitmapInfoCGImageGetBitsPerComponentCGImageGetBitsPerPixel 函数来确定数据的布局。这些值的组合将允许您确定存在哪些组件、它们的大小和它们的顺序。

【讨论】:

  • 对。我正在查看该信息,但我不确定如何解释它。我会用详细信息更新我的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-01-16
  • 1970-01-01
  • 1970-01-01
  • 2015-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多