Ios 为什么查询HSB值与绘制HSB值不同?

Ios 为什么查询HSB值与绘制HSB值不同?,ios,rgb,uicolor,hsb,Ios,Rgb,Uicolor,Hsb,首先,我创建此实用程序是为了调试我的情况: +(NSString *)hsbaFromColor:(UIColor *)c { CGFloat hue, saturation, brightness, alpha; NSString *returnValue; if ([c getHue:&hue saturation:&saturation brightness:&brightness alpha:&alpha]) { return

首先,我创建此实用程序是为了调试我的情况:

+(NSString *)hsbaFromColor:(UIColor *)c
{
   CGFloat hue, saturation, brightness, alpha;
   NSString *returnValue;
   if ([c getHue:&hue saturation:&saturation brightness:&brightness alpha:&alpha]) {
      returnValue = [NSString stringWithFormat:@"H:%f S:%f B:%f A:%f",hue,saturation,brightness,alpha];
   }
   return returnValue;
}
此实用程序用于确认我在读取刚绘制的值时没有获得预期的数据集。我希望得到与刚才绘制的值匹配的值。以下是图纸代码:

CGContextSetLineCap(self.context, kCGLineCapRound);
CGContextSetStrokeColorWithColor(self.context, ant.color.CGColor);
CGContextSetLineWidth(self.context, ant.size.width*1.0);
CGContextMoveToPoint(self.context, ant.previousLocation.x, ant.previousLocation.y);
CGContextAddLineToPoint(self.context, ant.location.x, ant.location.y);
CGContextStrokePath(self.context);
NSLog(@"Draw color: %@",[ColorTools hsbaFromColor:ant.color]);
UIColor *colorJustDrawn = [self getColorFromContextAtPosition:ant.location];
NSLog(@"Read color: %@",[ColorTools hsbaFromColor:colorJustDrawn]);
self.lightColor = [UIColor colorWithHue:hue saturation:saturation brightness:1.0 alpha:1.0];
在我的测试用例中,ant.size.width是5。这会产生一条足够宽的线,当我查询颜色时,我会得到相同的颜色。以下是查询颜色的方法:

-(UIColor *)getColorFromContextAtPosition:(CGPoint)p
{
   if (p.x < self.minX) {
      self.minX = p.x;
   }
   if (p.x > self.maxX) {
      self.maxX = p.x;
   }
   if (p.y < self.minY) {
      self.minY = p.y;
   }
   if (p.y > self.maxY) {
      self.maxY = p.y;
   }
   CGFloat screenScale = [[UIScreen mainScreen] scale];
   CGSize contextSize;
   contextSize.width = CGBitmapContextGetWidth(self.context);
   contextSize.height = CGBitmapContextGetHeight(self.context);
   unsigned char* data = CGBitmapContextGetData (self.context);
   UIColor *color = [UIColor whiteColor];
   if (data != NULL) {
        //offset locates the pixel in the data from x,y.
        //4 for 4 bytes of data per pixel, w is width of one row of data.
        int offset = 4*((contextSize.width*floorf(p.y*screenScale))+floorf(p.x*screenScale));
        int alpha =  data[offset+3];
        int red = data[offset+0];
        int green = data[offset+1];
        int blue = data[offset+2];
        color = [UIColor colorWithRed:(red/255.0f) green:(green/255.0f) blue:(blue/255.0f) alpha:(alpha/255.0f)];
   }
   return color;
}
这是一些数据的样本。该应用程序选择随机颜色,通过在每次需要新颜色时添加黄金比例来交替色调,然后将其规格化为0..1。在我刚才的跑步中,创建的颜色是:

H:0.537255 S:0.598039 B:1.000000 A:1.000000
使用以下代码创建:

CGContextSetLineCap(self.context, kCGLineCapRound);
CGContextSetStrokeColorWithColor(self.context, ant.color.CGColor);
CGContextSetLineWidth(self.context, ant.size.width*1.0);
CGContextMoveToPoint(self.context, ant.previousLocation.x, ant.previousLocation.y);
CGContextAddLineToPoint(self.context, ant.location.x, ant.location.y);
CGContextStrokePath(self.context);
NSLog(@"Draw color: %@",[ColorTools hsbaFromColor:ant.color]);
UIColor *colorJustDrawn = [self getColorFromContextAtPosition:ant.location];
NSLog(@"Read color: %@",[ColorTools hsbaFromColor:colorJustDrawn]);
self.lightColor = [UIColor colorWithHue:hue saturation:saturation brightness:1.0 alpha:1.0];
色调和饱和度的值在ant初始化时创建,但在对象的整个生命周期中保持不变。在任何情况下,以下是使用屏幕上显示为浅青蓝的颜色绘制和查询的输出:

Draw color: H:0.537255 S:0.598039 B:0.995069 A:1.000000
Draw color: R:0.399979 G:0.862049 B:0.995069 A:1.000000

Read color: H:0.129386 S:0.598425 B:0.996078 A:1.000000
Read color: R:0.996078 G:0.862745 B:0.400000 A:1.000000

嗯,现在我看,似乎有一个endian问题。看起来红色和蓝色是向后的。

更改此方法可以解决问题

-(UIColor *)getColorFromContextAtPosition:(CGPoint)p
{
   if (p.x < self.minX) {
      self.minX = p.x;
   }
   if (p.x > self.maxX) {
      self.maxX = p.x;
   }
   if (p.y < self.minY) {
      self.minY = p.y;
   }
   if (p.y > self.maxY) {
      self.maxY = p.y;
   }
   CGFloat screenScale = [[UIScreen mainScreen] scale];
   CGSize contextSize;
   contextSize.width = CGBitmapContextGetWidth(self.context);
   contextSize.height = CGBitmapContextGetHeight(self.context);
   unsigned char* data = CGBitmapContextGetData (self.context);
   UIColor *color = [UIColor whiteColor];
   if (data != NULL) {
        //offset locates the pixel in the data from x,y.
        //4 for 4 bytes of data per pixel, w is width of one row of data.
        int offset = 4*((contextSize.width*floorf(p.y*screenScale))+floorf(p.x*screenScale));
        int alpha =  data[offset+3];
        int red = data[offset+2];       //Note red and blue are reversed.
        int green = data[offset+1];
        int blue = data[offset+0];      //
        color = [UIColor colorWithRed:(red/255.0f) green:(green/255.0f) blue:(blue/255.0f) alpha:(alpha/255.0f)];
   }
   return color;
}
我不记得我是从哪里想到这个代码的。不管是什么,阿尔法通道也在另一端。当我移动alpha通道时,我也应该检查其他通道,但我没有


如果有人决定借用此代码,您应该知道设备上的通道顺序与模拟器中的不同。我现在要寻找的是一种方法,可以告诉你合适的顺序是什么。

你用什么颜色空间来表示各种颜色?我没有做任何特定于颜色空间的事情。我假设iOS使用的默认空间就是整个过程中使用的空间。我已经为blankOutImageView添加了代码,它创建了我使用的上下文。到目前为止,我还没有处理过iOS上的颜色空间。我在想也许这就是我遇到的,但我不确定在哪里设置颜色空间。啊,我想的是NSColor,不是UIColor。我不认为颜色使用颜色空间。也可能是HSB之间的转换是不可逆的。也许其中一个色域比另一个更宽?RGB颜色也不匹配。也许我的颜色查询方法有错误。我将在一分钟内更新这个问题,提供更多细节和一些输出。啊哈。这是频道的顺序。如果我能在getColorFromContextAtPosition中添加一些东西,也许可以得到一个可接受的答案:告诉我读取频道的顺序。如何判断上下文是否使用RGB或BGR等?