Я перевел решение @Roman Starkov на java, если оно было необходимо, но по какой-то причине оно не сработало так хорошо, затем я начал немного читать и обнаружил, что решение очень простое, нужно сделать 2 вещи:
При изменении оттенка или насыщенности замените исходное изображение только оттенком и насыщенностью, а яркость останется такой, как была в исходном изображении, этот метод наложения называется 10.2.4. режим наложения яркости: https://www.w3.org/TR/compositing-1/#backdrop
При изменении яркости в фотошопе ползунок показывает, сколько процентов нам нужно добавить или отнять от исходной яркости, чтобы получить белый или черный цвет в HSL.
например: если исходный пиксель имеет яркость 0,7, а ползунок яркости = 20, значит, нам нужно больше 0,3 яркости, чтобы получить 1
поэтому нам нужно добавить к исходному пикселю яркости: 0,7 + 0,2 * 0,3; это будет новое значение смешанной яркости для нового пикселя.
Реализация решения @Roman Starkov на Java:
//newHue, which is photoshop_hue (i.e. 0..360)
//newSaturation, which is photoshop_saturation / 100.0 (i.e. 0..1)
//newLightness, which is photoshop_lightness / 100.0 (i.e. -1..1)
//returns rgb int array of new color
private static int[] colorizeSinglePixel(int originlPixel,int newHue,float newSaturation,float newLightness)
{
float[] originalPixelHSV = new float[3];
Color.colorToHSV(originlPixel,originalPixelHSV);
float originalPixelLightness = originalPixelHSV[2];
float[] hueRGB_HSV = {newHue,100.0f,100.0f};
int[] hueRGB = {Color.red(Color.HSVToColor(hueRGB_HSV)),Color.green(Color.HSVToColor(hueRGB_HSV)),Color.blue(Color.HSVToColor(hueRGB_HSV))};
int color[] = blend2(new int[]{128,128,128},hueRGB,newSaturation);
int blackColor[] = new int[]{Color.red(Color.BLACK),Color.green(Color.BLACK),Color.blue(Color.BLACK)};
int whileColor[] = new int[]{Color.red(Color.WHITE),Color.green(Color.WHITE),Color.blue(Color.WHITE)};
if(newLightness <= -1)
{
return blackColor;
}
else if(newLightness >=1)
{
return whileColor;
}
else if(newLightness >=0)
{
return blend3(blackColor,color,whileColor, (int) (2*(1-newLightness)*(originalPixelLightness-1) + 1));
}
else
{
return blend3(blackColor,color,whileColor, (int) ((1+newLightness)*(originalPixelLightness) - 1));
}
}
private static int[] blend2(int[] left,int[] right,float pos)
{
return new int[]{(int) (left[0]*(1-pos)+right[0]*pos),(int) (left[1]*(1-pos)+right[1]*pos),(int) (left[2]*(1-pos)+right[2]*pos)};
}
private static int[] blend3(int[] left,int[] main,int[] right,int pos)
{
if(pos < 0)
{
return blend2(left,main,pos+1);
}
else if(pos > 0)
{
return blend2(main,right,pos);
}
else
{
return main;
}
}
person
Stav Bodik
schedule
02.07.2020