很久以前有个调色板的需求,现在闲下来终于可以整理一下了。
首先我们先要画出调色板
.h
//
// HanColorView.h
//
// Created by han on 2021/10/15.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@class HanColorView;
@protocol HanColorViewDelegate <NSObject>
@optional
-(void)colorView:(HanColorView *)colorView color:(UIColor *)color;
-(void)colorView:(HanColorView *)colorView red:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha;
@end
@interface HanColorView : UIView
@property (nonatomic, weak) id<HanColorViewDelegate> delegate;
/// 是否隐藏拾取块 默认NO 展示
@property (nonatomic, assign) BOOL isHiddenPointView;
@end
NS_ASSUME_NONNULL_END
.m
//
// HanColorView.m
//
// Created by han on 2021/10/15.
//
#import "HanColorView.h"
#import "UIImage+ColorSelect.h"
@interface HanColorView ()
@property (nonatomic, strong) UIView *colorView;
@end
@implementation HanColorView
- (void)drawRect:(CGRect)rect {
// Drawing code
CGContextRef context = UIGraphicsGetCurrentContext();
CGSize size = rect.size;
CGPoint center = CGPointMake(floorf(size.width/2.0f),floorf(size.height/2.0f));
CGFloat radius = floorf(size.width/2.0f);
// 创建RGB色彩空间,创建这个以后,context里面用的颜色都是用RGB表示
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
CGContextSaveGState(context);
CGContextAddEllipseInRect(context, CGRectMake(0, 0, size.width, size.height));
CGContextClip(context);
NSInteger numberOfSegments =360;
for(CGFloat i =0; i < numberOfSegments; i++) {
UIColor*color = [UIColor colorWithHue:i/(float)numberOfSegments saturation:1 brightness:1 alpha:1];
CGContextSetStrokeColorWithColor(context, color.CGColor);
CGFloat segmentAngle =2*M_PI/ (float)numberOfSegments;
CGPoint start = center;
CGPoint end =CGPointMake(center.x+ radius *cosf(i * segmentAngle), center.y+ radius *sinf(i * segmentAngle));
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path,0, start.x, start.y);
CGFloat offsetFromMid =2.f*(M_PI/180);
CGPoint end1 =CGPointMake(center.x+ radius *cosf(i * segmentAngle-offsetFromMid), center.y+ radius *sinf(i * segmentAngle-offsetFromMid));
CGPoint end2 =CGPointMake(center.x+ radius *cosf(i * segmentAngle+offsetFromMid), center.y+ radius *sinf(i * segmentAngle+offsetFromMid));
CGPathAddLineToPoint(path,0, end1.x, end1.y);
CGPathAddLineToPoint(path,0, end2.x, end2.y);
CGContextSaveGState(context);
CGContextAddPath(context, path);
CGPathRelease(path);
CGContextClip(context);
NSArray*colors =@[(__bridge id)[UIColor colorWithWhite:1 alpha:1].CGColor, (__bridge id)color.CGColor];
// 通过成对的颜色值(colors)和位置(locations)创建一个渐变色,colors是一个由CGColor对象组成的非空数组,如果space非空,所有颜色都会转换到该色彩空间,并且渐变将绘制在这个色彩空间里面;否则(space为NULL),每一种颜色将会被转换并且绘制在一般的RGB色彩空间中。如果locations为NULL,第一个颜色在location 0,最后一个颜色在location 1, 并且中间的颜色将会等距分布在中间。locations中的每一个location应该是一个0~1之间的CGFloat值;locations数字的元素数量应该跟colors中的一样,如果没有颜色提供给0或者1,这个渐变将使用location中最靠近0或者1的颜色值
CGGradientRef gradient =CGGradientCreateWithColors(rgbColorSpace, (__bridge CFArrayRef)colors,NULL);
// 在当前context的裁剪的区域中,填充一个从startPoint到endPoint的线性渐变颜色。渐变色中location 0对应着startPoint;location 1对应着endPoint;颜色将根据locations的值线性插入在这两点(startPoint,endPoint)之间。option标志控制在startPoint之前和endPoint之后时候填充颜色。(跟开始的颜色还有最后的颜色相同)
CGContextDrawLinearGradient(context, gradient, start, end, kCGGradientDrawsBeforeStartLocation|kCGGradientDrawsAfterEndLocation);
CGGradientRelease(gradient);
CGContextRestoreGState(context);
}
CGColorSpaceRelease(rgbColorSpace);
CGContextRestoreGState(context);
CGContextSetStrokeColorWithColor(context, UIColor.clearColor.CGColor);
CGContextSetLineWidth(context, 1);
CGContextStrokeEllipseInRect(context, CGRectMake(0, 0, size.width, size.height));
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[self getMyPointWithEvent:event];
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[self getMyPointWithEvent:event];
}
-(void)getMyPointWithEvent:(UIEvent *)event{
NSSet *allTouch = [event allTouches];
UITouch *touch = [allTouch anyObject];
CGPoint point = [touch locationInView:[touch view]];
int x = point.x;
int y = point.y;
CGFloat r = self.frame.size.width/2;
CGFloat px = x - r;
CGFloat py = r - y;
CGFloat pl = fabs(sqrt(powf(fabs(px), 2) + pow(fabs(py), 2)));
if (pl > r) {
return;
}
UIImage *img = [self convertViewToImage:self];
UIColor *color = [img colorAtPoint:point withSize:self.frame.size];
NSArray *colorArr = [img rgbaAtPoint:point withSize:self.frame.size];
self.colorView.backgroundColor = color;
if (self.delegate && [self.delegate respondsToSelector:@selector(colorView:color:)]) {
[self.delegate colorView:self color:color];
}
if (self.delegate && [self.delegate respondsToSelector:@selector(colorView:red:green:blue:alpha:)]) {
[self.delegate colorView:self red:[colorArr[0] floatValue] green:[colorArr[1] floatValue] blue:[colorArr[2] floatValue] alpha:[colorArr[3] floatValue]];
}
}
//view转image
- (UIImage *)convertViewToImage:(UIView *)view {
UIImage *imageRet = [[UIImage alloc]init];
//UIGraphicsBeginImageContextWithOptions(区域大小, 是否是非透明的, 屏幕密度);
UIGraphicsBeginImageContextWithOptions(view.frame.size, YES, [UIScreen mainScreen].scale);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
imageRet = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return imageRet;
}
#pragma mark - get/set
-(UIView *)colorView{
if (!_colorView) {
_colorView = [[UIView alloc] initWithFrame:CGRectMake(self.frame.size.width - 30, 0, 30, 30)];
[self addSubview:_colorView];
}
return _colorView;
}
- (void)setIsHiddenPointView:(BOOL)isHiddenPointView{
_isHiddenPointView= isHiddenPointView;
self.colorView.hidden = !isHiddenPointView;
}
@end
画出来就是这样子的
然后拾取色
思路:从UIImage获取该点的UIColor(RGB),使用Category方式拓展UIImage。所以这个方法可以获取任意图片的任意点的颜色。
.h
//
// UIImage+ColorSelect.h
//
// Created by han on 2021/10/20.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIImage (ColorSelect)
/// 返回颜色
/// @param point 点
/// @param size 视图大小
- (UIColor *)colorAtPoint:(CGPoint)point withSize:(CGSize)size;
/// 返回RGBA
/// @param point 点
/// @param size 视图大小
- (NSArray *)rgbaAtPoint:(CGPoint)point withSize:(CGSize)size;
@end
NS_ASSUME_NONNULL_END
.m
//
// UIImage+ColorSelect.m
//
// Created by han on 2021/10/20.
//
#import "UIImage+ColorSelect.h"
@implementation UIImage (ColorSelect)
- (NSArray *)colorAtPixel:(CGPoint)point withSize:(CGSize)size{
// Cancel if point is outside image coordinates
if (!CGRectContainsPoint(CGRectMake(0.0f, 0.0f, size.width, size.height), point)) {
return nil;
}
NSInteger pointX = trunc(point.x);
NSInteger pointY = trunc(point.y);
CGImageRef cgImage = self.CGImage;
NSUInteger width = size.width;
NSUInteger height = 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 @[@(red),@(green),@(blue),@(alpha)];
}
- (UIColor *)colorAtPoint:(CGPoint)point withSize:(CGSize)size{
NSArray *arr = [self colorAtPixel:point withSize:size];
if (arr.count == 4) {
return [UIColor colorWithRed:[arr[0] floatValue] green:[arr[1] floatValue] blue:[arr[2] floatValue] alpha:[arr[3] floatValue]];
}
return [UIColor whiteColor];
}
- (NSArray *)rgbaAtPoint:(CGPoint)point withSize:(CGSize)size{
NSArray *arr = [self colorAtPixel:point withSize:size];
if (arr.count == 4) {
return arr;
}
return @[@(1),@(1),@(1),@(1)];
}
@end
补充:拾取图片上的颜色
.h
//
// HanSelectColorView.h
//
// Created by han on 2021/10/21.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@class HanSelectColorView;
@protocol HanSelectColorViewDelegate <NSObject>
@optional
-(void)selectColorView:(HanSelectColorView *)colorView color:(UIColor *)color;
-(void)selectColorView:(HanSelectColorView *)colorView red:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha;
@end
@interface HanSelectColorView : UIView
@property (nonatomic, weak) id<HanSelectColorViewDelegate> delegate;
@property (nonatomic, strong) UIImage *image;
/// 是否展示拾取块 默认NO 展示
@property (nonatomic, assign) BOOL isHiddenPointView;
@end
NS_ASSUME_NONNULL_END
.m
//
// HanSelectColorView.m
//
// Created by han on 2021/10/21.
//
#import "HanSelectColorView.h"
#import "UIImage+ColorSelect.h"
@interface HanSelectColorView ()
@property (nonatomic, strong) UIImageView *imgView;
@property (nonatomic, strong) UIView *colorView;
@end
@implementation HanSelectColorView
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[self getMyPointWithEvent:event];
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[self getMyPointWithEvent:event];
}
-(void)getMyPointWithEvent:(UIEvent *)event{
NSSet *allTouch = [event allTouches];
UITouch *touch = [allTouch anyObject];
CGPoint point = [touch locationInView:self];
UIImage *img = self.image;
UIColor *color = [img colorAtPoint:point withSize:self.frame.size];
NSArray *colorArr = [img rgbaAtPoint:point withSize:self.frame.size];
self.colorView.backgroundColor = color;
if (self.delegate && [self.delegate respondsToSelector:@selector(selectColorView:color:)]) {
[self.delegate selectColorView:self color:color];
}
if (self.delegate && [self.delegate respondsToSelector:@selector(selectColorView:red:green:blue:alpha:)]) {
[self.delegate selectColorView:self red:[colorArr[0] floatValue] green:[colorArr[1] floatValue] blue:[colorArr[2] floatValue] alpha:[colorArr[3] floatValue]];
}
}
#pragma mark - get/set
- (UIImageView *)imgView{
if (_imgView == nil) {
_imgView = [[UIImageView alloc] init];
_imgView.frame = self.bounds;
[self addSubview:_imgView];
}
return _imgView;
}
-(UIView *)colorView{
if (!_colorView) {
_colorView = [[UIView alloc] initWithFrame:CGRectMake(self.frame.size.width - 30, 0, 30, 30)];
[self addSubview:_colorView];
}
return _colorView;
}
-(void)setImage:(UIImage *)image{
_image = image;
self.imgView.image = image;
self.imgView.hidden = NO;
self.colorView.hidden = NO;
}
- (void)setIsHiddenPointView:(BOOL)isHiddenPointView{
_isHiddenPointView= isHiddenPointView;
self.colorView.hidden = !isHiddenPointView;
}
@end
===========
判断是不是白屏
// 遍历像素点 白色像素占比大于99%认定为白屏
- (BOOL)searchEveryPixel:(UIImage *)image {
CGImageRef cgImage = [image CGImage];
size_t width = CGImageGetWidth(cgImage);
size_t height = CGImageGetHeight(cgImage);
// 每个像素点包含r g b a 四个字节
size_t bytesPerRow = CGImageGetBytesPerRow(cgImage);
size_t bitsPerPixel = CGImageGetBitsPerPixel(cgImage);
CGDataProviderRef dataProvider = CGImageGetDataProvider(cgImage);
CFDataRef data = CGDataProviderCopyData(dataProvider);
UInt8 *buffer = (UInt8 *)CFDataGetBytePtr(data);
int whiteCount = 0;
int totalCount = 0;
for (int j = 0; j < height; j ++ ) {
for (int i = 0; i < width; i ++) {
UInt8 *pt = buffer + j * bytesPerRow + i * (bitsPerPixel / 8);
UInt8 red = * pt;
UInt8 green = *(pt + 1);
UInt8 blue = *(pt + 2);
totalCount ++;
if (red >= 254 && green >= 254 && blue >= 254) {
whiteCount ++;
}
}
}
float proportion = (float)whiteCount / totalCount ;
NSLog(@"H5像素点数:%d,白色像素点数:%d , 占比: %f",totalCount , whiteCount , proportion );
if (proportion > 0.99) {
return YES;
} else {
return NO;
}
}