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;
Status | Released |
Category | Tool |
Platforms | HTML5 |
Author | Uchenik_333 |
Made with | Unity |
Leave a comment
Log in with itch.io to leave a comment.