Ich möchte die Farbeinstellung für einen Hintergrund auf einem UIImageView überprüfen. Ich habe es versucht:
if(myimage.backgroundColor == [UIColor greenColor]){
...}
else{
...}
aber das funktioniert nicht, selbst wenn ich weiß, dass die Farbe grün ist, fällt sie immer in den anderen Teil.
Gibt es auch eine Möglichkeit, die aktuelle Farbe in der Debug-Konsole auszugeben.
p [myimage backgroundColor]
und
po [myimage backgroundColor]
arbeite nicht.
Haben Sie [myColor isEqual:someOtherColor]
ausprobiert?
Wie zoul in den Kommentaren hervorgehoben hat, gibt isEqual:
NO
zurück, wenn Farben verglichen werden, die sich in unterschiedlichen Modellen/Räumen befinden (z. B. #FFF
mit [UIColor whiteColor]
). Ich habe diese UIColor-Erweiterung geschrieben, die beide Farben in denselben Farbraum konvertiert, bevor sie miteinander verglichen werden:
- (BOOL)isEqualToColor:(UIColor *)otherColor {
CGColorSpaceRef colorSpaceRGB = CGColorSpaceCreateDeviceRGB();
UIColor *(^convertColorToRGBSpace)(UIColor*) = ^(UIColor *color) {
if (CGColorSpaceGetModel(CGColorGetColorSpace(color.CGColor)) == kCGColorSpaceModelMonochrome) {
const CGFloat *oldComponents = CGColorGetComponents(color.CGColor);
CGFloat components[4] = {oldComponents[0], oldComponents[0], oldComponents[0], oldComponents[1]};
CGColorRef colorRef = CGColorCreate( colorSpaceRGB, components );
UIColor *color = [UIColor colorWithCGColor:colorRef];
CGColorRelease(colorRef);
return color;
} else
return color;
};
UIColor *selfColor = convertColorToRGBSpace(self);
otherColor = convertColorToRGBSpace(otherColor);
CGColorSpaceRelease(colorSpaceRGB);
return [selfColor isEqual:otherColor];
}
Dies könnte etwas zu spät sein, aber CoreGraphics hat eine einfachere API, um dies zu erreichen:
CGColorEqualToColor(myColor.CGColor, [UIColor clearColor].CGColor)
Wie die Dokumentation sagt:
Gibt an, ob zwei Farben gleich sind . Zwei Farben sind gleich, wenn sie gleiche Farbräume und numerisch gleiche Farbkomponenten haben.
Dies löst viele Probleme und undichte Algorithmen.
samvermettes Lösung in Swift übersetzt:
extension UIColor {
func isEqualToColor(otherColor : UIColor) -> Bool {
if self == otherColor {
return true
}
let colorSpaceRGB = CGColorSpaceCreateDeviceRGB()
let convertColorToRGBSpace : ((color : UIColor) -> UIColor?) = { (color) -> UIColor? in
if CGColorSpaceGetModel(CGColorGetColorSpace(color.CGColor)) == CGColorSpaceModel.Monochrome {
let oldComponents = CGColorGetComponents(color.CGColor)
let components : [CGFloat] = [ oldComponents[0], oldComponents[0], oldComponents[0], oldComponents[1] ]
let colorRef = CGColorCreate(colorSpaceRGB, components)
let colorOut = UIColor(CGColor: colorRef!)
return colorOut
}
else {
return color;
}
}
let selfColor = convertColorToRGBSpace(color: self)
let otherColor = convertColorToRGBSpace(color: otherColor)
if let selfColor = selfColor, otherColor = otherColor {
return selfColor.isEqual(otherColor)
}
else {
return false
}
}
}
#import "UIColor-Expanded.h"
//https://github.com/thetaplab/uicolor-utilities
//RGB distance
CGFloat distance = sqrtf(powf((clr0.red - clr1.red), 2) + powf((clr0.green - clr1.green), 2) + powf((clr0.blue - clr1.blue), 2) );
if(distance<=minDistance){
....
}else{
...
}
Ich habe diese Kategorie geschrieben. Wenn isEqual:
NEIN zurückgibt, wird geprüft, ob der weitere Vergleich verschiedener Komponenten noch übereinstimmt. Nach Möglichkeit werden verschiedene Modelle noch miteinander verglichen.
@implementation UIColor (Matching)
-(BOOL)matchesColor:(UIColor *)color error:(NSError *__autoreleasing *)error
{
UIColor *lhs = self;
UIColor *rhs = color;
if([lhs isEqual:rhs]){ // color model and values are the same
return YES;
}
CGFloat red1, red2, green1, alpha1, green2, blue1, blue2, alpha2;
BOOL lhsSuccess = [lhs getRed:&red1 green:&green1 blue:&blue1 alpha:&alpha1];
BOOL rhsSuccess = [rhs getRed:&red2 green:&green2 blue:&blue2 alpha:&alpha2];
if((!lhsSuccess && rhsSuccess) || (lhsSuccess && !rhsSuccess)){ // one is RGBA, one color not.
CGFloat r,g,b,a;
if(!lhsSuccess){ // lhs color could be a monochrome
const CGFloat *components = CGColorGetComponents(lhs.CGColor);
if([lhs _colorSpaceModel] == kCGColorSpaceModelMonochrome){
r = g = b = components[0];
a = components[1];
return r == red2 && g == green2 && b == blue2 && a == alpha2;
}
} else { // rhs color could be a monochrome
const CGFloat *components = CGColorGetComponents(rhs.CGColor);
if([rhs _colorSpaceModel] == kCGColorSpaceModelMonochrome){
r = g = b = components[0];
a = components[1];
return r == red1 && g == green1 && b == blue1 && a == alpha1;
}
}
NSError *aError = [[NSError alloc] initWithDomain:@"UIColorComparision" code:-11111 userInfo:[self _colorComparisionErrorUserInfo]];
*error = aError;
return NO;
} else if (!lhsSuccess && !rhsSuccess){ // both not RGBA, lets try HSBA
CGFloat hue1,saturation1,brightness1;
CGFloat hue2,saturation2,brightness2;
lhsSuccess = [lhs getHue:&hue1 saturation:&saturation1 brightness:&brightness1 alpha:&alpha1];
rhsSuccess = [lhs getHue:&hue2 saturation:&saturation2 brightness:&brightness2 alpha:&alpha2];
if((!lhsSuccess && rhsSuccess) || (lhsSuccess && !rhsSuccess)){
NSError *aError = [[NSError alloc] initWithDomain:@"UIColorComparision" code:-11111 userInfo:[self _colorComparisionErrorUserInfo]];
*error = aError;
return NO;
} else if(!lhsSuccess && !rhsSuccess){ // both not HSBA, lets try monochrome
CGFloat white1, white2;
lhsSuccess = [lhs getWhite:&white1 alpha:&alpha1];
rhsSuccess = [rhs getWhite:&white2 alpha:&alpha2];
if((!lhsSuccess && rhsSuccess) || (lhsSuccess && !rhsSuccess)){
NSError *aError = [[NSError alloc] initWithDomain:@"UIColorComparision" code:-11111 userInfo:[self _colorComparisionErrorUserInfo]];
*error = aError;
return NO;
} else {
return white1 == white2 && alpha1 == alpha2;
}
} else {
return hue1 == hue2 && saturation1 == saturation2 && brightness1 == brightness2 && alpha1 == alpha2;
}
} else {
return (red1 == red2 && green1 == green2 && blue1 == blue2 && alpha1 == alpha2);
}
}
-(NSDictionary *)_colorComparisionErrorUserInfo{
NSDictionary *userInfo = @{
NSLocalizedDescriptionKey: NSLocalizedString(@"Comparision failed.", nil),
NSLocalizedFailureReasonErrorKey: NSLocalizedString(@"The colors models are incompatible. Or the color is a pattern.", nil),
};
return userInfo;
}
- (CGColorSpaceModel)_colorSpaceModel {
return CGColorSpaceGetModel(CGColorGetColorSpace(self.CGColor));
}
@end
UIColor *green1 = [UIColor greenColor];
UIColor *green2 = [UIColor colorWithRed:0 green:1 blue:0 alpha:1];
UIColor *yellow = [UIColor yellowColor];
UIColor *grey1 = [UIColor colorWithWhite:2.0/3.0 alpha:1];
UIColor *grey2 = [UIColor lightGrayColor];
NSError *error1, *error2, *error3, *error4, *error5;
BOOL match1 = [green1 matchesColor:green2 error:&error1]; // YES
BOOL match2 = [green1 matchesColor:yellow error:&error2]; // NO
BOOL match3 = [green1 matchesColor:grey1 error:&error3]; // NO
BOOL match4 = [grey1 matchesColor:grey2 error:&error4]; // YES
BOOL match5 = [grey1 matchesColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"bg.png"]]
error:&error5]; // NO, Error
Diese UIColor-Erweiterung funktioniert einwandfrei, sofern die verglichenen Farben in das RGB-Format konvertiert werden können.
public extension UIColor {
static func == (l: UIColor, r: UIColor) -> Bool {
var l_red = CGFloat(0); var l_green = CGFloat(0); var l_blue = CGFloat(0); var l_alpha = CGFloat(0)
guard l.getRed(&l_red, green: &l_green, blue: &l_blue, alpha: &l_alpha) else { return false }
var r_red = CGFloat(0); var r_green = CGFloat(0); var r_blue = CGFloat(0); var r_alpha = CGFloat(0)
guard r.getRed(&r_red, green: &r_green, blue: &r_blue, alpha: &r_alpha) else { return false }
return l_red == r_red && l_green == r_green && l_blue == r_blue && l_alpha == r_alpha
}
}
Zumindest mit dieser Erweiterung:
UIColor.whiteColor == UIColor(hex: "#FFFFFF") // true
UIColor.black == UIColor(red: 0, green: 0, blue: 0, alpha: 1) // true
Beide Vergleiche würden false zurückgeben, wenn sie mit der nativen UColor.isEqual (...) verglichen werden.
Wenn Sie
myimage.backgroundColor == [UIColor greenColor]
wie folgt vergleichen, wenn Sie die backgroundColor vor dieser Anweisung nicht in grün geändert haben, funktioniert sie nicht.
Ich hatte das gleiche Problem in meinem Farbenspiel und ich habe gelöst, dass man mit der einfachen Differenzgleichung in RGB-Farben diesen kurzen Codebeispiel ColorProcess aus hier betrachten kann.
es ist wie Sieger antworten
GFloat distance = sqrtf(powf((clr0.red - clr1.red), 2) + powf((clr0.green - clr1.green), 2) + powf((clr0.blue - clr1.blue), 2) );
if(distance<=minDistance){
....
}else{
…
}
Anstelle dieses Codebeispiels können Sie verwenden
include "UIColorProcess.h"
..
float distance = [UIColorProcess findDistanceBetweenTwoColor:[UIColor redColor] secondColor:[UIColor blueColor]];
und wenn es 0 zurückgibt, bedeutet das, dass Sie zu ähnliche Farben vergleichen. Rückkehrbereich ist so etwas wie (0.0f - 1.5f) ..
Ich verwende diese Erweiterung, die in allen Fällen für mich funktioniert.
/***** UIColor Extension to Compare colors as string *****/
@interface UIColor (compare)
- (BOOL)compareWithColor:(UIColor *)color;
@end
@implementation UIColor(compare)
- (BOOL)compareWithColor:(UIColor *)color {
return ([[[CIColor colorWithCGColor:self.CGColor] stringRepresentation] isEqualToString:[[CIColor colorWithCGColor:color.CGColor] stringRepresentation]]);
}
@end
/**** End ****/
Hoffnung hilft jemandem.
Hinweis: #ffffff
entspricht [UIColor whiteColor]
durch diese Erweiterung
Ich habe rafs Antwort in Swift 4 (viele Änderungen in der CGColor
-API) konvertiert, das Entpacken von Gewalt entfernt und die Einrückung dank großzügiger Verwendung von guard
verringert:
@extension UIColor {
func isEqualToColor(otherColor: UIColor) -> Bool {
if self == otherColor {
return true
}
let colorSpaceRGB = CGColorSpaceCreateDeviceRGB()
let convertColorToRGBSpace: ((UIColor) -> UIColor?) = { (color) -> UIColor? in
guard color.cgColor.colorSpace?.model == .monochrome else {
return color
}
guard let oldComponents = color.cgColor.components else {
return nil
}
let newComponents = [oldComponents[0], oldComponents[0], oldComponents[0], oldComponents[1]]
guard let colorRef = CGColor(colorSpace: colorSpaceRGB, components: newComponents) else {
return nil
}
return UIColor(cgColor: colorRef)
}
guard let selfColor = convertColorToRGBSpace(self),
let otherColor = convertColorToRGBSpace(otherColor) else {
return false
}
return selfColor.isEqual(otherColor)
}
}
Warum nicht die Erweiterung mit gleichwertigem Protokoll hinzufügen? Diese Antwort verwendet die Lösung von Nicolas Miari. Also, wenn Sie diese Antwort mögen, seien Sie willkommen, seine Antwort zu mögen (zweite von oben)
Der Kommentar von Zoul: Seien Sie vorsichtig, wenn Sie Farben auf diese Weise vergleichen, da sie im selben Farbmodell sein müssen, um als gleichwertig betrachtet zu werden. Zum Beispiel ist #ffffff nicht gleich [UIColor whiteColor]
static func == (lhs: UIColor, rhs: UIColor) -> Bool {
let colorSpaceRGB = CGColorSpaceCreateDeviceRGB()
let convertColorToRGBSpace: ((UIColor) -> UIColor?) = { (color) -> UIColor? in
guard color.cgColor.colorSpace?.model == .monochrome else {
return color
}
guard let oldComponents = color.cgColor.components else {
return nil
}
let newComponents = [oldComponents[0], oldComponents[0], oldComponents[0], oldComponents[1]]
guard let colorRef = CGColor(colorSpace: colorSpaceRGB, components: newComponents) else {
return nil
}
return UIColor(cgColor: colorRef)
}
guard let selfColor = convertColorToRGBSpace(lhs),
let otherColor = convertColorToRGBSpace(rhs) else {
return false
}
return selfColor.isEqual(otherColor)
}
UIColor-Erweiterung
- (CGFloat)accuracyCompareWith:(UIColor *)color {
CIColor *c1 = [[CIColor alloc] initWithColor:self];
CIColor *c2 = [[CIColor alloc] initWithColor:color];
BOOL hasAlpha = c1.numberOfComponents == 4 && c2.numberOfComponents == 4;
NSInteger numberOfComponents = hasAlpha ? 4 : 3;
CGFloat colorMax = 1.0;
CGFloat p = colorMax / 100.0;
CGFloat redP = fabs(c1.red / p - c2.red / p);
CGFloat greenP = fabs(c1.green / p - c2.green / p);
CGFloat blueP = fabs(c1.blue / p - c2.blue / p);
CGFloat alphaP = 0;
if (hasAlpha)
alphaP = fabs(c1.alpha / p - c2.alpha / p);
return (redP + greenP + blueP + alphaP) / (CGFloat)numberOfComponents;
}
Die Antwort von @ samvermette ist zwar sehr gut, aber ich habe festgestellt, dass es beim Vergleich verschiedener Farbtypen manchmal zu falschen Negativen kommen kann (in meinem Fall UIDeviceRGBColor
zu UICachedDeviceWhiteColor
). Ich habe es behoben, indem ich die Farbe explizit auch im `else 'erzeugt habe:
- (BOOL)isEqualToColor:(UIColor *)otherColor
{
if (self == otherColor)
return YES;
CGColorSpaceRef colorSpaceRGB = CGColorSpaceCreateDeviceRGB();
UIColor *(^convertColorToRGBSpace)(UIColor*) = ^(UIColor *color)
{
if (CGColorSpaceGetModel(CGColorGetColorSpace(color.CGColor)) == kCGColorSpaceModelMonochrome)
{
const CGFloat *oldComponents = CGColorGetComponents(color.CGColor);
CGFloat components[4] = {oldComponents[0], oldComponents[0], oldComponents[0], oldComponents[1]};
CGColorRef colorRef = CGColorCreate(colorSpaceRGB, components);
UIColor *color = [UIColor colorWithCGColor:colorRef];
CGColorRelease(colorRef);
return color;
}
else
{
const CGFloat *oldComponents = CGColorGetComponents(color.CGColor);
CGFloat components[4] = {oldComponents[0], oldComponents[1], oldComponents[2], oldComponents[3]};
CGColorRef colorRef = CGColorCreate(colorSpaceRGB, components);
UIColor *color = [UIColor colorWithCGColor:colorRef];
CGColorRelease(colorRef);
return color;
}
};
UIColor *selfColor = convertColorToRGBSpace(self);
otherColor = convertColorToRGBSpace(otherColor);
CGColorSpaceRelease(colorSpaceRGB);
return [selfColor isEqual:otherColor];
}
Wie wäre es mit:
+(BOOL)color:(UIColor *)color1 matchesColor:(UIColor *)color2
{
CGFloat red1, red2, green1, green2, blue1, blue2, alpha1, alpha2;
[color1 getRed:&red1 green:&green1 blue:&blue1 alpha:&alpha1];
[color2 getRed:&red2 green:&green2 blue:&blue2 alpha:&alpha2];
return (red1 == red2 && green1 == green2 && blue1 == blue2 && alpha1 == alpha2);
}
Einige ungewöhnliche Rundungsfehler können auftreten. Dies kann der Grund sein, warum ein Objekt auf eine Farbe gesetzt ist und die Farbe, für die Sie es festgelegt haben, nicht genau übereinstimmt.
So habe ich es gelöst:
private func compareColors (c1:UIColor, c2:UIColor) -> Bool{
// some kind of weird rounding made the colors unequal so had to compare like this
var red:CGFloat = 0
var green:CGFloat = 0
var blue:CGFloat = 0
var alpha:CGFloat = 0
c1.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
var red2:CGFloat = 0
var green2:CGFloat = 0
var blue2:CGFloat = 0
var alpha2:CGFloat = 0
c2.getRed(&red2, green: &green2, blue: &blue2, alpha: &alpha2)
return (Int(green*255) == Int(green2*255))
}
Dieser Code kann verbessert werden, indem nicht nur 1, sondern alle Komponenten verglichen werden. ZB rot + grün + blau + alpha == red2 + green2 + blue2 + alpha2
Hier ist eine Erweiterung zum Umschalten auf die RGC Space Color in Swift:
extension UIColor {
func convertColorToRGBSpaceColor() -> UIColor {
let colorSpaceRGB = CGColorSpaceCreateDeviceRGB()
let oldComponents = CGColorGetComponents(self.CGColor)
let components = [oldComponents[0], oldComponents[0], oldComponents[0], oldComponents[1]]
let colorRef = CGColorCreate(colorSpaceRGB, components)
let convertedColor = UIColor(CGColor: colorRef!)
return convertedColor
}
}
Die anderen Lösungen funktionierten nicht richtig. Hier ist ein Ansatz, der in Swift funktioniert:
import CoreGraphics
extension UIColor {
/**
Checks for visual equality of two colors regardless of their color space.
- parameter color: The other color for comparison.
- returns: A boolean representing whether the colors are visually the same color.
*/
public func isVisuallyEqualTo(_ color: UIColor) -> Bool {
return rgbaComponents == color.rgbaComponents
}
public var rgbaComponents: [CGFloat] {
var data = [CUnsignedChar](repeating: 0, count: 4)
let colorSpace = CGColorSpaceCreateDeviceRGB()
let context = CGContext(data: &data,
width: 1, height: 1,
bitsPerComponent: 8, bytesPerRow: 4,
space: colorSpace,
bitmapInfo: CGImageAlphaInfo.noneSkipLast.rawValue)
context?.setFillColor(cgColor)
context?.fill(CGRect(x: 0, y: 0, width: 1, height: 1))
return data.map { CGFloat($0) / 255.0 }
}
}
Erweiterung um UIColor, unter Verwendung der Swift 2.2-Features ..__ Beachten Sie jedoch, dass aufgrund der Vergleiche der RGBA-Werte, und dies sind CGFloat, Rundungsfehler dazu führen können, dass die Farben nicht gleich sind, wenn sie nicht genau gleich sind (z ursprünglich nicht mit den gleichen Eigenschaften in init erstellt (...)!).
/**
Extracts the RGBA values of the colors and check if the are the same.
*/
public func isEqualToColorRGBA(color : UIColor) -> Bool {
//local type used for holding converted color values
typealias colorType = (red : CGFloat, green : CGFloat, blue : CGFloat, alpha : CGFloat)
var myColor : colorType = (0,0,0,0)
var otherColor : colorType = (0,0,0,0)
//getRed returns true if color could be converted so if one of them failed we assume that colors are not equal
guard getRed(&myColor.red, green: &myColor.green, blue: &myColor.blue, alpha: &myColor.alpha) &&
color.getRed(&otherColor.red, green: &otherColor.green, blue: &otherColor.blue, alpha: &otherColor.alpha)
else {
return false
}
log.debug("\(myColor) = \(otherColor)")
//as of Swift 2.2 (Xcode 7.3.1), tuples up to arity 6 can be compared with == so this works nicely
return myColor == otherColor
}