Старая яркость не нужна, если у вас исходный RGB.
Ссылка https://www.fourcc.org/fccyvrgb.php для преобразования YUV в RGB.
Вычислить U и V из исходного RGB:
```
V = (0.439 * R) - (0.368 * G) - (0.071 * B) + 128
U = -(0.148 * R) - (0.291 * G) + (0.439 * B) + 128
```
Y
- это новая яркость, нормализованная до значения от 0 до 255
Затем просто конвертируйте обратно в RGB:
B = 1.164(Y - 16) + 2.018(U - 128)
G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
R = 1.164(Y - 16) + 1.596(V - 128)
Убедитесь, что вы ограничили вычисленные значения каждого уравнения в диапазоне 0..255
. Некоторые из этих формул могут преобразовывать значение YUV или RGB в значение меньше 0 или больше 255.
Также существует несколько формул для преобразования между YUV и RGB. (Разные константы). Я заметил, что на указанной выше странице вычисление Y отличается от приведенного вами. Все они относительно близки с разными уточнениями и корректировками. Для простого изменения яркости пикселя подойдет практически любая формула.
Обновлено
Я изначально удалил этот ответ после того, как OP предположил, что он не работает. Последние несколько дней я был слишком занят, чтобы что-то расследовать, но я написал образец кода, чтобы подтвердить свою гипотезу. Внизу этого ответа находится фрагмент кода на основе GDI +, который увеличивает яркость изображения на переменную величину. Вместе с кодом есть изображение, на котором я это тестировал, и два преобразования. Один с яркостью 130%. Другой с яркостью 170%.
Вот пример преобразования
Исходное изображение ![Original Image](https://i.stack.imgur.com/g5tGI.jpg)
Updated Image (at 130% Y)
![Updated image](https://i.stack.imgur.com/qRVCD.jpg)
Updated Image (at 170% Y)
введите описание изображения здесь
Источник:
#define CLAMP(val) {val = (val > 255) ? 255 : ((val < 0) ? 0 : val);}
void Brighten(Gdiplus::BitmapData& dataIn, Gdiplus::BitmapData& dataOut, const double YMultiplier=1.3)
{
if ( ((dataIn.PixelFormat != PixelFormat24bppRGB) && (dataIn.PixelFormat != PixelFormat32bppARGB)) ||
((dataOut.PixelFormat != PixelFormat24bppRGB) && (dataOut.PixelFormat != PixelFormat32bppARGB)))
{
return;
}
if ((dataIn.Width != dataOut.Width) || (dataIn.Height != dataOut.Height))
{
// images sizes aren't the same
return;
}
const size_t incrementIn = dataIn.PixelFormat == PixelFormat24bppRGB ? 3 : 4;
const size_t incrementOut = dataIn.PixelFormat == PixelFormat24bppRGB ? 3 : 4;
const size_t width = dataIn.Width;
const size_t height = dataIn.Height;
for (size_t y = 0; y < height; y++)
{
auto ptrRowIn = (BYTE*)(dataIn.Scan0) + (y * dataIn.Stride);
auto ptrRowOut = (BYTE*)(dataOut.Scan0) + (y * dataOut.Stride);
for (size_t x = 0; x < width; x++)
{
uint8_t B = ptrRowIn[0];
uint8_t G = ptrRowIn[1];
uint8_t R = ptrRowIn[2];
uint8_t A = (incrementIn == 3) ? 0xFF : ptrRowIn[3];
auto Y = (0.257 * R) + (0.504 * G) + (0.098 * B) + 16;
auto V = (0.439 * R) - (0.368 * G) - (0.071 * B) + 128;
auto U = -(0.148 * R) - (0.291 * G) + (0.439 * B) + 128;
Y *= YMultiplier;
auto newB = 1.164*(Y - 16) + 2.018*(U - 128);
auto newG = 1.164*(Y - 16) - 0.813*(V - 128) - 0.391*(U - 128);
auto newR = 1.164*(Y - 16) + 1.596*(V - 128);
CLAMP(newR);
CLAMP(newG);
CLAMP(newB);
ptrRowOut[0] = newB;
ptrRowOut[1] = newG;
ptrRowOut[2] = newR;
if (incrementOut == 4)
{
ptrRowOut[3] = A; // keep original alpha
}
ptrRowIn += incrementIn;
ptrRowOut += incrementOut;
}
}
}