Domanda

My app has several methods partly based on this article.

Images, where I need to find the color at a location could come from the camera, the library, the app bundle, or generated within the app. I've just run into an issue where the order of the channels is different (it happens that the ones that are different are the ones generated by the app and saved in jpeg format for cache purposes).

So my question is, how, preferably using the link as a starting point, can I determine the color order of a CGImage? I'm sure this is documented somewhere, but where?

Using a method I've called +imageDump:, inspired by this article I extract the following information from one image:

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

and from another image, with the channels in a different order:

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

It seems like this information somehow specifies the channel order, but I don't know how to interpret these constants. Or am I looking at the wrong thing?

È stato utile?

Soluzione

I'm posting this answer mainly to answer a comment to my question. Here is the solution I used:

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

I seem to recall that it wasn't a complete solution but was sufficient for my own purposes.

Altri suggerimenti

You need to use the CGImageGetAlphaInfo, CGImageGetBitmapInfo, CGImageGetBitsPerComponent, and CGImageGetBitsPerPixel functions to determine the layout of the data. The combination of the values will allow you to determine what components there are, their size, and their order.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top