ChangeBrightContrast
Поменять яркость, оттенок, контрастность изображения C# Unity3D, Delphi.
// C# ////////////////////////////////////////////////////////////////////////////////////////////////////////////
private Texture2D texture2;
public Texture2D ChangeBSC(Texture2D texture,
float Percent_Bright, float Max_Percent_Bright,
float Percent_Shade, float Max_Percent_Shade,
float Percent_Contrast, float Max_Percent_Contrast)
{ // Поменять яркость, оттенок, контрастность всего изображения
// Пример использования: MyNewTexture = ChangeBSC (MyTexture,-50,100,80,100,50,100);
// texture = изначальное изображение
// Percent_Bright = на сколько изменить яркость в процентах от "-Max_Percent_Bright" до "Max_Percent_Bright", где 0 оставляет яркость неизменной
// Percent_Shade = на сколько изменить оттенок в процентах от "-Max_Percent_Shade" до "Max_Percent_Shade", где 0 оставляет оттенок неизменным
// Percent_Contrast = на сколько изменить контрастность в процентах от "-Max_Percent_Contrast" до "Max_Percent_Contrast", где 0 оставляет контрастность неизменной
// 255 - максимальное значение для = Max_Percent_Bright и Max_Percent_Contrast
// 1530 - максимальное значение для = Max_Percent_Shade
int Lc, Lc2, w, h, numofcolorXY;
float R, G, B, RGBmax, RGBmin, RGBmid, Bright, Shade, Contrast, MaxContrast,
LcR, LcG, LcB, CountInRow, MaxCountInRow, Sline, Zero1, Kside, NextRGBmid, DiffRGBmid,
BGW, NextMidCount = 0;
float Q,CellsCount,SideLR,E,Qmax,Qp,Qmid,Qmin;
// Корректировка, если свойства вводятся вручную //////////////////////////////
float Lp0,Lp1,D,Rm,Gm,Bm,Qrm,Qgm,Qbm;
float OldShade,CellsInRow,OnePercentStep,StepNumber,CellsInRowTriangle,Qb,Ql,Qn,Qlout; // (-1529..1529)
// -1 = уменьшить яркость, 0 = увеличить яркость
Lc = Mathf.FloorToInt(Percent_Bright/(Mathf.Abs(Percent_Bright)+1)); // -1= если "Percent_Bright<0", иначе 0
// 0 = уменьшить контрастность, 1 = увеличить контрастность
Lc2 = Mathf.FloorToInt(Percent_Contrast/(Mathf.Abs(Percent_Contrast)+1))+1; // 1= если "Percent_Contrast<0", иначе 0
// Перевести изображение "texture" в массив "Color" (с массивом "Color" напрямую работать быстрее чем с самой текстурой)
w = texture.width;
h = texture.height;
Color[] PictByColor = new Color[w * h];
PictByColor = texture.GetPixels(0, 0, w, h);
Color[] DrawByColor = new Color[w * h]; // Холст на котором будет вестись отрисовка
for (int Yy = 0; Yy < h; Yy++)
{
for (int Xx = 0; Xx < w; Xx++)
{
numofcolorXY = (h - 1 - Yy) * w + Xx; // Номер ячейки в массиве "PictByColor"
// Если не прозрачный пиксель
if (PictByColor [numofcolorXY].a > 0) {
Color color = PictByColor [numofcolorXY]; // цвет кисти
// Цвет "color" в формате от 0 до 1, (R,G,B)/255f
R = color.r;
G = color.g;
B = color.b;
// Поменять оттенок ////////////////////////////////////////////////////
R = Mathf.RoundToInt(R * 255f);
G = Mathf.RoundToInt(G * 255f);
B = Mathf.RoundToInt(B * 255f);
// Определить значение оттенка
RGBmax = (((((R + G) / 2f) + (Mathf.Abs (R - G) / 2f)) + B) / 2f) + (Mathf.Abs ((((R + G) / 2f) + (Mathf.Abs (R - G) / 2f)) - B) / 2f);
RGBmin = (((((R + G) / 2f) - (Mathf.Abs (R - G) / 2f)) + B) / 2f) - (Mathf.Abs ((((R + G) / 2f) - (Mathf.Abs (R - G) / 2f)) - B) / 2f);
Bright = (RGBmax + RGBmin) / 2f; // Яркость от 0 до 255
Contrast = (RGBmax - RGBmin) / 2f; // Контрастность от 0 до 127.5
Rm = Mathf.FloorToInt ((R - Bright) / 256f); // -1= если R<bright, 0="если" r="">=Bright
Gm = Mathf.FloorToInt ((G - Bright) / 256f); // -1= если G<bright, 0="если" g="">=Bright
Bm = Mathf.FloorToInt ((B - Bright) / 256f); // -1= если B<bright, 0="если" b="">=Bright
Qrm = (Rm + 1) * -Bm; //1= если 1 или 2 треугольник, иначе 0
Qgm = (Gm + 1) * -Rm; //1= если 3 или 4 треугольник, инач,,е 0
Qbm = (Bm + 1) * -Gm; //1= если 5 или 6 треугольник, иначе 0
Q = Qrm * (Gm + 2) + Qgm * (3 + (Bm + 1)) + Qbm * (5 + (Rm + 1)); // Номер треугольника "1..6"
Shade = (Q * 257 - 129 + Qrm * (G - (B * -Gm) - (R * (1 + Gm))) + Qgm * (B - (R * -Bm) - (G * (1 + Bm))) + Qbm * (R - (G * -Rm) - (B * (1 + Rm)))) * (Qrm + Qgm + Qbm); // Оттенок от 0 до 1540
// Поменять значение оттенка
//4. (-1529..1529) Свойства оттенка (для 5 пункта) --------------------------
OldShade = Shade; // Оттенок в треугольнике (Уже просчитанный под контрастность "NumContrast")
//Q = Mathf.FloorToInt (OldShade / 257f) + 1; // Номер треугольника "1..6"
CellsCount = OldShade - (Q * 257f - 129); // Количество ячеек от середины треугольника к краям, + вправо, - влево
E = 1 - (Q / 2f - Mathf.FloorToInt (Q / 2f)) * 2f; // Если четный треугольник то E=1, иначе E=0
//-----
//5. (-1529..1529) Проверить, находится ли оттенок в пределах одного из треугольников ------
D = 1 - 2f * (Bright - Mathf.FloorToInt (Bright)); //1=если яркость с целым числом, иначе 0
CellsInRow = (Mathf.CeilToInt (Contrast) * 2f - 1) * 6f + D * 6f; // Количество ячеек во всех 6 треугольниках, в ряду "Mathf.CeilToInt(Contrast)"
OnePercentStep = Max_Percent_Shade / CellsInRow; // Сколько ячеек из 1530, являются одним шагом для "CellsInRow" ячеек. (Пример: на контрастности=1, 6 ячеек в ряду и для прохода каждой нужно 6 шагов, по 255 ячеек за шаг)
StepNumber = Mathf.FloorToInt (Percent_Shade / OnePercentStep); // Номер ячейки в ряду "Mathf.CeilToInt(Contrast)"
Shade = StepNumber;
CellsInRowTriangle = Mathf.Abs (Mathf.CeilToInt (Contrast) * 2f - 1); // Количество ячеек в треугольнике в ряду "Mathf.CeilToInt(Contrast)", без учета четности треугольника
Ql = Mathf.FloorToInt ((Shade + CellsCount) / (CellsInRowTriangle + D)); // Приблизительное количество треугольников в указанном промежутке "Shade"
Qn = (Shade + CellsCount) - Ql * (CellsInRowTriangle + D); // Количество ячеек от центра следующего треугольника
Qlout = -Mathf.FloorToInt (((Mathf.CeilToInt (Contrast) - 1 + D * (1 - ((Ql + 1) / 2f - Mathf.FloorToInt ((Ql + 1) / 2f)) * 2f)) - Mathf.Abs (Qn)) / 1531f); //1=если "Qn" за пределами треугольника "Ql", иначе 0
Qb = Ql + Qlout; // Количество треугольников в указанном промежутке "Shade"
// Установить новый оттенок в указанном промежутке "Shade", от предыдущего оттенка "OldShade"
Shade = Qb * 257f + OldShade + (Shade - CellsInRowTriangle * Qb - D * (1 - E) * Qb);
//-----
// Если "Shade<0" или "Shade>1541", то установить "Shade" в пределах "0..1541"
Lp0 = Mathf.Abs (Mathf.FloorToInt (Shade / (Mathf.Abs (Shade) + 1))); //1= если "Shade<0", иначе 0
Lp1 = Mathf.FloorToInt ((Mathf.Abs (Shade) - Lp0) / 1542f); // Во сколько раз "Mathf.Abs(Shade)>1542"
Shade = Mathf.Abs (Shade * (Lp0 * -2 + 1) - 1542f * (Lp1 + Lp0)); // "Shade" в пределах "0..1541"
// Перевести яркость, оттенок, контрастность в RGB
Q = Mathf.FloorToInt (Shade / 257f) + 1; // Номер треугольника "1..6"
CellsCount = Shade - (Q * 257f - 129); // Количество ячеек от середины треугольника к краям, + вправо, - влево
SideLR = -Mathf.FloorToInt (CellsCount / 130f); //1= если "CellsCount < 0", 0= если "CellsCount >= 0"
E = 1 - (Q / 2f - Mathf.FloorToInt (Q / 2f)) * 2f; // Если четный треугольник то E=1, иначе E=0
Qmax = Mathf.CeilToInt (Q / 2f) - 1 + E * (1 - SideLR) - 3f * Mathf.FloorToInt (Q / 6f) * (1 - SideLR); // (0-R, 1-G, 2-B) = RGBmax
Qp = Q - Mathf.FloorToInt (Q / 4f) * 3f; // Приравнивание 6 треугольников, к 1,2,3 (1-1,2-2,3-3) (4-1,5-2,6-3)
Qmid = 2 - (Qp - SideLR - Mathf.FloorToInt (Qp / 3f) * (1 - SideLR) * 3f); // (0-R, 1-G, 2-B) = RGBmid
Qmin = 3 - (Qmax + Qmid); // (0-R, 1-G, 2-B) = RGBmin
RGBmax = Bright + Contrast; // Максимальное значение из R,G,B
RGBmin = Bright - Mathf.Abs (Contrast); // Минимальное значение из R,G,B
RGBmid = Mathf.Abs (RGBmin + (Mathf.Abs (CellsCount) - (Bright * 2f) * E) * Mathf.CeilToInt (Contrast / 129f)); // Среднее значение из R,G,B
R = Mathf.RoundToInt((Mathf.Abs (Qmax - 2 + 0.5f) - 0.5f) * RGBmax + (Mathf.Abs (Qmid - 2 + 0.5f) - 0.5f) * RGBmid + (Mathf.Abs (Qmin - 2 + 0.5f) - 0.5f) * RGBmin); // Если Qmax или Qmid или Qmin=0, то R = RGBmax или RGBmid или RGBmin соответственно
G = Mathf.RoundToInt((1 - Mathf.Abs (Qmax - 1)) * RGBmax + (1 - Mathf.Abs (Qmid - 1)) * RGBmid + (1 - Mathf.Abs (Qmin - 1)) * RGBmin); // Если Qmax или Qmid или Qmin=1, то G = RGBmax или RGBmid или RGBmin соответственно
B = Mathf.RoundToInt((Mathf.Abs (Qmax - 0.5f) - 0.5f) * RGBmax + (Mathf.Abs (Qmid - 0.5f) - 0.5f) * RGBmid + (Mathf.Abs (Qmin - 0.5f) - 0.5f) * RGBmin); // Если Qmax или Qmid или Qmin=2, то B = RGBmax или RGBmid или RGBmin соответственно
// Поменять контрастность ////////////////////////////////////////////////////
// Максимальное, минимальное значение из R,G,B
RGBmax = (((((R + G) /2f) + (Mathf.Abs(R - G) /2f)) + B) /2f) + (Mathf.Abs((((R + G) /2f) + (Mathf.Abs(R - G) /2f)) - B) /2f);
RGBmin = (((((R + G) /2f) - (Mathf.Abs(R - G) /2f)) + B) /2f) - (Mathf.Abs((((R + G) /2f) - (Mathf.Abs(R - G) /2f)) - B) /2f);
Bright = (RGBmax + RGBmin) /2f; // Яркость от 0 до 255
Contrast = (RGBmax - RGBmin) /2f; // Контрастность от 0 до 127.5
LcR = (Mathf.CeilToInt((R - Bright) /256f) * -2f) + 1; //1=Если "R" меньше "Bright", -1=если больше
LcG = (Mathf.CeilToInt((G - Bright) /256f) * -2f) + 1; //1=Если "G" меньше "Bright", -1=если больше
LcB = (Mathf.CeilToInt((B - Bright) /256f) * -2f) + 1; //1=Если "B" меньше "Bright", -1=если больше
//0 = уменьшить контрастность, 1 = увеличить контрастность
Lc2 = Mathf.FloorToInt(Percent_Contrast/(Mathf.Abs(Percent_Contrast)+1f))+1; //1= если "Percent_Bright<0", иначе 0
MaxContrast = 127.5f-Mathf.Abs(Bright-127.5f); // Определить максимальную контрастность на яркости "Bright"
RGBmid = (R + G + B)-(RGBmax+RGBmin); // Среднее значение из R,G,B
E = Mathf.CeilToInt((RGBmid+0.002f-Bright)/256f); //0=если нечетный треугольник, 1=если четный треугольник
D = 1-2f*(Bright-Mathf.FloorToInt(Bright)); //1=если яркость с целым числом, иначе 0
CountInRow = (Mathf.CeilToInt(Contrast)+E*D-1f)*2f; // Количество ячеек в основном ряду треугольника
MaxCountInRow = (Mathf.CeilToInt(MaxContrast)+E*D-1f)*2f; // Количество ячеек в целевом ряду треугольника
CellsCount = CountInRow/2f-(Mathf.Abs(RGBmax*E-(RGBmid-RGBmin*(1f-E)))); // Количество ячеек от середины треугольника
Sline = Mathf.CeilToInt((CellsCount+1f)/(CountInRow+1f))-1f; //1=если "CellsCount>CountInRow", иначе 0
Zero1 = 1f-Mathf.CeilToInt(CountInRow/254f); //1=если "CountInRow=0", иначе 0
Kside = (1f/(CountInRow+Zero1))*(CellsCount-Sline); // Коеффициент положения ячейки
NextMidCount = MaxCountInRow/2f-Mathf.Abs(Mathf.RoundToInt(Mathf.Abs(Kside)*MaxCountInRow))+Sline; // Количество ячеек от середины треугольника, в целевом ряду
NextRGBmid = Mathf.FloorToInt(Mathf.CeilToInt(Mathf.Abs(Bright+MaxContrast*(E*2f-1f)))-NextMidCount*(E*2f-1f)); // "RGBmid" в целевом ряду
DiffRGBmid = Mathf.Abs(NextRGBmid-RGBmid); // Сколько нужно приплюсовать к "RGBmid", чтобы получить "DiffRGBmid"
Rm = 1f+Mathf.FloorToInt(((RGBmax-RGBmin)-(Mathf.Abs((RGBmax-R)-(R-RGBmin))+1f))/256f); //1=если R=RGBmid, иначе 0
Gm = 1f+Mathf.FloorToInt(((RGBmax-RGBmin)-(Mathf.Abs((RGBmax-G)-(G-RGBmin))+1f))/256f); //1=если G=RGBmid, иначе 0
Bm = 1f+Mathf.FloorToInt(((RGBmax-RGBmin)-(Mathf.Abs((RGBmax-B)-(B-RGBmin))+1f))/256f); //1=если B=RGBmid, иначе 0
BGW = Mathf.CeilToInt((Mathf.Abs(R-G)+Mathf.Abs(R-B))/511f); //0=если R=G=B, иначе 1
R = Mathf.RoundToInt(Mathf.Abs(((((MaxContrast*Lc2-(Bright * LcR - R * LcR))*(1f-Rm*Lc2)+
DiffRGBmid*Rm*Lc2)*BGW * -Mathf.Abs(Percent_Contrast)) / Max_Percent_Contrast) + R * LcR));
G = Mathf.RoundToInt(Mathf.Abs(((((MaxContrast*Lc2-(Bright * LcG - G * LcG))*(1f-Gm*Lc2)+
DiffRGBmid*Gm*Lc2)*BGW * -Mathf.Abs(Percent_Contrast)) / Max_Percent_Contrast) + G * LcG));
B = Mathf.RoundToInt(Mathf.Abs(((((MaxContrast*Lc2-(Bright * LcB - B * LcB))*(1f-Bm*Lc2)+
DiffRGBmid*Bm*Lc2)*BGW * -Mathf.Abs(Percent_Contrast)) / Max_Percent_Contrast) + B * LcB));
R = R / 255f;
G = G / 255f;
B = B / 255f;
// Поменять яркость ////////////////////////////////////////////////////
R = Mathf.Abs (((((1 + Lc) + R * -(Lc * 2 + 1)) * Mathf.Abs (Percent_Bright)) / Max_Percent_Bright) - R * -(Lc * 2 + 1));
G = Mathf.Abs (((((1 + Lc) + G * -(Lc * 2 + 1)) * Mathf.Abs (Percent_Bright)) / Max_Percent_Bright) - G * -(Lc * 2 + 1));
B = Mathf.Abs (((((1 + Lc) + B * -(Lc * 2 + 1)) * Mathf.Abs (Percent_Bright)) / Max_Percent_Bright) - B * -(Lc * 2 + 1));
color.r = R;
color.g = G;
color.b = B;
DrawByColor [numofcolorXY] = color; // Нарисовать новый цвет
}
}
}
if (texture2==null)
{
texture2 = new Texture2D(w, h);
texture2.filterMode = FilterMode.Point; // Для четкой отрисовки
}
else texture2.Resize(w, h);
texture2.SetPixels(DrawByColor);
texture2.Apply();
return texture2;
}
// Delphi ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Перевести RGB в яркость, оттенок, контрастность. uses Math; function RGB_to_BSC (R,G,B:extended; out NumOfBright,NumOfShade,NumOfContrast:extended):boolean; // Перевести RGB в яркость, оттенок, контрастность var RGBmax,RGBmin,Rm,Gm,Bm,Qrm,Qgm,Qbm,Q: extended; begin RGBmax := (((((R + G) / 2) + (Abs(R - G) / 2)) + B) / 2) + (Abs((((R + G) / 2) + (Abs(R - G) / 2)) - B) / 2); RGBmin := (((((R + G) / 2) - (Abs(R - G) / 2)) + B) / 2) - (Abs((((R + G) / 2) - (Abs(R - G) / 2)) - B) / 2); NumOfBright := (RGBmax + RGBmin) / 2; // Яркость от 0 до 255 NumOfContrast := (RGBmax - RGBmin) / 2; // Контрастность от 0 до 127.5 Rm := Floor((R-NumOfBright)/256); // -1= если R<Bright, 0= если R>=Bright Gm := Floor((G-NumOfBright)/256); // -1= если G<Bright, 0= если G>=Bright Bm := Floor((B-NumOfBright)/256); // -1= если B<Bright, 0= если B>=Bright Qrm := (Rm+1)*-Bm; // 1= если 1 или 2 треугольник, иначе 0 Qgm := (Gm+1)*-Rm; // 1= если 3 или 4 треугольник, иначе 0 Qbm := (Bm+1)*-Gm; // 1= если 5 или 6 треугольник, иначе 0 Q := Qrm*(Gm+2)+Qgm*(3+(Bm+1))+Qbm*(5+(Rm+1)); // Номер треугольника "1..6" NumOfShade := (Q*257-129+Qrm*(G-(B*-Gm)-(R*(1+Gm)))+Qgm*(B-(R*-Bm)-(G*(1+Bm)))+Qbm*(R-(G*-Rm)-(B*(1+Rm))))*(Qrm+Qgm+Qbm); // Оттенок от 0 до 1540 end; procedure TForm1.Button1Click(Sender: TObject); // По нажатию кнопки var R,G,B, Main_NumOfBright, Main_NumOfShade, Main_NumOfContrast : extended; begin R := 255; G := 0; B := 0; // от 0 до 255 // Перевести RGB в яркость, оттенок, контрастность RGB_to_BSC(R,G,B, Main_NumOfBright, Main_NumOfShade, Main_NumOfContrast); Main_NumOfBright := Main_NumOfBright*2; // Поменять диапазон яркости от 0 до 510 Main_NumOfContrast := Floor(Main_NumOfContrast+0.5); // Поменять диапазон контрастности от 0 до 128 Form1.Caption := 'R: '+floattostr(R)+' G: '+floattostr(G)+' B: '+floattostr(B) +' - Яркость: '+floattostr(Main_NumOfBright)+' Оттенок: '+floattostr(Main_NumOfShade) +' Контрастность: '+floattostr(Main_NumOfContrast); end;
// Delphi //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Перевести яркость, оттенок, контрастность в RGB (Цвет указывается вручную).
uses Math;
function BSC_to_RGB_2 (NumOfBright,NumOfShade,NumOfContrast:extended; Move1:boolean;
out ChangedBright,ChangedShade,ChangedContrast:extended; out R,G,B:extended):boolean; // Перевести яркость, оттенок, контрастность в RGB (Цвет указывается вручную)
var
Q,CellsCount,SideLR,E,Qmax,Qp,Qmid,Qmin,RGBmax,RGBmin,RGBmid: extended;
// Корректировка //////////////////////////////////////////////////////////////
Lp0,Lp1,MaxContrast,D,HalfSideCount,OutOfTriangle: extended;
begin
// 0.Корректировка ///////////////////////////////////////////////////////////
// 1.Проверка яркости --------------------------------------------------------
NumOfBright := NumOfBright/2; // Перевести яркость "0...510" в формат с дробью "0.0 ... 255.0"
//-----
// Если "NumOfBright<0" или "NumOfBright>255", то поменять "NumOfBright" соответственно на 0 или 255
Lp0 := 1-abs(Floor(NumOfBright/(abs(NumOfBright)+1))); // 1= если "NumOfBright>=0", иначе 0
Lp1 := abs(Floor((255-abs(NumOfBright))/(abs(NumOfBright)+256)))*Lp0; // 1= если "abs(NumOfBright)>255", иначе 0
NumOfBright := Lp0*(NumOfBright*(1-Lp1)+255*Lp1); // "NumOfBright" в пределах "0..255"
// 2.Проверка контрастности --------------------------------------------------
// Если "NumOfContrast<0" или "NumOfContrast>128", то поменять "NumOfContrast" соответственно на 0 или 128
Lp0 := 1-abs(Floor(NumOfContrast/(abs(NumOfContrast)+1))); // 1= если "NumOfContrast>=0", иначе 0
Lp1 := abs(Floor((128-abs(NumOfContrast))/(abs(NumOfContrast)+129)))*Lp0; // 1= если "abs(NumOfContrast)>128", иначе 0
NumOfContrast := Lp0*(NumOfContrast*(1-Lp1)+128*Lp1); // "NumOfContrast" в пределах "0 ... 128"
//----- (Проверить, выходит ли контрастность за пределы максимальной контрастности "MaxContrast" на заданной яркости "NumOfBright")
NumOfContrast := Floor(NumOfContrast)-(NumOfBright-Floor(NumOfBright)); // Если яркость с дробью то добавить 0.5 к контрастности.
MaxContrast := 127.5-abs(NumOfBright-127.5); // Определить максимальную контрастность на яркости "NumOfBright"
Lp1 := abs(Floor((MaxContrast-abs(NumOfContrast))/(abs(NumOfContrast)+(MaxContrast+1)))); // 1= если "abs(NumOfContrast)>MaxContrast", иначе 0
NumOfContrast := NumOfContrast*(1-Lp1)+MaxContrast*Lp1; // "NumOfContrast" в пределах "0..MaxContrast"
// 3. (0..1541) Проверка оттенка ---------------------------------------------
// Если "NumOfShade<0" или "NumOfShade>1541", то установить "NumOfShade" в пределах "0..1541"
Lp0 := abs(Floor(NumOfShade/(abs(NumOfShade)+1))); // 1= если "NumOfShade<0", иначе 0
Lp1 := Floor((abs(NumOfShade)-Lp0)/1542); // Во сколько раз "abs(NumOfShade)>1542"
NumOfShade := abs(NumOfShade*(Lp0*-2+1)-1542*(Lp1+Lp0)); // "NumOfShade" в пределах "0..1541"
//----------------------------------------------------------------------------
// 4. (0..1541) Свойства оттенка (для 5 пункта) ------------------------------
Q := Floor(NumOfShade/257)+1; // Номер треугольника "1..6"
CellsCount := NumOfShade-(Q*257-129); // Количество ячеек от середины треугольника к краям, + вправо, - влево
SideLR := -Floor(CellsCount/130); // 1= если "CellsCount < 0", 0= если "CellsCount >= 0"
E := 1-(Q/2-Floor(Q/2))*2; // Если четный треугольник то E=1, иначе E=0
//-----
// 5. (0..1541) Проверить, находится ли оттенок в пределах одного из треугольников ------
D := 1-2*(NumOfBright-Floor(NumOfBright)); // 1=если яркость с целым числом, иначе 0
HalfSideCount := Ceil(NumOfContrast)+E*D-1; // Количество ячеек сбоку от треугольника, не учитывая центр
OutOfTriangle := -Floor((HalfSideCount-abs(CellsCount))/130); // 1= если "NumOfShade" за пределами треугольника, иначе 0
if (Move1 = true) then // Перейти к правому треугольнику если оттенок выходит за пределы с правой стороны от треугольника "Q" или к левому треугольнику если выходит за пределы слева от "Q", иначе оставить оттенок "NumOfShade" как есть
NumOfShade := (OutOfTriangle*((Q*257-129)+(129+(128-(Ceil(NumOfContrast)-1))-(1-E)*D)*(SideLR*-2+1))
+(1-OutOfTriangle)*NumOfShade)*Ceil(NumOfContrast/129)
else // Оставить оттенок в "Q" треугольнике справа если оттенок выходит за пределы с правой стороны или в "Q" треугольнике слева если выходит за пределы слева от "Q", иначе оставить оттенок "NumOfShade" как есть
NumOfShade := (OutOfTriangle*((Q*257-129)+HalfSideCount*(SideLR*-2+1))+(1-OutOfTriangle)*NumOfShade)*Ceil(NumOfContrast/129);
//-----
// Если "NumOfShade<0" или "NumOfShade>1541", то установить "NumOfShade" в пределах "0..1541"
Lp0 := abs(Floor(NumOfShade/(abs(NumOfShade)+1))); // 1= если "NumOfShade<0", иначе 0
Lp1 := Floor((abs(NumOfShade)-Lp0)/1542); // Во сколько раз "abs(NumOfShade)>1542"
NumOfShade := abs(NumOfShade*(Lp0*-2+1)-1542*(Lp1+Lp0)); // "NumOfShade" в пределах "0..1541"
// 6. (0..1541) Вывести за пределы функции измененные значения яркости, оттенка, контрастности ----
ChangedBright := Floor(NumOfBright*2); // Новая яркость
ChangedShade := Floor(NumOfShade); // Новый оттенок
ChangedContrast := Floor(NumOfContrast+0.5); // Новая контрастность
//////////////////////////////////////////////////////////////////////////////
// Перевести яркость, оттенок, контрастность в RGB ///////////////////////////
Q := Floor(NumOfShade/257)+1; // Номер треугольника "1..6"
CellsCount := NumOfShade-(Q*257-129); // Количество ячеек от середины треугольника к краям, + вправо, - влево
SideLR := -Floor(CellsCount/130); // 1= если "CellsCount < 0", 0= если "CellsCount >= 0"
E := 1-(Q/2-Floor(Q/2))*2; // Если четный треугольник то E=1, иначе E=0
Qmax := Ceil(Q/2)-1+E*(1-SideLR)-3*Floor(Q/6)*(1-SideLR); // (0-R, 1-G, 2-B) = RGBmax
Qp := Q-Floor(Q/4)*3; // Приравнивание 6 треугольников, к 1,2,3 (1-1,2-2,3-3) (4-1,5-2,6-3)
Qmid := 2-(Qp-SideLR-Floor(Qp/3)*(1-SideLR)*3); // (0-R, 1-G, 2-B) = RGBmid
Qmin := 3-(Qmax+Qmid); // (0-R, 1-G, 2-B) = RGBmin
RGBmax := NumOfBright+NumOfContrast; // Максимальное значение из R,G,B
RGBmin := NumOfBright-abs(NumOfContrast); // Минимальное значение из R,G,B
RGBmid := abs(RGBmin+(abs(CellsCount)-(NumOfBright*2)*E)*Ceil(NumOfContrast/129)); // Среднее значение из R,G,B
R := Round((abs(Qmax-2+0.5)-0.5)*RGBmax+(abs(Qmid-2+0.5)-0.5)*RGBmid+(abs(Qmin-2+0.5)-0.5)*RGBmin); // Если Qmax или Qmid или Qmin=0, то R = RGBmax или RGBmid или RGBmin соответственно
G := Round((1-abs(Qmax-1))*RGBmax+(1-abs(Qmid-1))*RGBmid+(1-abs(Qmin-1))*RGBmin); // Если Qmax или Qmid или Qmin=1, то G = RGBmax или RGBmid или RGBmin соответственно
B := Round((abs(Qmax-0.5)-0.5)*RGBmax+(abs(Qmid-0.5)-0.5)*RGBmid+(abs(Qmin-0.5)-0.5)*RGBmin); // Если Qmax или Qmid или Qmin=2, то B = RGBmax или RGBmid или RGBmin соответственно
//////////////////////////////////////////////////////////////////////////////
end;
procedure TForm1.Button4Click(Sender: TObject); // По нажатию кнопки
var
R,G,B, Main_NumOfBright, Main_NumOfShade, Main_NumOfContrast,
ChangedBright, ChangedShade, ChangedContrast : extended;
begin
Main_NumOfBright := 255; // Яркость, от 0 до 510
Main_NumOfShade := 1027; // Оттенок, от 0 до 1541 (0 и 1541 переходные значения между 1 и 6 треугольником)
Main_NumOfContrast := 200; // Контрастность, от 0 до 128 (0=черно-белые оттенки)
// Перевести яркость, оттенок, контрастность в RGB (Цвет указывается вручную) (true-переходить к следующим треугольникам если оттенок за пределами, false-оставаться в пределах указанного треугольника)
BSC_to_RGB_2(Main_NumOfBright, Main_NumOfShade, Main_NumOfContrast, true,
ChangedBright,ChangedShade,ChangedContrast, R,G,B);
Form1.Caption := 'B: '+floattostr(Main_NumOfBright) +' S: '+floattostr(Main_NumOfShade)
+' C: '+floattostr(Main_NumOfContrast) +' |nB: '+floattostr(ChangedBright)
+' nS: '+floattostr(ChangedShade)+' nC: '+floattostr(ChangedContrast)
+'| R: '+floattostr(R)+' G: '+floattostr(G)+' B: '+floattostr(B);
end;
// Delphi ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Перевести яркость, оттенок, контрастность в RGB. uses Math; function BSC_to_RGB (NumOfBright,NumOfShade,NumOfContrast:extended; out R,G,B:extended):boolean; // Перевести яркость, оттенок, контрастность в RGB var Q,CellsCount,SideLR,E,Qmax,Qp,Qmid,Qmin,RGBmax,RGBmin,RGBmid: extended; begin Q := Floor(NumOfShade/257)+1; // Номер треугольника "1..6" CellsCount := NumOfShade-(Q*257-129); // Количество ячеек от середины треугольника к краям, + вправо, - влево SideLR := -Floor(CellsCount/130); // 1= если "CellsCount < 0", 0= если "CellsCount >= 0" E := 1-(Q/2-Floor(Q/2))*2; // Если четный треугольник то E=1, иначе E=0 Qmax := Ceil(Q/2)-1+E*(1-SideLR)-3*Floor(Q/6)*(1-SideLR); // (0-R, 1-G, 2-B) = RGBmax Qp := Q-Floor(Q/4)*3; // Приравнивание 6 треугольников, к 1,2,3 (1-1,2-2,3-3) (4-1,5-2,6-3) Qmid := 2-(Qp-SideLR-Floor(Qp/3)*(1-SideLR)*3); // (0-R, 1-G, 2-B) = RGBmid Qmin := 3-(Qmax+Qmid); // (0-R, 1-G, 2-B) = RGBmin RGBmax := NumOfBright+NumOfContrast; // Максимальное значение из R,G,B RGBmin := NumOfBright-abs(NumOfContrast); // Минимальное значение из R,G,B RGBmid := abs(RGBmin+(abs(CellsCount)-(NumOfBright*2)*E)*Ceil(NumOfContrast/129)); // Среднее значение из R,G,B R := Round((abs(Qmax-2+0.5)-0.5)*RGBmax+(abs(Qmid-2+0.5)-0.5)*RGBmid+(abs(Qmin-2+0.5)-0.5)*RGBmin); // Если Qmax или Qmid или Qmin=0, то R = RGBmax или RGBmid или RGBmin соответственно G := Round((1-abs(Qmax-1))*RGBmax+(1-abs(Qmid-1))*RGBmid+(1-abs(Qmin-1))*RGBmin); // Если Qmax или Qmid или Qmin=1, то G = RGBmax или RGBmid или RGBmin соответственно B := Round((abs(Qmax-0.5)-0.5)*RGBmax+(abs(Qmid-0.5)-0.5)*RGBmid+(abs(Qmin-0.5)-0.5)*RGBmin); // Если Qmax или Qmid или Qmin=2, то B = RGBmax или RGBmid или RGBmin соответственно end; procedure TForm1.Button2Click(Sender: TObject); // По нажатию кнопки var R,G,B, Main_NumOfBright, Main_NumOfShade, Main_NumOfContrast : extended; begin Main_NumOfBright := 127.5; // Яркость, от 0 до 255 Main_NumOfShade := 128; // Оттенок, от 1 до 1540 Main_NumOfContrast := 127.5; // Контрастность, от 0 до 127.5 (0=черно-белые оттенки) BSC_to_RGB(Main_NumOfBright, Main_NumOfShade, Main_NumOfContrast, R,G,B); // Перевести яркость, оттенок, контрастность в RGB Main_NumOfBright := Main_NumOfBright*2; // Поменять диапазон яркости от 0 до 510 Main_NumOfContrast := Floor(Main_NumOfContrast+0.5); // Поменять диапазон контрастности от 0 до 128 Form1.Caption := 'Яркость: '+floattostr(Main_NumOfBright)+' Оттенок: '+floattostr(Main_NumOfShade) +' Контрастность: '+floattostr(Main_NumOfContrast) +' - R: '+floattostr(R)+' G: '+floattostr(G)+' B: '+floattostr(B); end;
// Delphi //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Поменять контрастность RGB.
uses Math;
function RGB_Contrast (R,G,B, Max_Percent_Contrast,Percent_Contrast:extended;
out R2,G2,B2:extended):boolean; // Поменять контрастность RGB
var
RGBmax,RGBmin,NumOfBright,NumOfContrast,LcR,LcG,LcB,Lc2,MaxNumOfContrast,
RGBmid,E,D,CountInRow,MaxCountInRow,CellsCount,Sline,Zero1,Kside,NextMidCount,
NextRGBmid,DiffRGBmid,Rm,Gm,Bm,BGW:extended;
begin
// Максимальное, минимальное значение из R,G,B
RGBmax := (((((R + G) / 2) + (Abs (R - G) / 2)) + B) / 2) + (Abs ((((R + G) / 2) + (Abs (R - G) / 2)) - B) / 2);
RGBmin := (((((R + G) / 2) - (Abs (R - G) / 2)) + B) / 2) - (Abs ((((R + G) / 2) - (Abs (R - G) / 2)) - B) / 2);
NumOfBright := (RGBmax + RGBmin) / 2; // Яркость от 0 до 255
NumOfContrast := (RGBmax - RGBmin) / 2; // Контрастность от 0 до 127.5
LcR := (Ceil ((R - NumOfBright) / 256) * -2) + 1; // 1=Если "R" меньше "NumOfBright", -1=если больше
LcG := (Ceil ((G - NumOfBright) / 256) * -2) + 1; // 1=Если "G" меньше "NumOfBright", -1=если больше
LcB := (Ceil ((B - NumOfBright) / 256) * -2) + 1; // 1=Если "B" меньше "NumOfBright", -1=если больше
// 0 = уменьшить контрастность, 1 = увеличить контрастность
Lc2 := Floor(Percent_Contrast/(Abs(Percent_Contrast)+1))+1; // 1= если "Percent_NumOfBright<0", иначе 0
MaxNumOfContrast := 127.5-abs(NumOfBright-127.5); // Определить максимальную контрастность на яркости "NumOfBright"
RGBmid := (R + G + B)-(RGBmax+RGBmin); // Среднее значение из R,G,B
E := Ceil((RGBmid+0.002-NumOfBright)/256); // 0=если нечетный треугольник, 1=если четный треугольник
D := 1-2*(NumOfBright-Floor(NumOfBright)); // 1=если яркость с целым числом, иначе 0
CountInRow := (Ceil(NumOfContrast)+E*D-1)*2; // Количество ячеек в основном ряду треугольника
MaxCountInRow := (Ceil(MaxNumOfContrast)+E*D-1)*2; // Количество ячеек в целевом ряду треугольника
CellsCount := CountInRow/2-(abs(RGBmax*E-(RGBmid-RGBmin*(1-E)))); // Количество ячеек от середины треугольника
Sline := Ceil((CellsCount+1)/(CountInRow+1))-1; // 1=если "CellsCount>CountInRow", иначе 0
Zero1 := 1-Ceil(CountInRow/254); // 1=если "CountInRow=0", иначе 0
Kside := (1/(CountInRow+Zero1))*(CellsCount-Sline); // Коеффициент положения ячейки
NextMidCount := MaxCountInRow/2-abs(Round(abs(Kside)*MaxCountInRow))+Sline; // Количество ячеек от середины треугольника, в целевом ряду
NextRGBmid := Floor(Ceil(abs(NumOfBright+MaxNumOfContrast*(E*2-1)))-NextMidCount*(E*2-1)); // "RGBmid" в целевом ряду
DiffRGBmid := abs(NextRGBmid-RGBmid); // Сколько нужно приплюсовать к "RGBmid", чтобы получить "DiffRGBmid"
Rm := 1+Floor(((RGBmax-RGBmin)-(abs((RGBmax-R)-(R-RGBmin))+1))/256); // 1=если R=RGBmid, иначе 0
Gm := 1+Floor(((RGBmax-RGBmin)-(abs((RGBmax-G)-(G-RGBmin))+1))/256); // 1=если G=RGBmid, иначе 0
Bm := 1+Floor(((RGBmax-RGBmin)-(abs((RGBmax-B)-(B-RGBmin))+1))/256); // 1=если B=RGBmid, иначе 0
BGW := Ceil((abs(R-G)+abs(R-B))/511); // 0=если R=G=B, иначе 1
R2 := Round(Abs(((((MaxNumOfContrast*Lc2-(NumOfBright * LcR - R * LcR))*(1-Rm*Lc2)+
DiffRGBmid*Rm*Lc2)*BGW * -abs(Percent_Contrast)) / Max_Percent_Contrast) + R * LcR));
G2 := Round(Abs(((((MaxNumOfContrast*Lc2-(NumOfBright * LcG - G * LcG))*(1-Gm*Lc2)+
DiffRGBmid*Gm*Lc2)*BGW * -abs(Percent_Contrast)) / Max_Percent_Contrast) + G * LcG));
B2 := Round(Abs(((((MaxNumOfContrast*Lc2-(NumOfBright * LcB - B * LcB))*(1-Bm*Lc2)+
DiffRGBmid*Bm*Lc2)*BGW * -abs(Percent_Contrast)) / Max_Percent_Contrast) + B * LcB));
end;
procedure TForm1.Button3Click(Sender: TObject);
var
R,G,B,R2,G2,B2,Max_Percent_Contrast,Percent_Contrast: extended;
begin
R := 199; G := 56; B := 56; // от 0 до 255
Max_Percent_Contrast := 128; // Максимально допустимое значение контрастности (255= Учитывать треугольники на яркости с дробью и без, 128= Учитывать треугольники только одного типа яркости)
Percent_Contrast := -64; // На сколько процентов поменять контрастность от –Max_Percent_Contrast до Max_Percent_Contrast
// Поменять контрастность RGB
RGB_Contrast (R,G,B, Max_Percent_Contrast,Percent_Contrast, R2,G2,B2);
Form1.Caption := 'R: '+floattostr(R)+' G: '+floattostr(G)+' B: '+floattostr(B)
+' |Поменять контрастность на '+floattostr(Percent_Contrast)
+'% из '+floattostr(Max_Percent_Contrast)
+'| R2: '+floattostr(R2)+' G2: '+floattostr(G2)+' B2: '+floattostr(B2);
end;
// Delphi //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Поменять оттенок RGB.
uses Math;
function RGB_Shade (NumOfBright,NumOfShade,NumOfContrast,PlusShade:extended; RightColor:boolean;
out ChangedBright,ChangedShade,ChangedContrast,ChangedShadeMin,ChangedShadeMax:extended;
out R,G,B:extended):boolean; // Поменять оттенок RGB
var
Q,CellsCount,SideLR,E,Qmax,Qp,Qmid,Qmin,RGBmax,RGBmin,RGBmid: extended;
// Корректировка //////////////////////////////////////////////////////////////
Lp0,Lp1,MaxContrast,D,HalfSideCount,OutOfTriangle: extended;
CellsInRow,OnePercentStep,StepNumber,CellsInRowTriangle,Qb,Ql,Qn,Qlout: extended;
begin
// 0.Корректировка ///////////////////////////////////////////////////////////
if (RightColor = false) then // Цвет указывается вручную
begin
// 1.Проверка яркости --------------------------------------------------------
NumOfBright := NumOfBright/2; // Перевести яркость "0...510" в формат с дробью "0.0 ... 255.0"
//-----
// Если "NumOfBright<0" или "NumOfBright>255", то поменять "NumOfBright" соответственно на 0 или 255
Lp0 := 1-abs(Floor(NumOfBright/(abs(NumOfBright)+1))); // 1= если "NumOfBright>=0", иначе 0
Lp1 := abs(Floor((255-abs(NumOfBright))/(abs(NumOfBright)+256)))*Lp0; // 1= если "abs(NumOfBright)>255", иначе 0
NumOfBright := Lp0*(NumOfBright*(1-Lp1)+255*Lp1); // "NumOfBright" в пределах "0..255"
// 2.Проверка контрастности --------------------------------------------------
// Если "NumOfContrast<0" или "NumOfContrast>128", то поменять "NumOfContrast" соответственно на 0 или 128
Lp0 := 1-abs(Floor(NumOfContrast/(abs(NumOfContrast)+1))); // 1= если "NumOfContrast>=0", иначе 0
Lp1 := abs(Floor((128-abs(NumOfContrast))/(abs(NumOfContrast)+129)))*Lp0; // 1= если "abs(NumOfContrast)>128", иначе 0
NumOfContrast := Lp0*(NumOfContrast*(1-Lp1)+128*Lp1); // "NumOfContrast" в пределах "0 ... 128"
//----- (Проверить, выходит ли контрастность за пределы максимальной контрастности "MaxContrast" на заданной яркости "NumOfBright")
NumOfContrast := Floor(NumOfContrast)-(NumOfBright-Floor(NumOfBright)); // Если яркость с дробью то добавить 0.5 к контрастности.
MaxContrast := 127.5-abs(NumOfBright-127.5); // Определить максимальную контрастность на яркости "NumOfBright"
Lp1 := abs(Floor((MaxContrast-abs(NumOfContrast))/(abs(NumOfContrast)+(MaxContrast+1)))); // 1= если "abs(NumOfContrast)>MaxContrast", иначе 0
NumOfContrast := NumOfContrast*(1-Lp1)+MaxContrast*Lp1; // "NumOfContrast" в пределах "0..MaxContrast"
// 3. (-1529..1529) Проверка оттенка -----------------------------------------
// Если "PlusShade<-1529" или "PlusShade>1529", то поменять "PlusShade" соответственно на -1529 или 1529
Lp0 := Floor(PlusShade/(abs(PlusShade)+1))*2+1; // 1= если "PlusShade>=0", иначе -1
Lp1 := abs(Floor((1529-abs(PlusShade))/(abs(PlusShade)+1530))); // 1= если "abs(PlusShade)>1529", иначе 0
PlusShade := Lp0*abs(PlusShade*(1-Lp1)+1529*Lp1); // "PlusShade" в пределах "-1529..1529"
//----------------------------------------------------------------------------
// 4. (0..1541) Свойства оттенка (для 5 пункта) ------------------------------
Q := Floor(NumOfShade/257)+1; // Номер треугольника "1..6"
CellsCount := NumOfShade-(Q*257-129); // Количество ячеек от середины треугольника к краям, + вправо, - влево
SideLR := -Floor(CellsCount/130); // 1= если "CellsCount < 0", 0= если "CellsCount >= 0"
E := 1-(Q/2-Floor(Q/2))*2; // Если четный треугольник то E=1, иначе E=0
//-----
// 5. (0..1541) Проверить, находится ли оттенок в пределах одного из треугольников ------
D := 1-2*(NumOfBright-Floor(NumOfBright)); // 1=если яркость с целым числом, иначе 0
HalfSideCount := Ceil(NumOfContrast)+E*D-1; // Количество ячеек сбоку от треугольника, не учитывая центр
OutOfTriangle := -Floor((HalfSideCount-abs(CellsCount))/130); // 1= если "NumOfShade" за пределами треугольника, иначе 0
// Оставить оттенок в "Q" треугольнике справа если оттенок выходит за пределы с правой стороны или в "Q" треугольнике слева если выходит за пределы слева от "Q", иначе оставить оттенок "NumOfShade" как есть
NumOfShade := (OutOfTriangle*((Q*257-129)+HalfSideCount*(SideLR*-2+1))+(1-OutOfTriangle)*NumOfShade)*Ceil(NumOfContrast/129);
end
else // Цвет точно находится в треугольнике
begin
NumOfBright := NumOfBright/2; // Перевести яркость "0...510" в формат с дробью "0.0 ... 255.0"
NumOfContrast := Floor(NumOfContrast)-(NumOfBright-Floor(NumOfBright)); // Если яркость с дробью то добавить 0.5 к контрастности.
end;
// 4. (-1529..1529) Свойства оттенка (для 5 пункта) --------------------------
//NumOfShade := 128; // Оттенок в треугольнике (Уже просчитанный под контрастность "NumContrast")
Q := Floor(NumOfShade/257)+1; // Номер треугольника "1..6"
CellsCount := NumOfShade-(Q*257-129); // Количество ячеек от середины треугольника к краям, + вправо, - влево
E := 1-(Q/2-Floor(Q/2))*2; // Если четный треугольник то E=1, иначе E=0
//-----
// 5. (-1529..1529) Проверить, находится ли оттенок в пределах одного из треугольников ------
D := 1-2*(NumOfBright-Floor(NumOfBright)); // 1=если яркость с целым числом, иначе 0
CellsInRow := (Ceil(NumOfContrast)*2-1)*6+D*6; // Количество ячеек во всех 6 треугольниках, в ряду "Ceil(NumOfContrast)"
//OnePercentStep := 1530/CellsInRow; // Сколько ячеек из 1530, являются одним шагом для "CellsInRow" ячеек. (Пример: на контрастности=1, 6 ячеек в ряду и для прохода каждой нужно 6 шагов, по 255 ячеек за шаг)
//StepNumber := Floor(PlusShade/OnePercentStep); // Номер ячейки в ряду "Ceil(NumOfContrast)"
//PlusShade := StepNumber;
CellsInRowTriangle := abs(Ceil(NumOfContrast)*2-1); // Количество ячеек в треугольнике в ряду "Ceil(NumOfContrast)", без учета четности треугольника
Ql := Floor((PlusShade+CellsCount)/(CellsInRowTriangle+D)); // Приблизительное количество треугольников в указанном промежутке "PlusShade"
Qn := (PlusShade+CellsCount)-Ql*(CellsInRowTriangle+D); // Количество ячеек от центра следующего треугольника
Qlout := -Floor(((Ceil(NumOfContrast)-1+D*(1-((Ql+1)/2-Floor((Ql+1)/2))*2))-abs(Qn))/1531); // 1=если "Qn" за пределами треугольника "Ql", иначе 0
Qb := Ql+Qlout; // Количество треугольников в указанном промежутке "PlusShade"
// Установить новый оттенок в указанном промежутке "PlusShade", от предыдущего оттенка "NumOfShade"
NumOfShade := Qb*257+NumOfShade+(PlusShade-CellsInRowTriangle*Qb-D*(1-E)*Qb);
//-----
// Если "NumOfShade<0" или "NumOfShade>1541", то установить "NumOfShade" в пределах "0..1541"
Lp0 := abs(Floor(NumOfShade/(abs(NumOfShade)+1))); // 1= если "NumOfShade<0", иначе 0
Lp1 := Floor((abs(NumOfShade)-Lp0)/1542); // Во сколько раз "abs(NumOfShade)>1542"
NumOfShade := abs(NumOfShade*(Lp0*-2+1)-1542*(Lp1+Lp0)); // "NumOfShade" в пределах "0..1541"
// 6. (-1529..1529) Вывести за пределы функции измененные значения яркости, оттенка, контрастности ----
ChangedBright := Floor(NumOfBright*2); // Новая яркость
ChangedShade := Floor(NumOfShade); // Новый оттенок
ChangedShadeMax := Floor(CellsInRow); // Границы оттенка
ChangedShadeMin := -Floor(CellsInRow);
ChangedContrast := Floor(NumOfContrast+0.5); // Новая контрастность
//////////////////////////////////////////////////////////////////////////////
// Перевести яркость, оттенок, контрастность в RGB ///////////////////////////
Q := Floor(NumOfShade/257)+1; // Номер треугольника "1..6"
CellsCount := NumOfShade-(Q*257-129); // Количество ячеек от середины треугольника к краям, + вправо, - влево
SideLR := -Floor(CellsCount/130); // 1= если "CellsCount < 0", 0= если "CellsCount >= 0"
E := 1-(Q/2-Floor(Q/2))*2; // Если четный треугольник то E=1, иначе E=0
Qmax := Ceil(Q/2)-1+E*(1-SideLR)-3*Floor(Q/6)*(1-SideLR); // (0-R, 1-G, 2-B) = RGBmax
Qp := Q-Floor(Q/4)*3; // Приравнивание 6 треугольников, к 1,2,3 (1-1,2-2,3-3) (4-1,5-2,6-3)
Qmid := 2-(Qp-SideLR-Floor(Qp/3)*(1-SideLR)*3); // (0-R, 1-G, 2-B) = RGBmid
Qmin := 3-(Qmax+Qmid); // (0-R, 1-G, 2-B) = RGBmin
RGBmax := NumOfBright+NumOfContrast; // Максимальное значение из R,G,B
RGBmin := NumOfBright-abs(NumOfContrast); // Минимальное значение из R,G,B
RGBmid := abs(RGBmin+(abs(CellsCount)-(NumOfBright*2)*E)*Ceil(NumOfContrast/129)); // Среднее значение из R,G,B
R := Round((abs(Qmax-2+0.5)-0.5)*RGBmax+(abs(Qmid-2+0.5)-0.5)*RGBmid+(abs(Qmin-2+0.5)-0.5)*RGBmin); // Если Qmax или Qmid или Qmin=0, то R = RGBmax или RGBmid или RGBmin соответственно
G := Round((1-abs(Qmax-1))*RGBmax+(1-abs(Qmid-1))*RGBmid+(1-abs(Qmin-1))*RGBmin); // Если Qmax или Qmid или Qmin=1, то G = RGBmax или RGBmid или RGBmin соответственно
B := Round((abs(Qmax-0.5)-0.5)*RGBmax+(abs(Qmid-0.5)-0.5)*RGBmid+(abs(Qmin-0.5)-0.5)*RGBmin); // Если Qmax или Qmid или Qmin=2, то B = RGBmax или RGBmid или RGBmin соответственно
//////////////////////////////////////////////////////////////////////////////
end;
procedure TForm1.TrackBar1Change(Sender: TObject); // Если передвинут ползунок "TrackBar1"
var
R,G,B, Main_NumOfBright, Main_NumOfShade, Main_NumOfContrast, PlusShade,
ChangedBright, ChangedShade, ChangedContrast, ChangedShadeMin, ChangedShadeMax : extended;
begin
//R := 170; G := 0; B := 0; // от 0 до 255
//RGB_to_BSC(R,G,B, Main_NumOfBright, Main_NumOfShade, Main_NumOfContrast); // Перевести RGB в яркость, оттенок, контрастность
//Main_NumOfBright := Main_NumOfBright*2; // Поменять диапазон яркости от 0 до 510
//Main_NumOfContrast := Floor(Main_NumOfContrast+0.5); // Поменять диапазон контрастности от 0 до 128
Main_NumOfBright := 170; // Яркость, от 0 до 510
Main_NumOfShade := 128; // Оттенок, от 1 до 1540
Main_NumOfContrast := 85; // Контрастность, от 0 до 128 (0=черно-белые оттенки)
PlusShade := TrackBar1.Position; // Прибавить к оттенку от -1529 до 1529
// Поменять оттенок RGB (true- цвет точно находится в треугольнике, false- цвет указывается вручную)
RGB_Shade(Main_NumOfBright, Main_NumOfShade, Main_NumOfContrast, PlusShade, false,
ChangedBright,ChangedShade,ChangedContrast,ChangedShadeMin,ChangedShadeMax,
R,G,B);
if ((TrackBar1.Min<>ChangedShadeMin) or (TrackBar1.Max<>ChangedShadeMax)) then
begin
TrackBar1.Min := Floor(ChangedShadeMin);
TrackBar1.Max := Floor(ChangedShadeMax);
end;
Form1.Caption := 'B: '+floattostr(Main_NumOfBright) +' S: '+floattostr(Main_NumOfShade)
+' C: '+floattostr(Main_NumOfContrast) +' plus: '+floattostr(PlusShade) +' |nB: '+floattostr(ChangedBright)
+' nS: '+floattostr(ChangedShade)+' nC: '+floattostr(ChangedContrast)
+' min: '+floattostr(ChangedShadeMin)+' max: '+floattostr(ChangedShadeMax)
+'| R: '+floattostr(R)+' G: '+floattostr(G)+' B: '+floattostr(B);
end;
// Delphi //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Поменять яркость RGB.
uses Math;
function RGB_Bright (R,G,B, Max_Percent_Bright,Percent_Bright: extended;
out R2,G2,B2:extended):boolean; // Поменять яркость RGB
var
Lc: extended;
begin
Lc := Floor(Percent_Bright/(Abs(Percent_Bright)+1)); // -1 = уменьшить яркость, 0 = увеличить яркость
// RGB в формат 0...1
R := R/255;
G := G/255;
B := B/255;
// Поменять яркость
R := Abs (((((1 + Lc) + R * -(Lc * 2 + 1)) * Abs (Percent_Bright)) / Max_Percent_Bright) - R * -(Lc * 2 + 1));
G := Abs (((((1 + Lc) + G * -(Lc * 2 + 1)) * Abs (Percent_Bright)) / Max_Percent_Bright) - G * -(Lc * 2 + 1));
B := Abs (((((1 + Lc) + B * -(Lc * 2 + 1)) * Abs (Percent_Bright)) / Max_Percent_Bright) - B * -(Lc * 2 + 1));
// RGB в формат 0...255
R2 := Round(R * 255);
G2 := Round(G * 255);
B2 := Round(B * 255);
end;
procedure TForm1.Button5Click(Sender: TObject);
var
R,G,B,R2,G2,B2,Max_Percent_Bright,Percent_Bright: extended;
begin
R := 255; G := 0; B := 0;
Max_Percent_Bright := 255; // Максимально допустимое значение яркости (Максимальная яркость = 255)
Percent_Bright := -127; // На сколько процентов поменять яркость
// Поменять яркость RGB
RGB_Bright (R,G,B, Max_Percent_Bright,Percent_Bright, R2,G2,B2);
Form1.Caption := 'R: '+floattostr(R)+' G: '+floattostr(G)+' B: '+floattostr(B)
+' |Поменять яркость на '+floattostr(Percent_Bright)
+'% из '+floattostr(Max_Percent_Bright)
+'| R2: '+floattostr(R2)+' G2: '+floattostr(G2)+' B2: '+floattostr(B2);
end;
// Delphi //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Порядковый номер RGB.
uses Math;
function RGB_Number (R,G,B:extended; out MainNumberInRow:extended):boolean; // Найти порядковый номер R,G,B ( черно-белые оттенки = 0-255; цветные оттенки = 256-16777215 )
var
RGBmax,RGBmin,Bright,Contrast, Rm,Gm,Bm,Qrm,Qgm,Qbm,Q,Shade,RGBmid,
E,D,CountInRow,CellsInRow,CellsCount, NumberBeforeRow,NumberInRow,NumberInBright,
MaxContrast,CountBright1,CountBright2,CountBright3, CountMultiply1,CountMultiply2,CountCells127_5,
Bright127_5,MainCountCells,BGW: extended;
begin
// Максимальное, минимальное значение из R,G,B
RGBmax := (((((R + G) / 2) + (Abs(R - G) / 2)) + B) / 2) + (Abs((((R + G) / 2) + (Abs(R - G) / 2)) - B) / 2);
RGBmin := (((((R + G) / 2) - (Abs(R - G) / 2)) + B) / 2) - (Abs((((R + G) / 2) - (Abs(R - G) / 2)) - B) / 2);
Bright := (RGBmax + RGBmin) / 2; // Яркость от 0 до 255
Contrast := (RGBmax - RGBmin) / 2; // Контрастность от 0 до 127.5
Rm := Floor((R-Bright)/256); // -1= если R<Bright, 0= если R>=Bright
Gm := Floor((G-Bright)/256); // -1= если G<Bright, 0= если G>=Bright
Bm := Floor((B-Bright)/256); // -1= если B<Bright, 0= если B>=Bright
Qrm := (Rm+1)*-Bm; // 1= если 1 или 2 треугольник, иначе 0
Qgm := (Gm+1)*-Rm; // 1= если 3 или 4 треугольник, иначе 0
Qbm := (Bm+1)*-Gm; // 1= если 5 или 6 треугольник, иначе 0
Q := Qrm*(Gm+2)+Qgm*(3+(Bm+1))+Qbm*(5+(Rm+1)); // Номер треугольника "1..6"
Shade := (Q*257-129+Qrm*(G-(B*-Gm)-(R*(1+Gm)))+Qgm*(B-(R*-Bm)-(G*(1+Bm)))+Qbm*(R-(G*-Rm)-(B*(1+Rm))))*(Qrm+Qgm+Qbm); // Оттенок от 0 до 1540
RGBmid := (R + G + B)-(RGBmax+RGBmin); // Среднее значение из R,G,B
E := Ceil((RGBmid+0.002-Bright)/256); // 0=если нечетный треугольник, 1=если четный треугольник
D := 1-2*(Bright-Floor(Bright)); // 1=если яркость с целым числом, иначе 0
CountInRow := (Ceil(Contrast)+E*D-1)*2; // Количество ячеек в основном ряду треугольника -1
CellsInRow := (Ceil(Contrast)*2-1)*6+D*6; // Количество ячеек во всех 6 треугольниках, в ряду "Ceil(Contrast)"
CellsCount := Shade-(Q*257-129); // Количество ячеек от середины треугольника к краям, + вправо, - влево
NumberBeforeRow := (Power(Ceil(Contrast)-1, 2)+(Ceil(Contrast)-1)*D)*6; // № первой ячейки в ряду
NumberInRow := Q*(CountInRow+1-(E*2-1)*D)-(1-E)*D-CountInRow/2+CellsCount-1; // Порядковый номер ячейки в ряду "Ceil(Contrast)"
NumberInBright := NumberBeforeRow+NumberInRow; // Порядковый номер ячейки на яркости "Bright"
MaxContrast := Ceil(127.5-abs(Bright-127.5)); // Определить максимальную контрастность на яркости "Bright" и перевести в целый формат
CountBright1 := Power(MaxContrast, 2)*6; // Кол-во ячеек во всех треугольниках на яркости с дробным числом
CountBright2 := (Power(MaxContrast, 2)+MaxContrast)*6; // Кол-во ячеек во всех треугольниках на яркости с целым числом
CountBright3 := Power(128, 2)*6; // Кол-во ячеек во всех треугольниках на "127,5" яркости
CountMultiply1 := ((Power(MaxContrast, 3)-MaxContrast)/6)*2+((MaxContrast+1)*MaxContrast)/2; // На сколько нужно умножить 6, чтобы определить кол-во ячеек в предыдущих и текущей яркости
CountMultiply2 := (Power((MaxContrast+D), 3)-(MaxContrast+D))/6; // На сколько нужно умножить 12, чтобы определить кол-во ячеек в предыдущих и текущей яркости
CountCells127_5 := (((Power(128, 3)-128)/6)*2+(129*128)/2)*6+((Power(128, 3)-128)/6)*12; // Количество ячеек на "127,5" и нижних яркостях
Bright127_5 := -Floor((127.5-Bright)/256); // 1=если "Bright>127,5", иначе 0
MainCountCells := abs(CountCells127_5*Bright127_5+
(CountCells127_5*Bright127_5-(CountMultiply1*6+CountMultiply2*12)-
(CountBright3-CountBright2*D-CountBright1*(1-D))*Bright127_5)); // Количество ячеек на яркости "Bright" и нижних яркостях
BGW := Ceil((abs(R-G)+abs(R-B))/511); // 0=если R=G=B, иначе 1
MainNumberInRow := R*(1-BGW)+(256+MainCountCells-CountBright2*D-CountBright1*(1-D)+NumberInBright)*BGW; // Порядковый номер R,G,B
end;
procedure TForm1.Button6Click(Sender: TObject); // Если нажата кнопка
var
R,G,B,MainNumberInRow: extended;
begin
R := 255; G := 0; B := 0;
// Найти порядковый номер R,G,B ( черно-белые оттенки = 0-255; цветные оттенки = 256-16777215 )
RGB_Number (R,G,B, MainNumberInRow);
Form1.Caption := 'R: '+floattostr(R)+' G: '+floattostr(G)+' B: '+floattostr(B)
+' | Порядковый номер RGB: '+floattostr(MainNumberInRow);
end;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
// C# ////////////////////////////////////////////////////////////////////////////////////////////////////////////
private Texture2D texture2;
public Texture2D ChangeBC(Texture2D texture,
float Percent_Bright, float Max_Percent_Bright,
float Percent_Contrast, float Max_Percent_Contrast)
{ // Поменять яркость, контрастность всего изображения
// Пример использования: MyNewTexture = ChangeBC (MyTexture,-50,100,50,100);
// texture = изначальное изображение
// Percent_Bright = на сколько изменить яркость в процентах от "-Max_Percent_Bright" до "Max_Percent_Bright", где 0 оставляет яркость неизменной
// Percent_Contrast = на сколько изменить контрастность в процентах от "-Max_Percent_Contrast" до "Max_Percent_Contrast", где 0 оставляет контрастность неизменной
// 255 - максимальное значение для = Max_Percent_Bright и Max_Percent_Contrast
int Lc, LcR, LcG, LcB, w, h, numofcolorXY; ;
float R, G, B, RGBmax, RGBmin, Bright = 0;
if (Percent_Bright < 0)
Lc = -1; // -1 = уменьшить яркость
else
Lc = 0; // 0 = увеличить яркость
// Перевести изображение "texture" в массив "Color" (с массивом "Color" напрямую работать быстрее чем с самой текстурой)
w = texture.width;
h = texture.height;
Color[] PictByColor = new Color[w * h];
PictByColor = texture.GetPixels(0, 0, w, h);
Color[] DrawByColor = new Color[w * h]; // Холст на котором будет вестись отрисовка
for (int Yy = 0; Yy < h; Yy++)
{
for (int Xx = 0; Xx < w; Xx++)
{
numofcolorXY = (h - 1 - Yy) * w + Xx; // Номер ячейки в массиве "PictByColor"
// Если не прозрачный пиксель
if (PictByColor[numofcolorXY].a > 0)
{
Color color = PictByColor[numofcolorXY]; // цвет кисти
// Цвет "color" в формате от 0 до 1, (R,G,B)/255f
R = color.r;
G = color.g;
B = color.b;
// Поменять яркость ////////////////////////////////////////////////////
R = Mathf.Abs(((((1 + Lc) + R * -(Lc * 2 + 1)) * Mathf.Abs(Percent_Bright)) / Max_Percent_Bright) - R * -(Lc * 2 + 1));
G = Mathf.Abs(((((1 + Lc) + G * -(Lc * 2 + 1)) * Mathf.Abs(Percent_Bright)) / Max_Percent_Bright) - G * -(Lc * 2 + 1));
B = Mathf.Abs(((((1 + Lc) + B * -(Lc * 2 + 1)) * Mathf.Abs(Percent_Bright)) / Max_Percent_Bright) - B * -(Lc * 2 + 1));
// Поменять контрастность ////////////////////////////////////////////////////
RGBmax = (((((R + G) / 2f) + (Mathf.Abs(R - G) / 2f)) + B) / 2f) + (Mathf.Abs((((R + G) / 2f) + (Mathf.Abs(R - G) / 2f)) - B) / 2f);
RGBmin = (((((R + G) / 2f) - (Mathf.Abs(R - G) / 2f)) + B) / 2f) - (Mathf.Abs((((R + G) / 2f) - (Mathf.Abs(R - G) / 2f)) - B) / 2f);
Bright = (RGBmax + RGBmin) / 2f; // Яркость от 0 до 255 (или от 0 до 1)
//Contrast = (RGBmax-RGBmin)/2f; // Контрастность от 0 до 127.5 (или от 0 до 0.5)
LcR = (Mathf.CeilToInt((R - Bright) / 2f) * -2) + 1; // 1=Если "R" меньше "Bright", -1=если больше
LcG = (Mathf.CeilToInt((G - Bright) / 2f) * -2) + 1; // 1=Если "G" меньше "Bright", -1=если больше
LcB = (Mathf.CeilToInt((B - Bright) / 2f) * -2) + 1; // 1=Если "B" меньше "Bright", -1=если больше
R = Mathf.Abs((((Bright * LcR - R * LcR) * Percent_Contrast) / Max_Percent_Contrast) + R * LcR);
G = Mathf.Abs((((Bright * LcG - G * LcG) * Percent_Contrast) / Max_Percent_Contrast) + G * LcG);
B = Mathf.Abs((((Bright * LcB - B * LcB) * Percent_Contrast) / Max_Percent_Contrast) + B * LcB);
if (R>1) R = 1;
if (G>1) G = 1;
if (B>1) B = 1;
color.r = R;
color.g = G;
color.b = B;
DrawByColor[numofcolorXY] = color; // Нарисовать новый цвет
}
}
}
if (texture2==null)
{
texture2 = new Texture2D(w, h);
texture2.filterMode = FilterMode.Point; // Для четкой отрисовки
}
else texture2.Resize(w, h);
texture2.SetPixels(DrawByColor);
texture2.Apply();
return texture2;
}
// Delphi //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
uses Math;
function ChangeBC(RGB1: TColor;
Percent_Bright,Max_Percent_Bright,
Percent_Contrast,Max_Percent_Contrast: extended):TColor; // Поменять яркость, контрастность
var
Lc, LcR, LcG, LcB, w, h, numofcolorXY: integer ;
R, G, B, RGBmax, RGBmin, Bright, Contrast: extended;
//Shade, Rm, Gm, Bm, Qrm, Qgm, Qbm: extended;
begin
showmessage('Прибавить к яркости: '+floattostr(Percent_Bright)
+#13#10+'Прибавить к контрастности: '+floattostr(Percent_Contrast));
R := GetRValue(RGB1);
G := GetGValue(RGB1);
B := GetBValue(RGB1);
// Percent_Bright = на сколько изменить яркость в процентах от "-Max_Percent_Bright" до "Max_Percent_Bright", где 0 оставляет яркость неизменной
// Percent_Contrast = на сколько изменить контрастность в процентах от "-Max_Percent_Contrast" до "Max_Percent_Contrast", где 0 оставляет контрастность неизменной
// 255 - максимальное значение для = Max_Percent_Bright и Max_Percent_Contrast
// Цвет "color" в формате от 0 до 1, (R,G,B)/255
R := R /255;
G := G /255;
B := B /255;
if (Percent_Bright < 0) then
Lc := -1 // -1 = уменьшить яркость
else Lc := 0; // 0 = увеличить яркость
// Поменять яркость ////////////////////////////////////////////////////
R := Abs(((((1 + Lc) + R * -(Lc * 2 + 1)) * Abs(Percent_Bright)) / Max_Percent_Bright) - R * -(Lc * 2 + 1));
G := Abs(((((1 + Lc) + G * -(Lc * 2 + 1)) * Abs(Percent_Bright)) / Max_Percent_Bright) - G * -(Lc * 2 + 1));
B := Abs(((((1 + Lc) + B * -(Lc * 2 + 1)) * Abs(Percent_Bright)) / Max_Percent_Bright) - B * -(Lc * 2 + 1));
// Поменять контрастность ////////////////////////////////////////////////////
// Максимальное и минимальное значение из трех чисел
RGBmax := (((((R + G) / 2) + (Abs(R - G) / 2)) + B) / 2) + (Abs((((R + G) / 2) + (Abs(R - G) / 2)) - B) / 2);
RGBmin := (((((R + G) / 2) - (Abs(R - G) / 2)) + B) / 2) - (Abs((((R + G) / 2) - (Abs(R - G) / 2)) - B) / 2);
Bright := (RGBmax + RGBmin) / 2; // Яркость от 0 до 255 (или от 0 до 1)
//Contrast := (RGBmax-RGBmin)/2; // Контрастность от 0 до 127.5 (или от 0 до 0.5)
// Условие, уменьшать или увеличивать переменную
LcR := (Ceil((R - Bright) / 2) * -2) + 1; // 1=Если "R" меньше "Bright", -1=если больше
LcG := (Ceil((G - Bright) / 2) * -2) + 1; // 1=Если "G" меньше "Bright", -1=если больше
LcB := (Ceil((B - Bright) / 2) * -2) + 1; // 1=Если "B" меньше "Bright", -1=если больше
R := Abs((((Bright * LcR - R * LcR) * Percent_Contrast) / Max_Percent_Contrast) + R * LcR);
G := Abs((((Bright * LcG - G * LcG) * Percent_Contrast) / Max_Percent_Contrast) + G * LcG);
B := Abs((((Bright * LcB - B * LcB) * Percent_Contrast) / Max_Percent_Contrast) + B * LcB);
if (R>1) then R := 1;
if (G>1) then G := 1;
if (B>1) then B := 1;
ChangeBC := RGB(Round(R*255),Round(G*255),Round(B*255));
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Color1: TColor;
begin
Color1 := RGB(255,8,14);
Form1.Color := Color1;
Form1.Color := ChangeBC(Color1, 50, 100, 60, 100);
end;
Leave a comment
Log in with itch.io to leave a comment.