Let’s briefly introduce the principle of Photoshop image brightness/contrast adjustment:
1. Contrast algorithm formula.
Photoshop processes the contrast increment according to the positive and negative values of the given value respectively.
If newRGB is used to represent the new R, G, and B components of the image pixel, RGB represents the R, G, and B components of the image pixel, Threshold is the given threshold, and Contrast is the contrast increment. When Contrast is greater than 0 When:
1) newRGB = RGB + (RGB - Threshold) * (1 / (1 - Contrast / 255) - 1)
Where, when Contrast is equal to 255 (RGB - Threshold ) * (1 / (1 - Contrast / 255) - 1) is infinite (±). Since the maximum and minimum values of RGB are 255 and 0 respectively, newRGB can only be determined by Threshold, that is, newRGB = RGB >= Threshold ? 255: 0, this is actually setting the image threshold. The image is composed of up to eight colors, namely red, yellow, green, cyan, blue, purple, black and white. There are only up to 8 lines on the grayscale image.
When Contrast is less than 0:
2) newRGB = RGB + (RGB - Threshold) * Contrast / 255
Among them, when Contrast is equal to -255, the image RGB Each component is equal to the threshold, the image is completely gray, and there is only one line on the grayscale image, which is the threshold grayscale.
2. Image brightness adjustment. This article uses the most commonly used non-linear brightness adjustment (this brightness adjustment method is also used in versions below Photoshop CS3, and CS3 and above versions also retain the option of this brightness adjustment method).
3. Image brightness/contrast comprehensive adjustment algorithm. This is very simple. When the brightness and contrast are adjusted at the same time, if the contrast is greater than 0, adjust the brightness now, and then adjust the contrast; when the contrast is less than 0, the opposite is true, adjust the contrast first, and then adjust the brightness.
The following is all the code for Photoshop image brightness/contrast adjustment written using BCB2007 and GDI+ bitmap data, including example code:
//--- -------------------------------------------------- -----------------------
##// Define ARGB pixel structure
typedef union{
ARGB Color;
struct {
BYTE Blue;
BYTE Green;
BYTE Red;
BYTE Alpha;
};
}ARGBQuad, *PARGBQuad;
//------------- -------------------------------------------------- -----------
//---------------------------------------------------------------------------
FORCEINLINE
INT CheckValue(INT value)
{
return value <= 0? 0 : value >= 255? 255 : value;
}
//---------------------------------------------------------------------------
VOID BrightAndContrast(BitmapData *data, INT bright, INT contrast, BYTE threshold)
{
FLOAT cv = contrast <= -255? -1.0f : contrast / 255.0f;
if (contrast > 0 && contrast < 255)
cv = 1.0f / (1.0f - cv) - 1.0f;
BYTE values[256];
for (INT i = 0; i < 256; i ++)
{
INT v = contrast > 0? CheckValue(i + bright) : i;
if (contrast >= 255)
v = v >= threshold? 255 : 0;
else
v = CheckValue(v + (INT)((v - threshold) * cv + 0.5f));
values[i] = contrast < 0? CheckValue(v + bright) : v;
}
PARGBQuad p = (PARGBQuad)data->Scan0;
INT offset = data->Stride - data->Width * sizeof(ARGBQuad);
for (UINT y = 0; y < data->Height; y ++, (BYTE*)p += offset)
{
for (UINT x = 0; x < data->Width; x ++, p ++)
{
p->Blue = values[p->Blue];
p->Green = values[p->Green];
p->Red = values[p->Red];
}
}
}
//------------------------------------------ ------------------------------------
// Lock GDI+ bitmap scan line to data
FORCEINLINE
VOID LockBitmap(Gdiplus::Bitmap *bmp, BitmapData *data)
{
Gdiplus::Rect r(0, 0, bmp->GetWidth(), bmp->GetHeight());
bmp->LockBits( &r, ImageLockModeRead | ImageLockModeWrite,
PixelFormat32bppARGB, data);
}
//---------------- -------------------------------------------------- -------
// GDI+ bitmap scan line unlock
FORCEINLINE
VOID UnlockBitmap(Gdiplus::Bitmap *bmp, BitmapData *data)
{
bmp->UnlockBits(data);
}
//--- -------------------------------------------------- -----------------------
##void __fastcall TForm1::Button3Click( TObject *Sender){
Gdiplus::Bitmap *bmp =
new Gdiplus::Bitmap(L"d:\\source.jpg"); Gdiplus::Graphics *g =
new Gdiplus::Graphics(Canvas->Handle); g->DrawImage(bmp,
0, 0);
BitmapData data;
LockBitmap(bmp, &data);
BrightAndContrast(&data,
0 , 100, 121); UnlockBitmap(bmp, &data);
g->DrawImage(bmp, data.Width,
0 );
delete g;
delete bmp;
}
//------------- -------------------------------------------------- ----------