Android에서 color 및 color.darker를 사용하십니까?
좋아, 내 응용 프로그램에 정수 변수가 있습니다. 내 환경 설정의 색상 선택기에 의해 설정되는 색상의 가치입니다. 이제 해당 색상과 더 어두운 색상을 모두 사용해야합니다.
이제 표준 Java에는 Color.darker () 메서드가 있지만 Android에는 해당 메서드가없는 것 같습니다. 누구든지 동등하거나 해결 방법을 알고 있습니까?
가장 쉬운 방법은 HSV로 변환하고 거기에서 어둡게 한 다음 다시 변환하는 것입니다.
float[] hsv = new float[3];
int color = getColor();
Color.colorToHSV(color, hsv);
hsv[2] *= 0.8f; // value component
color = Color.HSVToColor(hsv);
가볍게하기 위해 간단한 접근 방식은 값 구성 요소에> 1.0을 곱하는 것입니다. 그러나 결과를 [0.0, 1.0] 범위로 고정해야합니다. 또한 단순히 곱하면 검은 색이 밝아지지 않습니다.
따라서 더 나은 해결책은 다음과 같습니다. 값 구성 요소의 1.0 차이를 줄여 밝게합니다.
hsv[2] = 1.0f - 0.8f * (1.0f - hsv[2]);
이는 0 대신 원점으로 1을 사용하는 어둡게하는 방법과 완전히 유사합니다. 모든 색상 (검은 색 포함)을 밝게하는 데 작동하며 클램핑이 필요하지 않습니다. 다음과 같이 단순화 할 수 있습니다.
hsv[2] = 0.2f + 0.8f * hsv[2];
그러나 부동 소수점 산술의 가능한 반올림 효과로 인해 결과가 1.0f (아마도 1 비트)를 초과 할 수 있다는 점이 우려됩니다. 약간 더 복잡한 공식을 고수하는 것이 좋습니다.
내가 만든 것은 다음과 같습니다.
/**
* Returns darker version of specified <code>color</code>.
*/
public static int darker (int color, float factor) {
int a = Color.alpha( color );
int r = Color.red( color );
int g = Color.green( color );
int b = Color.blue( color );
return Color.argb( a,
Math.max( (int)(r * factor), 0 ),
Math.max( (int)(g * factor), 0 ),
Math.max( (int)(b * factor), 0 ) );
}
색상을 밝게하는 Ted의 답변이 저에게 효과가 없었으므로 다른 사람에게 도움이 될 수있는 솔루션이 있습니다.
/**
* Lightens a color by a given factor.
*
* @param color
* The color to lighten
* @param factor
* The factor to lighten the color. 0 will make the color unchanged. 1 will make the
* color white.
* @return lighter version of the specified color.
*/
public static int lighter(int color, float factor) {
int red = (int) ((Color.red(color) * (1 - factor) / 255 + factor) * 255);
int green = (int) ((Color.green(color) * (1 - factor) / 255 + factor) * 255);
int blue = (int) ((Color.blue(color) * (1 - factor) / 255 + factor) * 255);
return Color.argb(Color.alpha(color), red, green, blue);
}
어둡게 및 밝게하기위한 Java Color 루틴에는 특별한 것이 필요하지 않습니다. 사실, 관련 색상에 어떤 밝기가 적용되는지에 대한 이해 일뿐입니다. 즉, 단순히 빨강, 녹색, 파랑 값을 취할 수 있습니다. 어떤 요소로든 곱하고 영역에 올바르게 들어가는 지 확인하십시오.
다음은 Color 클래스에있는 코드입니다.
private static final double FACTOR = 0.7;
//...
public Color darker() {
return new Color(Math.max((int)(getRed() *FACTOR), 0),
Math.max((int)(getGreen()*FACTOR), 0),
Math.max((int)(getBlue() *FACTOR), 0),
getAlpha());
}
분명히 이것으로부터 우리는 안드로이드에서이 과정을 수행하는 방법을 볼 수 있습니다. RGB 값을 가져 와서 요소를 곱한 다음 영역에 압착합니다. (라이선스 이유로 처음부터 다시 코딩 됨).
public int crimp(int c) {
return Math.min(Math.max(c, 0), 255);
}
public int darken(int color) {
double factor = 0.7;
return (color & 0xFF000000) |
(crimp((int) (((color >> 16) & 0xFF) * factor)) << 16) |
(crimp((int) (((color >> 8) & 0xFF) * factor)) << 8) |
(crimp((int) (((color) & 0xFF) * factor)));
}
이것은 HSB에서 밝기를 높이는 것과 동일하며 B는 단순히 가장 밝은 요소이고 색조는 다양한 색상 간의 비율이며 S는 서로 얼마나 멀리 떨어져 있는지를 나타냅니다. 따라서 모든 색상을 가져 와서 요소를 곱하면 동일한 색상이 동일한 혼합에 들어가고 흰색 / 검은 색이 약간 더 많이 사용됩니다.
현대의 많은 색상 공간은 밝기에 가장 가까운 다양한 색상 구성 요소를 통해 Y 값을 계산하여이를 수행합니다. 따라서 최신 색상 공간 중 하나를 통해 더 나은 형태의 Y 또는 L로 변환하고 변환을 취소하려는 경우 다른 색상 공간은 각 색상이 실제 밝기, 밝기, 값에 얼마나 기여하는지와 관련하여 더 나은 형태의 감마를 가질 수 있습니다. 백색도, 흑색도 또는 그 색 공간이 부르는 모든 것. 이것은 더 나은 일을 할 것이지만 대부분의 경우 이것은 견고합니다.
따라서 최대한의 경우 Lab으로 변환하고 L 구성 요소를 줄인 다음 다시 변환하여이를 수행 할 수 있습니다.
이를 수행하는 코드는 다음과 같습니다.
static int darken(int color) {
double factor = 0.7;
double[] returnarray = new double[3];
convertRGBsRGB(returnarray, ((color >> 16) & 0xFF), ((color >> 8) & 0xFF), (color & 0xFF));
convertRGBXYZ(returnarray,returnarray[0], returnarray[1], returnarray[2]);
convertXYZLab(returnarray,returnarray[0], returnarray[1], returnarray[2]);
returnarray[0] *= factor;
convertLabXYZ(returnarray,returnarray[0], returnarray[1], returnarray[2]);
convertXYZRGB(returnarray,returnarray[0], returnarray[1], returnarray[2]);
return (color & 0xFF000000) | convertsRGBRGB(returnarray);
}
static void convertRGBsRGB(double[] returnarray, int R, int G, int B) {
double var_R = (((double) R) / 255.0d); //RGB from 0 to 255
double var_G = (((double) G) / 255.0d);
double var_B = (((double) B) / 255.0d);
returnarray[0] = var_R;
returnarray[1] = var_G;
returnarray[2] = var_B;
}
static int convertsRGBRGB(double[] sRGB) {
int red = (int) (sRGB[0] * 255);
int green = (int) (sRGB[1] * 255);
int blue = (int) (sRGB[2] * 255);
red = crimp(red);
green = crimp(green);
blue = crimp(blue);
return (red << 16) | (green << 8) | blue;
}
public static int crimp(int v) {
if (v > 0xff) {
v = 0xff;
}
if (v < 0) {
v = 0;
}
return v;
}
public static final double ref_X = 95.047; //ref_X = 95.047 Observer= 2°, Illuminant= D65
public static final double ref_Y = 100.000; //ref_Y = 100.000
public static final double ref_Z = 108.883;//ref_Z = 108.883
static void convertRGBXYZ(double[] returnarray, double var_R, double var_G, double var_B) {
if (var_R > 0.04045) {
var_R = Math.pow(((var_R + 0.055) / 1.055), 2.4);
} else {
var_R = var_R / 12.92;
}
if (var_G > 0.04045) {
var_G = Math.pow(((var_G + 0.055) / 1.055), 2.4);
} else {
var_G = var_G / 12.92;
}
if (var_B > 0.04045) {
var_B = Math.pow(((var_B + 0.055) / 1.055), 2.4);
} else {
var_B = var_B / 12.92;
}
var_R = var_R * 100;
var_G = var_G * 100;
var_B = var_B * 100; //Observer. = 2°, Illuminant = D65
double X = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805;
double Y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722;
double Z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505;
returnarray[0] = X;
returnarray[1] = Y;
returnarray[2] = Z;
}
static void convertXYZLab(double[] returnarray, double X, double Y, double Z) {
double var_X = X / ref_X;
double var_Y = Y / ref_Y;
double var_Z = Z / ref_Z;
if (var_X > 0.008856) {
var_X = Math.cbrt(var_X);
} else {
var_X = (7.787 * var_X) + (16.0d / 116.0d);
}
if (var_Y > 0.008856) {
var_Y = Math.cbrt(var_Y);
} else {
var_Y = (7.787 * var_Y) + (16.0d / 116.0d);
}
if (var_Z > 0.008856) {
var_Z = Math.cbrt(var_Z);
} else {
var_Z = (7.787 * var_Z) + (16.0d / 116.0d);
}
double CIE_L = (116 * var_Y) - 16;
double CIE_a = 500 * (var_X - var_Y);
double CIE_b = 200 * (var_Y - var_Z);
returnarray[0] = CIE_L;
returnarray[1] = CIE_a;
returnarray[2] = CIE_b;
}
static void convertLabXYZ(double[] returnarray, double CIE_L, double CIE_a, double CIE_b) {
double var_Y = (CIE_L + 16) / 116;
double var_X = CIE_a / 500 + var_Y;
double var_Z = var_Y - CIE_b / 200;
if ((var_Y * var_Y * var_Y) > 0.008856) {
var_Y = (var_Y * var_Y * var_Y);
} else {
var_Y = (((var_Y - 16) / 116)) / 7.787;
}
if ((var_X * var_X * var_X) > 0.008856) {
var_X = (var_X * var_X * var_X);
} else {
var_X = ((var_X - 16) / 116) / 7.787;
}
if ((var_Z * var_Z * var_Z) > 0.008856) {
var_Z = (var_Z * var_Z * var_Z);
} else {
var_Z = ((var_Z - 16) / 116) / 7.787;
}
double X = ref_X * var_X; //ref_X = 95.047 Observer= 2°, Illuminant= D65
double Y = ref_Y * var_Y; //ref_Y = 100.000
double Z = ref_Z * var_Z; //ref_Z = 108.883
returnarray[0] = X;
returnarray[1] = Y;
returnarray[2] = Z;
}
static void convertXYZRGB(double[] returnarray, double X, double Y, double Z) {
double var_X = X / 100; //X from 0 to 95.047 (Observer = 2°, Illuminant = D65)
double var_Y = Y / 100; //Y from 0 to 100.000
double var_Z = Z / 100; //Z from 0 to 108.883
double var_R = (var_X * 3.2406) + (var_Y * -1.5372) + (var_Z * -0.4986);
double var_G = (var_X * -0.9689) + (var_Y * 1.8758) + (var_Z * 0.0415);
double var_B = (var_X * 0.0557) + (var_Y * -0.2040) + (var_Z * 1.0570);
if (var_R > 0.0031308) {
var_R = 1.055 * (Math.pow(var_R, (1f / 2.4f))) - 0.055;
} else {
var_R = 12.92 * var_R;
}
if (var_G > 0.0031308) {
var_G = 1.055 * (Math.pow(var_G, (1f / 2.4f))) - 0.055;
} else {
var_G = 12.92 * var_G;
}
if (var_B > 0.0031308) {
var_B = 1.055 * (Math.pow(var_B, (1f / 2.4f))) - 0.055;
} else {
var_B = 12.92 * var_B;
}
returnarray[0] = var_R;
returnarray[1] = var_G;
returnarray[2] = var_B;
}
내 두 줄은 Color.darken ()과 동일한 작업을 수행합니다. 여기에 샘플 색상 세트의 이미지가 있습니다 (이 색상은 강력한 색상 샘플 세트로 사용하기 만하면 CIE-LabD2000을 통해 이전의 모든 색상에서 최대 거리입니다).
Index Color, Color.darker () 및 기본 darken ()은 모두 FACTOR 0.7입니다. (동일해야 함)
다음으로 Lab을 사용하여 어둡게하는 것을 제안한 사람들을 위해
인덱스 색상, Color.darker () 및 Lab Darker ()는 모두 FACTOR 0.7입니다. (이것이 시간의 가치가있는 개선인가?)
참고 URL : https://stackoverflow.com/questions/4928772/using-color-and-color-darker-in-android
'Nice programing' 카테고리의 다른 글
PIP 설치에서 libffi를 인식하더라도 ffi.h를 찾을 수 없습니다. (0) | 2020.11.25 |
---|---|
PHP 내에서 .sql 파일로드 (0) | 2020.11.25 |
Entity Framework 코어 : DbContextOptionsBuilder '에'usesqlserver '에 대한 정의가 포함되어 있지 않고 확장 메서드'usesqlserver '가 없습니다. (0) | 2020.11.25 |
작업 표시 줄에 뒤로 버튼 추가 (0) | 2020.11.25 |
최근 콘솔 명령을 모두 제거하는 방법 (0) | 2020.11.25 |