iOS获取图片区域主色的方法

之前的项目有这样的需求,有一个页面可以检索一块区域内图片的主色。效果图如图所示

下面是如何获取区域主色的实现思路:
首先,我们需要从相册,或者相机去获取图片;
其次,得到图片需要截取区域图片;
然后,获取截取图片的主色。
理想中是这样的,但是有很多阻碍,得到的图片需要自适应imageView(imageView的宽高是固定的),截图的得到的区域不是自己想要的区域。这里需要将图片等比例缩放,按照ImageView的宽高。

那现在就直接上代码吧!

首先我们需要等比例缩放Image:

/**
 *  缩放图片
 *
 *  @param img  image
 *  @param size 缩放后的大小
 *
 *  @return image
 */
+ (UIImage *)scaleToSize:(UIImage *)img size:(CGSize)size{
    // 创建一个bitmap的context
    CGFloat width = CGImageGetWidth(img.CGImage);
    CGFloat height = CGImageGetHeight(img.CGImage);

    CGFloat max = width >= height ? width:height;
    CGSize originSize;
    if (max <= 0) {
        return nil;
    }
    if (width >= height) {
        originSize = CGSizeMake(size.width, (size.width * height)/width);
    }else{
        originSize = CGSizeMake((size.height * width)/height, size.height);
    }
    // 并把它设置成为当前正在使用的context
    UIGraphicsBeginImageContext(size);
    // 绘制改变大小的图片
    [img drawInRect:CGRectMake((size.width - originSize.width)/2, (size.height - originSize.height)/2, originSize.width, originSize.height)];
    // 从当前context中创建一个改变大小后的图片
    UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();
    // 使当前的context出堆栈
    UIGraphicsEndImageContext();
    // 返回新的改变大小后的图片
    return scaledImage;
}

之后就是截取区域图片,这理解去10*10的方块:

// 裁剪图片
+ (UIImage *)imageFromImage:(UIImage *)image inRect:(CGRect)rect {
    CGImageRef sourceImageRef = [image CGImage];
    CGImageRef newImageRef = CGImageCreateWithImageInRect(sourceImageRef, rect);
    UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
    CGImageRelease(newImageRef);
    return newImage;
}

然后获取图片的主色:

/**
 *  获取图片的主色
 *
 *  @param image image
 *  @param scale 精准度0.1~1
 *
 *  @return 图片的主要颜色
 */
+ (NSDictionary *)mostColor:(UIImage *)image scale:(CGFloat)scale{

#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_6_1
    int bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast;
#else
    int bitmapInfo = kCGImageAlphaPremultipliedLast;
#endif
    if (scale <= 0.1) {
        scale = 0.1;
    }else if(scale >= 1){
        scale = 1;
    }

    //第一步 先把图片缩小 加快计算速度. 但越小结果误差可能越大
        CGSize thumbSize=CGSizeMake([image size].width * scale, [image size].height * scale);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(NULL,
                                                 thumbSize.width,
                                                 thumbSize.height,
                                                 8,//bits per component
                                                 thumbSize.width*4,
                                                 colorSpace,
                                                 bitmapInfo);

    CGRect drawRect = CGRectMake(0, 0, thumbSize.width, thumbSize.height);
    CGContextDrawImage(context, drawRect, image.CGImage);
    CGColorSpaceRelease(colorSpace);

    //第二步 取每个点的像素值
    unsigned char* data = CGBitmapContextGetData (context);

    if (data == NULL){
        CGContextRelease(context);
        return nil;
    }

    NSCountedSet *cls=[NSCountedSet setWithCapacity:thumbSize.width*thumbSize.height];

  for (int x=0; x<thumbSize.height; x++) {
        for (int y=0; y<thumbSize.width; y++) {

            int offset = 4*(x*thumbSize.width + y);
            int red = data[offset];
            int green = data[offset+1];
            int blue = data[offset+2];
            int alpha =  data[offset+3];

            NSArray *clr=@[@(red),@(green),@(blue),@(alpha)];
            [cls addObject:clr];

        }
    }
    CGContextRelease(context);

    //第三步 找到出现次数最多的那个颜色
    NSEnumerator *enumerator = [cls objectEnumerator];
    NSArray *curColor = nil;

    NSArray *MaxColor=nil;
    NSUInteger MaxCount=0;

    while ( (curColor = [enumerator nextObject]) != nil )
    {
        NSUInteger tmpCount = [cls countForObject:curColor];

        if ( tmpCount < MaxCount ) continue;

        MaxCount=tmpCount;
        MaxColor=curColor;

    }
    //返回三原色色值
    NSMutableDictionary *dic = [[NSMutableDictionary alloc] initWithCapacity:0];
    [dic setValue:@([MaxColor[0] intValue]/255.0f) forKey:@"red"];
    [dic setValue:@([MaxColor[1] intValue]/255.0f) forKey:@"green"];
    [dic setValue:@([MaxColor[2] intValue]/255.0f) forKey:@"blue"];
    return dic;
}

其实获取图片区域的主要颜色就是这么简单,线面附上获取单点的颜色:

/**
 *  获取图片上一个点的颜色
 *
 *  @param point 点击的点的位置
 *  @param image image
 *
 *  @return 返回点击点的颜色
 */
+ (UIColor *)colorAtPixel:(CGPoint)point UIImage:(UIImage *)image CGRect:(CGRect)rect{
    // Cancel if point is outside image coordinates
    if (!CGRectContainsPoint(CGRectMake(0.0f, 0.0f,rect.size.width, rect.size.height), point)) {
        return nil;
    }

    NSInteger pointX = trunc(point.x);
    NSInteger pointY = trunc(point.y);
    CGImageRef cgImage = image.CGImage;
    NSUInteger width = image.size.width;
    NSUInteger height = image.size.height;
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    int bytesPerPixel = 4;
    int bytesPerRow = bytesPerPixel * 1;
    NSUInteger bitsPerComponent = 8;
    unsigned char pixelData[4] = { 0, 0, 0, 0 };
    CGContextRef context = CGBitmapContextCreate(pixelData,
                                                 1,
                                                 1,
                                                 bitsPerComponent,
                                                 bytesPerRow,
                                                 colorSpace,
                                                 kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGColorSpaceRelease(colorSpace);
    CGContextSetBlendMode(context, kCGBlendModeCopy);

    // Draw the pixel we are interested in onto the bitmap context
    CGContextTranslateCTM(context, -pointX, pointY-(CGFloat)height);
    CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, (CGFloat)width, (CGFloat)height), cgImage);
    CGContextRelease(context);

    // Convert color values [0..255] to floats [0.0..1.0]
    CGFloat red   = (CGFloat)pixelData[0] / 255.0f;
    CGFloat green = (CGFloat)pixelData[1] / 255.0f;
    CGFloat blue  = (CGFloat)pixelData[2] / 255.0f;
    CGFloat alpha = (CGFloat)pixelData[3] / 255.0f;
    return [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
}

最终就实现如上图的想过,页面丑了点,但是效果是实现了,又不真确的地方,请留言。

项目源码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • iOS去除图片背景颜色的方法

    实际项目场景:去除图片的纯白色背景图,获得一张透明底图片用于拼图功能 介绍两种途径的三种处理方式(不知道为啥想起了孔乙己),具体性能鶸并未对比,如果有大佬能告知,不胜感激. Core Image Core Graphics/Quarz 2D Core Image Core Image是一个很强大的框架.它可以让你简单地应用各种滤镜来处理图像,比如修改鲜艳程度,色泽,或者曝光. 它利用GPU(或者CPU)来非常快速.甚至实时地处理图像数据和视频的帧.并且隐藏了底层图形处理的所有细节,通过提供的AP

  • 改变iOS应用中UITableView的背景颜色与背景图片的方法

    改变UITableView的header.footer背景颜色 改变UITableView的header.footer背景颜色,这是个很常见的问题.之前知道的一般做法是,通过实现tableView: viewForHeaderInSection:返回一个自定义的View,里面什么都不填,只设背景颜色.但是今天发现一个更简洁的做法: 对于iOS 6及以后的系统,实现这个新的delegate函数即可: 复制代码 代码如下: - (void)tableView:(UITableView *)table

  • iOS实现文字转化成彩色文字图片

    本文写了个将文字转化为多彩图片的功能,输入文字将文字转化为彩色的文字图片,可选择不同的字体,渐变,先看看效果. 实现主要用CAGradientLayer渐变,先看看上部展示实现代码: -(void)setupContentView { UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 44, ScreenWidth, ScreenHight - 44 -300)]; [self.view addSubview:co

  • iOS获取图片区域主色的方法

    之前的项目有这样的需求,有一个页面可以检索一块区域内图片的主色.效果图如图所示 下面是如何获取区域主色的实现思路: 首先,我们需要从相册,或者相机去获取图片: 其次,得到图片需要截取区域图片: 然后,获取截取图片的主色. 理想中是这样的,但是有很多阻碍,得到的图片需要自适应imageView(imageView的宽高是固定的),截图的得到的区域不是自己想要的区域.这里需要将图片等比例缩放,按照ImageView的宽高. 那现在就直接上代码吧! 首先我们需要等比例缩放Image: /** * 缩放

  • iOS实现图片压缩的两种方法及图片压缩上传功能

    两种压缩图片的方法:压缩图片质量(Quality),压缩图片尺寸(Size). 压缩图片质量 NSData *data = UIImageJPEGRepresentation(image, compression); UIImage *resultImage = [UIImage imageWithData:data]; 通过 UIImage 和 NSData 的相互转化,减小 JPEG 图片的质量来压缩图片.UIImageJPEGRepresentation:: 第二个参数 compressi

  • iOS获取当前网络环境的实现方法(推荐)

    实例如下: // 获取网络环境的方法 + (NSString *)networktype{ NSArray *subviews = [[[[UIApplication sharedApplication] valueForKey:@"statusBar"] valueForKey:@"foregroundView"]subviews]; NSNumber *dataNetworkItemView = nil; for (id subview in subviews)

  • js判断图片加载完成后获取图片实际宽高的方法

    本文实例讲述了js判断图片加载完成后获取图片实际宽高的方法.分享给大家供大家参考,具体如下: 通常,我们会用jq的.width()/.height()方法获取图片的宽度/高度或者用js的.offsetwidth/.offsetheight方法来获取图片的宽度/高度,但这些方法在我们通过样式设置了图片的宽高后获取的就不是图片的实际宽高,这显然在有些时候不是我们想要的结果,那么有没有一种方法来获取这样的实际宽高呢?答案是有的.下面的代码就能解决这样的问题: <img src="01.jpg&q

  • Android编程获取图片和视频缩略图的方法

    本文实例讲述了Android编程获取图片和视频缩略图的方法.分享给大家供大家参考,具体如下: 从Android 2.2开始系统新增了一个缩略图ThumbnailUtils类,位于framework的android.media.ThumbnailUtils位 置,可以帮助我们从mediaprovider中获取系统中的视频或图片文件的缩略图,该类提供了三种静态方法可以直接调用获取. 1. createVideoThumbnail static Bitmap createVideoThumbnail(

  • js兼容火狐获取图片宽和高的方法

    本文实例讲述了js兼容火狐获取图片宽和高的方法.分享给大家供大家参考.具体实现方法如下: <!doctype html> <html> <head> <meta content="text/html; charset=GBK" http-equiv="Content-Type" /> <title>获取Image 宽高</title> </head> <body> <

  • Python3实现获取图片文字里中文的方法分析

    本文实例讲述了Python3实现获取图片文字里中文的方法.分享给大家供大家参考,具体如下: 一.运行环境 (1) win10 (2) pycharm (3) python 3.5 (4) pillow与pytesseract库安装: pip3 install pillow pip3 install pytesseract (5)  识别引擎tesseract-ocr ,下载之后解压安装,下载地址:https://www.jb51.net/softs/538925.html 二. 运行代码 # -

  • iOS 获取设备唯一标示符的方法详解

    在开发中会遇到应用需要记录设备标示,即使应用卸载后再安装也可重新识别的情况,在这写一种实现方式--读取设备的UUID(Universally Unique Identifier)并通过KeyChain记录. 首先iOS中获取设备唯一标示符的方法一直随版本的更新而变化.iOS 2.0版本以后UIDevice提供一个获取设备唯一标识符的方法uniqueIdentifier,通过该方法我们可以获取设备的序列号,这个也是目前为止唯一可以确认唯一的标示符.好景不长,因为该唯一标识符与手机一一对应,苹果觉得

  • C#获取图片文件扩展名的方法

    下面我给各位朋友整理了一篇C# 获取图片文件扩展名的例子,这里方法都非常的简单,我们只用到了image.RawFormat.Guid就实现了,具体看代码 例子 复制代码 代码如下: /// <summary> /// 根据图像获取图像的扩展名 /// </summary> /// <param name="image"></param> /// <returns></returns> public static S

  • Mybatis使用useGeneratedKeys获取自增主键的方法

    摘要 我们经常使用useGenerateKeys来返回自增主键,避免多一次查询.也会经常使用on duplicate key update,来进行insertOrUpdate,来避免先query 在insert/update.用起来很爽,但是经常踩坑,还不知为何.本篇就是深入分析获取自增主键的原理. 问题 首先摘两段我司一些老代码的bug 批量插入用户收藏 for (tries = 0; tries < MAX_RETRY; tries++) { final int result = colle

随机推荐