17

問題があります。2 つの色を取り、それらから「仮想グラデーション」を作成できるようにする必要があります。次に、この行の任意の時点で色を見つけることができる必要があります。私の現在のアプローチはこれです:

if (fahrenheit < kBottomThreshold)
{
    return [UIColor colorWithRed:kBottomR/255.0f green:kBottomG/255.0f blue:kBottomB/255.0f alpha:1];
}
if (fahrenheit > kTopThreshold)
{
    return [UIColor colorWithRed:kTopR/255.0f green:kTopG/255.0f blue:kTopB/255.0f alpha:1];
}

double rDiff = kTopR - kBottomR;
double gDiff = kTopG - kBottomG;
double bDiff = kTopB - kBottomB;

double tempDiff = kTopThreshold - kBottomThreshold;

double rValue;
double gValue;
double bValue;

rValue = kBottomR + ((rDiff/tempDiff) * fahrenheit);
gValue = kBottomG + ((gDiff/tempDiff) * fahrenheit);
bValue = kBottomB + ((bDiff/tempDiff) * fahrenheit);

return [UIColor colorWithRed:rValue/255.0f green:gValue/255.0f blue:bValue/255.0f alpha:1];

変数:

  • fahrenheit色を見つけたいこの仮想線の番号である関数に渡される変数です。
  • kTopRkTopB、およびkTopGは、グラデーションの一方の端の RGB 値です。対応する相手も同じですkBottom
  • kBottomThresholdそしてkTopThreshold私のグラデーションのエンドポイントです。

ここに私の問題があります: グラデーションfahrenheitのどちらかの端を超えると、グラデーションは別の値に「ジャンプ」するようです。

S3 サーバーでホストされているサンプル プロジェクトをここに含めました。

プロジェクトをダウンロードし、シミュレーター/デバイスで試して、私が何を意味するかを確認する必要があります(非常に頭が良く、コードを見るだけでわかる場合を除きます)。

4

7 に答える 7

8

kBottomThreshold問題は、から減算していないことですfarenheit

しかし、単純化しましょう。

まず、入力温度をt[0...1]の範囲のパラメーターにマッピングします。次に、範囲[...]の出力、および範囲[ ... ]の出力、および範囲[ ... ]tの出力にマップします。kBottomRkTopRkBottomGkTopGkBottomBkTopB

UIColor *colorForDegreesFahrenheit(double fahrenheit) {
    double t = (fahrenheit - kBottomThreshold) / (kTopThreshold - kBottomThreshold);

    // Clamp t to the range [0 ... 1].
    t = MAX(0.0, MIN(t, 1.0));

    double r = kBottomR + t * (kTopR - kBottomR);
    double g = kBottomG + t * (kTopG - kBottomG);
    double b = kBottomB + t * (kTopB - kBottomB);

    return [UIColor colorWithRed:r/255 green:g/255 blue:b/255 alpha:1];
}
于 2013-02-22T20:32:29.040 に答える
4

グラデーションが 2 色のグラデーションよりも複雑な場合は、CGGradientRef を一時的な CGImageRef に描画し、画像バッファーから RGBA 値を直接読み取ることを検討してください。

ここでは、5 つのグラデーション ストップと色を使用する必要がありました。

    CGFloat tmpImagewidth = 1000.0f; // Make this bigger or smaller if you need more or less resolution (number of different colors).
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

    // create a gradient
    CGFloat locations[] = { 0.0,
        0.35,
        0.55,
        0.8,
        1.0 };
    NSArray *colors = @[(__bridge id) [UIColor redColor].CGColor,
                        (__bridge id) [UIColor greenColor].CGColor,
                        (__bridge id) [UIColor blueColor].CGColor,
                        (__bridge id) [UIColor yellowColor].CGColor,
                        (__bridge id) [UIColor redColor].CGColor,
                        ];
    CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef) colors, locations);
    CGPoint startPoint = CGPointMake(0, 0);
    CGPoint endPoint = CGPointMake(tmpImagewidth, 0);

    // create a bitmap context to draw the gradient to, 1 pixel high.
    CGContextRef context = CGBitmapContextCreate(NULL, tmpImagewidth, 1, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);

    // draw the gradient into it
    CGContextAddRect(context, CGRectMake(0, 0, tmpImagewidth, 1));
    CGContextClip(context);
    CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);

    // Get our RGB bytes into a buffer with a couple of intermediate steps...
    //      CGImageRef -> CFDataRef -> byte array
    CGImageRef cgImage = CGBitmapContextCreateImage(context);
    CGDataProviderRef provider = CGImageGetDataProvider(cgImage);
    CFDataRef pixelData = CGDataProviderCopyData(provider);

    // cleanup:
    CGGradientRelease(gradient);
    CGColorSpaceRelease(colorSpace);
    CGImageRelease(cgImage);
    CGContextRelease(context);

    const UInt8* data = CFDataGetBytePtr(pixelData);

    // we got all the data we need.
    // bytes in the data buffer are a succession of R G B A bytes

    // For instance, the color of the point 27% in our gradient is:
    CGFloat x = tmpImagewidth * .27;
    int pixelIndex = (int)x * 4; // 4 bytes per color
    UIColor *color = [UIColor colorWithRed:data[pixelIndex + 0]/255.0f
                                     green:data[pixelIndex + 1]/255.0f
                                      blue:data[pixelIndex + 2]/255.0f
                                     alpha:data[pixelIndex + 3]/255.0f];

    // done fetching color data, finally release the buffer
    CGDataProviderRelease(provider);

これが上記の回答の「数学的な方法」よりも優れていると言っているわけではありません。確かに、一時的なイメージの作成にはメモリと CPU の負担がかかります。ただし、これの利点は、必要なグラデーションストップの数に関係なく、コードの複雑さが変わらないことです...

于 2014-01-19T00:14:43.283 に答える