草庐IT

ios - 确定 UIImage 的主要颜色和次要颜色

coder 2023-09-24 原文

我想知道是否有人可以帮我弄清楚如何确定 UIImage 中的主要原色和次色。我在 Google 中找不到任何非常有用的东西。

最佳答案

基于上面的 Panic 博客,这是一个快速的方法(<10ms>

获取 UIImage 输入和输出:

  • 背景色
  • 原色
  • 辅助色

将 UIImage 传递给方法时,还要传递一个“边缘”。这是指图像的哪一部分暴露给 View 的其余部分(请参见下图了解详情):

  • edge = 0 = top
  • 边 = 1 = 左
  • 边缘 = 2 = 底部
  • 边 = 3 = 右

**

第一步。

** 设置维度。这是指图像的横向和向下应该有多少像素。

第 2 步。根据尺寸输入调整图像大小(例如 20 x 20 = 400 像素)。

第 3 步。 创建一个颜色数组,从第 2 步中创建的原始数据中提取 RGB 值。另外收集沿所选边缘运行的像素。

第 4 步。 计算边缘或背景颜色。根据 Panic 博客,这稍后用于对比强调色。

第 5 步。检查收集的颜色(RGB 值)并确定它们是否与边缘/背景颜色充分对比。如果他们不这样做,则所需的最低对比度会降低。此外,对于每个颜色对象,设置它与其他颜色的“距离”。这是对颜色与图像中其他颜色的相似程度的粗略估计。

第 6 步。 按距离对重音进行排序(距离最短意味着最相似),最相似的颜色出现在顶部。将最常出现的颜色设置为主色。

第 7 步。检查剩余的颜色并确定与原色的对比最大的颜色。然后设置你的辅助颜色。

警告:我确信该方法可以改进,但这是一个快速的起点。例如,您可以确定图像右上角或左上角像素的颜色(通常放置后退图标等的位置),并为那里的图标建议对比色。

代码如下:

-(NSDictionary *)coloursForImage:(UIImage *)image forEdge:(int)edge {

    NSLog(@"start");

    //1. set vars
    float dimension = 20;

    //2. resize image and grab raw data
    //this part pulls the raw data from the image
    CGImageRef imageRef = [image CGImage];
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    unsigned char *rawData = (unsigned char*) calloc(dimension * dimension * 4, sizeof(unsigned char));
    NSUInteger bytesPerPixel = 4;
    NSUInteger bytesPerRow = bytesPerPixel * dimension;
    NSUInteger bitsPerComponent = 8;
    CGContextRef context = CGBitmapContextCreate(rawData, dimension, dimension, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGColorSpaceRelease(colorSpace);
    CGContextDrawImage(context, CGRectMake(0, 0, dimension, dimension), imageRef);
    CGContextRelease(context);

    //3. create colour array
    NSMutableArray * colours = [NSMutableArray new];
    float x = 0, y = 0; //used to set coordinates
    float eR = 0, eB = 0, eG = 0; //used for mean edge colour
    for (int n = 0; n<(dimension*dimension); n++){

        Colour * c = [Colour new]; //create colour
        int i = (bytesPerRow * y) + x * bytesPerPixel; //pull index
        c.r = rawData[i]; //set red
        c.g = rawData[i + 1]; //set green
        c.b = rawData[i + 2]; //set blue
        [colours addObject:c]; //add colour

        //add to edge if true
        if ((edge == 0 && y == 0) || //top
            (edge == 1 && x == 0) || //left
            (edge == 2 && y == dimension-1) || //bottom
            (edge == 3 && x == dimension-1)){ //right
            eR+=c.r; eG+=c.g; eB+=c.b; //add the colours
        }

        //update pixel coordinate
        x = (x == dimension - 1) ? 0 : x+1;
        y = (x == 0) ? y+1 : y;

    }
    free(rawData);

    //4. calculate edge colour
    Colour * e = [Colour new];
    e.r = eR/dimension;
    e.g = eG/dimension;
    e.b = eB/dimension;

    //5. calculate the frequency of colour
    NSMutableArray * accents = [NSMutableArray new]; //holds valid accents

    float minContrast = 3.1; //play with this value
    while (accents.count < 3) { //minimum number of accents
        for (Colour * a in colours){

            //NSLog(@"contrast value is %f", [self contrastValueFor:a andB:e]);

            //5.1 ignore if it does not contrast with edge
            if ([self contrastValueFor:a andB:e] < minContrast){ continue;}

            //5.2 set distance (frequency)
            for (Colour * b in colours){
                a.d += [self colourDistance:a andB:b];
            }

            //5.3 add colour to accents
            [accents addObject:a];
        }

        minContrast-=0.1f;
    }

    //6. sort colours by the most common
    NSArray * sorted = [[NSArray arrayWithArray:accents] sortedArrayUsingDescriptors:@[[[NSSortDescriptor alloc] initWithKey:@"d" ascending:true]]];

    //6.1 set primary colour (most common)
    Colour * p = sorted[0];

    //7. get most contrasting colour
    float high = 0.0f; //the high
    int index = 0; //the index
    for (int n = 1; n < sorted.count; n++){

        Colour * c = sorted[n];
        float contrast = [self contrastValueFor:c andB:p];
        //float sat = [self saturationValueFor:c andB:p];

        if (contrast > high){
            high = contrast;
            index = n;
        }
    }
    //7.1 set secondary colour (most contrasting)
    Colour * s = sorted[index];

    NSLog(@"er %i eg %i eb %i", e.r, e.g, e.b);
    NSLog(@"pr %i pg %i pb %i", p.r, p.g, p.b);
    NSLog(@"sr %i sg %i sb %i", s.r, s.g, s.b);

    NSMutableDictionary * result = [NSMutableDictionary new];
    [result setValue:[UIColor colorWithRed:e.r/255.0f green:e.g/255.0f blue:e.b/255.0f alpha:1.0f] forKey:@"background"];
    [result setValue:[UIColor colorWithRed:p.r/255.0f green:p.g/255.0f blue:p.b/255.0f alpha:1.0f] forKey:@"primary"];
    [result setValue:[UIColor colorWithRed:s.r/255.0f green:s.g/255.0f blue:s.b/255.0f alpha:1.0f] forKey:@"secondary"];

    NSLog(@"end");
    return result;

}
-(float)contrastValueFor:(Colour *)a andB:(Colour *)b {
    float aL = 0.2126 * a.r + 0.7152 * a.g + 0.0722 * a.b;
    float bL = 0.2126 * b.r + 0.7152 * b.g + 0.0722 * b.b;
    return (aL>bL) ? (aL + 0.05) / (bL + 0.05) : (bL + 0.05) / (aL + 0.05);
}
-(float)saturationValueFor:(Colour *)a andB:(Colour *)b {
    float min = MIN(a.r, MIN(a.g, a.b)); //grab min
    float max = MAX(b.r, MAX(b.g, b.b)); //grab max
    return (max - min)/max;
}
-(int)colourDistance:(Colour *)a andB:(Colour *)b {
    return abs(a.r-b.r)+abs(a.g-b.g)+abs(a.b-b.b);
}

Color 对象是一个简单的自定义类:

@interface Colour : NSObject
@property int r, g, b, d;
@end

关于ios - 确定 UIImage 的主要颜色和次要颜色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15962893/

有关ios - 确定 UIImage 的主要颜色和次要颜色的更多相关文章

  1. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  2. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  3. ruby - 即时确定方法的可见性 - 2

    我正在编写一个方法,它将在一个类中定义一个实例方法;类似于attr_accessor:classFoocustom_method(:foo)end我通过将custom_method函数添加到Module模块并使用define_method定义方法来实现它,效果很好。但我无法弄清楚如何考虑类(class)的可见性属性。例如,在下面的类中classFoocustom_method(:foo)privatecustom_method(:bar)end第一个生成的方法(foo)必须是公共(public)的,第二个(bar)必须是私有(private)的。我怎么做?或者,如何找到调用我的cust

  4. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  5. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  6. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  7. ruby 诅咒颜色 - 2

    如何使用Ruby的默认Curses库获取颜色?所以像这样:puts"\e[0m\e[30;47mtest\e[0m"效果很好。在浅灰色背景上呈现漂亮的黑色。但是这个:#!/usr/bin/envrubyrequire'curses'Curses.noecho#donotshowtypedkeysCurses.init_screenCurses.stdscr.keypad(true)#enablearrowkeys(forpageup/down)Curses.stdscr.nodelay=1Curses.clearCurses.setpos(0,0)Curses.addstr"Hello

  8. ruby - Rails 3 的 RGB 颜色选择器 - 2

    状态:我正在构建一个应用程序,其中需要一个可供用户选择颜色的字段,该字段将包含RGB颜色代码字符串。我已经测试了一个看起来很漂亮但效果不佳的。它是“挑剔的颜色”,并托管在此存储库中:https://github.com/Astorsoft/picky-color.在这里我打开一个关于它的一些问题的问题。问题:请建议我在Rails3应用程序中使用一些颜色选择器。 最佳答案 也许页面上的列表jQueryUIDevelopment:ColorPicker为您提供开箱即用的产品。原因是jQuery现在包含在Rails3应用程序中,因此使用基

  9. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  10. ruby - 确定 ruby​​ 脚本是否已经在运行 - 2

    有没有一种简单的方法可以判断ruby​​脚本是否已经在运行,然后适本地处理它?例如:我有一个名为really_long_script.rb的脚本。我让它每5分钟运行一次。当它运行时,我想看看之前运行的是否还在运行,然后停止第二个脚本的执行。有什么想法吗? 最佳答案 ps是一种非常糟糕的方法,并且可能会出现竞争条件。传统的Unix/Linux方法是将PID写入文件(通常在/var/run中)并在启动时检查该文件是否存在。例如pid文件位于/var/run/myscript.pid然后你会在运行程序之前检查它是否存在。有一些技巧可以避免

随机推荐