[英]How to get the calculate the RGB values of a pixel from the luminance?
I want to compute the RGB values from the luminance.我想根据亮度计算 RGB 值。
The data that I know are:我知道的数据是:
We can compute the luminance from the RGB values like this:我们可以像这样从 RGB 值计算亮度:
uint8_t luminance = R * 0.21 + G * 0.71 + B * 0.07;
My code is:我的代码是:
// We create a function to set the luminance of a pixel
void jpegImage::setLuminance(uint8_t newLuminance, unsigned int x, unsigned int y) {
// If the X or Y value is out of range, we throw an error
if(x >= width) {
throw std::runtime_error("Error : in jpegImage::setLuminance : The X value is out of range");
}
else if(y >= height) {
throw std::runtime_error("Error : in jpegImage::setLuminance : The Y value is out of range");
}
// If the image is monochrome
if(pixelSize == 1) {
// We set the pixel value to the luminance
pixels[y][x] = newLuminance;
}
// Else if the image is colored, we throw an error
else if(pixelSize == 3) {
// I don't know how to proceed
// My image is stored in a std::vector<std::vector<uint8_t>> pixels;
// This is a list that contain the lines of the image
// Each line contains the RGB values of the following pixels
// For example an image with 2 columns and 3 lines
// [[R, G, B, R, G, B], [R, G, B, R, G, B], [R, G, B, R, G, B]]
// For example, the R value with x = 23, y = 12 is:
// pixels[12][23 * pixelSize];
// For example, the B value with x = 23, y = 12 is:
// pixels[12][23 * pixelSize + 2];
// (If the image is colored, the pixelSize will be 3 (R, G and B)
// (If the image is monochrome the pixelSIze will be 1 (just the luminance value)
}
}
How can I proceed?我该如何进行? Thanks !谢谢 !
You don't need the old luminance if you have the original RGB.如果您有原始 RGB,则不需要旧亮度。
Referencing https://www.fourcc.org/fccyvrgb.php for YUV to RGB conversion.参考https://www.fourcc.org/fccyvrgb.php进行 YUV 到 RGB 的转换。
Compute U and V from original RGB:从原始 RGB 计算 U 和 V:
```
V = (0.439 * R) - (0.368 * G) - (0.071 * B) + 128
U = -(0.148 * R) - (0.291 * G) + (0.439 * B) + 128
```
Y
is the new luminance normalized to a value between 0 and 255 Y
是归一化为 0 到 255 之间的值的新亮度
Then just convert back to RGB:然后只需转换回 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)
Make sure you clamp your computed values of each equation to be in range of 0..255
.确保将每个方程的计算值限制在0..255
范围内。 Some of these formulas can convert a YUV or RGB value to something less than 0 or higher than 255.其中一些公式可以将 YUV 或 RGB 值转换为小于 0 或大于 255 的值。
There's also multiple formula for converting between YUV and RGB. YUV 和 RGB 之间的转换也有多种公式。 (Different constants). (不同的常数)。 I noticed the page listed above has a different computation for Y than you cited.我注意到上面列出的页面对 Y 的计算与您引用的不同。 They are all relatively close with different precisions and adjustments.它们都相对接近,具有不同的精度和调整。 For just changing the brightness of a pixel, almost any formula will do.仅仅改变一个像素的亮度,几乎任何公式都可以。
I originally deleted this answer after the OP suggested it wasn't working for him.在 OP 建议它对他不起作用后,我最初删除了这个答案。 I was too busy for the last few days to investigate, but I wrote some sample code to confirm my hypothesis.最近几天忙得没时间调查,但我写了一些示例代码来证实我的假设。 At the bottom of this answer is a snippet of GDI+ based code increases the luminance of an image by a variable amount.此答案的底部是基于 GDI+ 的代码片段,可将图像的亮度增加一个变量。 Along with the code is an image that I tested this out on and two conversions.与代码一起是我测试过的图像和两次转换。 One at 130% brightness.一个亮度为 130%。 Another at 170% brightness.另一个亮度为 170%。
Updated Image (at 130% Y)更新后的图像(130% Y)
Updated Image (at 170% Y)更新后的图像(170% Y)
Source:资源:
#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 = dataOut.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;
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.