• C++图像处理 图像黑白调整应用


    转自:http://blog.csdn.net/maozefa/article/details/6595831

    阅读提示

        《C++图像处理》系列以代码清晰,可读性为主,全部使用C++代码。

        《Delphi图像处理》系列以效率为侧重点,一般代码为PASCAL,核心代码采用BASM。

        尽可能保持二者内容一致,可相互对照。

        本文代码必须包括《C++图像处理 -- 数据类型及公用函数文章中的BmpData.h头文件。

     

        Photoshop CS的图像黑白调整功能,是通过对红、黄、绿、青、蓝和洋红等6种颜色的比例调节来完成的。能更精细地将彩色图片转换为高质量的黑白照片。

        Photoshop CS图像黑白调整功能的计算公式为:

        gray = (max - min) * ratio_max + (mid - min) * ratio_max_mid + min

        公式中:gray为像素灰度值,max、mid和min分别为图像像素R、G、B分量颜色的最大值、中间值和最小值,ratio_max为max所代表的分量颜色(单色)比率,ratio_max_mid则为max与mid两种分量颜色所形成的复色比率。

        用上面公式计算的灰度值,与我们通常所用的灰度计算方法有很大不同,通常所用的灰度公式为,是直接将颜色各分量乘以相应的比率相加而成,如:gray = 0.3R + 0.59G + 0.11B,而上面公式则是在最小值代表的颜色分量基础上,用最大值与最小值之差表示单色部分(红、绿、蓝),用中间值与最小值之差表示复色部分(黄、青、洋红),将单色和复色部分分别乘以与之对应的比率后相加,再加上最小值而得到灰度值。对于每个单独的像素来说,计算灰度值只需要用到上述6种颜色比率中的2种即可。在计算过程中可根据像素RGB相互关系选择对应的单色和复色比率,如像素RGB的大小关系为R>G>B,单色比率选最大值R红色,复色比率则为最大值R与中间值G所形成的复色黄色。

        用程序代码实现上面的灰度计算公式并不复杂,难点还是前面所说的根据像素RGB相互关系选择对应的单色和复色比率。在前天我写的《C++图像处理 -- 图像颜色混合(上)》文章中,已经实现了这项功能,同时,Photoshop图像黑白调整功能中附加的着色功能,也在文章中实现。本文的在上面文章代码基础上,编写一个相对简单的图像黑白调整界面,来实现图像动态黑白调整。

        下面是用BCB2007写的一个界面程序代码:

        程序头文件部分:

    1. //---------------------------------------------------------------------------  
    2.   
    3. #ifndef bwMainH  
    4. #define bwMainH  
    5. //---------------------------------------------------------------------------  
    6. #include <Classes.hpp>  
    7. #include <Controls.hpp>  
    8. #include <StdCtrls.hpp>  
    9. #include <Forms.hpp>  
    10. #include <ComCtrls.hpp>  
    11. #include <Dialogs.hpp>  
    12. #include <ExtCtrls.hpp>  
    13.   
    14. #define USE_GDIPLUS  
    15.   
    16. #include "BmpData.h"  
    17. //---------------------------------------------------------------------------  
    18. enum TLockType {ltEdit, ltTrack};  
    19. typedef Set<TLockType, ltEdit, ltTrack> TLockTypes;  
    20.   
    21. class TForm1 : public TForm  
    22. {  
    23. __published:    // IDE-managed Components  
    24.     TPaintBox *PaintBox1;  
    25.     TLabel *Label1;  
    26.     TLabel *Label2;  
    27.     TLabel *Label3;  
    28.     TLabel *Label4;  
    29.     TLabel *Label5;  
    30.     TLabel *Label6;  
    31.     TLabel *Label7;  
    32.     TLabel *Label8;  
    33.     TLabel *Label9;  
    34.     TLabel *Label10;  
    35.     TLabel *Label11;  
    36.     TLabel *Label12;  
    37.     TLabel *Label13;  
    38.     TLabel *Label18;  
    39.     TComboBox *ComboBox1;  
    40.     TEdit *Edit1;  
    41.     TTrackBar *TrackBar1;  
    42.     TEdit *Edit2;  
    43.     TTrackBar *TrackBar2;  
    44.     TEdit *Edit3;  
    45.     TTrackBar *TrackBar3;  
    46.     TEdit *Edit4;  
    47.     TTrackBar *TrackBar4;  
    48.     TEdit *Edit5;  
    49.     TTrackBar *TrackBar5;  
    50.     TEdit *Edit6;  
    51.     TTrackBar *TrackBar6;  
    52.     TCheckBox *CheckBox1;  
    53.     TGroupBox *GroupBox1;  
    54.     TLabel *Label14;  
    55.     TLabel *Label15;  
    56.     TLabel *Label16;  
    57.     TLabel *Label17;  
    58.     TPaintBox *PaintBox2;  
    59.     TEdit *Edit7;  
    60.     TTrackBar *TrackBar7;  
    61.     TEdit *Edit8;  
    62.     TTrackBar *TrackBar8;  
    63.     TColorDialog *ColorDialog1;  
    64.     void __fastcall FormCreate(TObject *Sender);  
    65.     void __fastcall FormDestroy(TObject *Sender);  
    66.     void __fastcall ComboBox1Change(TObject *Sender);  
    67.     void __fastcall TrackBar1Change(TObject *Sender);  
    68.     void __fastcall Edit1Change(TObject *Sender);  
    69.     void __fastcall Edit1KeyPress(TObject *Sender, char &Key);  
    70.     void __fastcall Edit1Exit(TObject *Sender);  
    71.     void __fastcall CheckBox1Click(TObject *Sender);  
    72.     void __fastcall TrackBar7Change(TObject *Sender);  
    73.     void __fastcall Edit7Change(TObject *Sender);  
    74.     void __fastcall Edit7KeyPress(TObject *Sender, char &Key);  
    75.     void __fastcall PaintBox2Click(TObject *Sender);  
    76.     void __fastcall PaintBox1Paint(TObject *Sender);  
    77.     void __fastcall PaintBox2Paint(TObject *Sender);  
    78.     void __fastcall TrackBar8Change(TObject *Sender);  
    79. private:    // User declarations  
    80.     Bitmap *Source;                 // 源图像  
    81.     Bitmap *Dest;                   // 调整后的图像  
    82.     BitmapData srcData;  
    83.     BitmapData dstData;  
    84.     float bwColors[6];              // 灰度选项数组  
    85.     int Bright;                     // 亮度  
    86.     TTrackBar *TrackBars[6];        // 灰度选项条元件数组  
    87.     TEdit *Edits[6];                // 灰度选项编辑框数组  
    88.     TLockTypes Lock;  
    89.     Gdiplus::Rect rect;  
    90.     ARGBQuad MixColor;              // 混合颜色  
    91.   
    92.     int __fastcall GetHue(void);  
    93.     int __fastcall GetSat(void);  
    94.     void __fastcall SetHue(int hue);  
    95.     void __fastcall SetSat(int sat);  
    96.   
    97.     void __fastcall MixColorToHSV(void);  
    98.     void __fastcall HSVToMixColor(void);  
    99.     void __fastcall Execute(void);  
    100.     void __fastcall MixColorChange(void);  
    101. public:     // User declarations  
    102.     __fastcall TForm1(TComponent* Owner);  
    103.   
    104.     __property int Hue = {read=GetHue, write=SetHue};   // 色相  
    105.     __property int Sat = {read=GetSat, write=SetSat};   // 饱和度  
    106. };  
    107. //---------------------------------------------------------------------------  
    108. const CustomIndex = 11;             // 自定义选项索引  
    109. const DefaultTint = 0xe1d3b3;       // 缺省混合颜色  
    110. const int DefOptions[][6] =         // 预定义灰度选项  
    111. {  
    112.     {40, 60, 40, 60, 20, 80},  
    113.     {128, 128, 100, 100, 128, 100},  
    114.     {100, 100, 100, 100, 100, 100},  
    115.     {0, 0, 0, 0, 0, 0},  
    116.     {-40, 235, 144, -68, -3, -107},  
    117.     {120, 110, -10, -50, 0, 120},  
    118.     {50, 120, 90, 50, 0, 0},  
    119.     {0, 0, 0, 110, 110, 110},  
    120.     {120, 120, -10, -50, -50, 120},  
    121.     {-50, -50, -50, 150, 150, 150},  
    122.     {120, 110, 40, -30, 0, 70}  
    123. };  
    124.   
    125. extern PACKAGE TForm1 *Form1;  
    126. //---------------------------------------------------------------------------  
    127. #endif  

         代码文件部分:

    1. //---------------------------------------------------------------------------  
    2.   
    3. #include <vcl.h>  
    4. #pragma hdrstop  
    5.   
    6. #include "bwMain.h"  
    7. //---------------------------------------------------------------------------  
    8. #pragma package(smart_init)  
    9. #pragma resource "*.dfm"  
    10. TForm1 *Form1;  
    11. //---------------------------------------------------------------------------  
    12. __fastcall TForm1::TForm1(TComponent* Owner)  
    13.     : TForm(Owner)  
    14. {  
    15. }  
    16. //---------------------------------------------------------------------------  
    17. ULONG gdiplusToken;  
    18.   
    19. typedef FLOAT       BWParams, *PBWParams;  
    20.   
    21. // 黑白调整缺省参数:红,黄,绿,洋红,蓝,青  
    22. CONST INT _BWDefault[] = {410, 614, 410, 819, 205, 614};  
    23.   
    24. enum  
    25. {  
    26.     BWIndexBlue     = 0x40000,  
    27.     BWIndexGreen    = 0x20000,  
    28.     BWIndexRed      = 0x00000  
    29. };  
    30.   
    31. enum  
    32. {  
    33.     IndexBlue   = 0x00000,  
    34.     IndexGreen  = 0x10000,  
    35.     IndexRed    = 0x20000  
    36. };  
    37.   
    38. typedef union               // 颜色分量交换结构  
    39. {  
    40.     INT tmp;                // 交换时用的临时变量  
    41.     struct  
    42.     {  
    43.         SHORT value;        // 颜色分量值  
    44.         SHORT index;        // 颜色分量索引  
    45.     };  
    46. }RGBIndex;  
    47. //---------------------------------------------------------------------------  
    48.   
    49. // 交换像素分量  
    50. FORCEINLINE  
    51. VOID SwapRgb(RGBIndex &a, RGBIndex &b)  
    52. {  
    53.     a.tmp ^= b.tmp;  
    54.     b.tmp ^= a.tmp;  
    55.     a.tmp ^= b.tmp;  
    56. }  
    57. //---------------------------------------------------------------------------  
    58.   
    59. // 获取黑白灰度  
    60. FORCEINLINE  
    61. INT GetBWGray(CONST PARGBQuad pixel, CONST PINT bwParams)  
    62. {  
    63.     RGBIndex max, mid, min;  
    64.     min.tmp = pixel->Blue | BWIndexBlue;  
    65.     mid.tmp = pixel->Green | BWIndexGreen;  
    66.     max.tmp = pixel->Red | BWIndexRed;  
    67.   
    68.     if (max.value < mid.value)  
    69.         SwapRgb(max, mid);  
    70.     if (max.value < min.value)  
    71.         SwapRgb(max, min);  
    72.     if (min.value > mid.value)  
    73.         SwapRgb(min, mid);  
    74.   
    75.     return (((max.value - mid.value) * bwParams[max.index] +  
    76.         (mid.value - min.value) * bwParams[max.index + mid.index - 1] +  
    77.         512) >> 10) + min.value;  
    78. }  
    79. //---------------------------------------------------------------------------  
    80.   
    81. VOID ColorMix(PARGBQuad pd, CONST PARGBQuad ps, INT gray)  
    82. {  
    83.     // 灰度计算常数:蓝,绿、红  
    84.     CONST INT ys[3] = {113, 604, 307};  
    85.   
    86.     RGBIndex max, mid, min;  
    87.     min.tmp = ps->Blue | IndexBlue;  
    88.     mid.tmp = ps->Green | IndexGreen;  
    89.     max.tmp = ps->Red | IndexRed;  
    90.   
    91.     if (max.value < mid.value)  
    92.         SwapRgb(max, mid);  
    93.     if (max.value < min.value)  
    94.         SwapRgb(max, min);  
    95.     if (min.value > mid.value)  
    96.         SwapRgb(min, mid);  
    97.   
    98.     INT max_min = max.value - min.value;  
    99.     // 饱和度为0,返回灰度  
    100.     if (max_min == 0)  
    101.     {  
    102.         pd->Blue = pd->Green = pd->Red = gray;  
    103.         return;  
    104.     }  
    105.     INT mid_min = mid.value - min.value;  
    106.   
    107.     INT newMax, newMid, newMin;  
    108.     gray <<= 10;  
    109.     newMax = (gray + (max_min - mid_min) * ys[mid.index] + max_min * ys[min.index] + 512) >> 10;  
    110.     newMin = newMax - max_min;  
    111.     if (newMax > 255)  
    112.     {  
    113.         INT hueCoef = (mid_min << 10) / max_min;  
    114.         INT v0 = (ys[mid.index] * hueCoef) >> 10;  
    115.         INT v1 = ys[min.index] + ys[mid.index] - v0;  
    116.         newMin = (gray - (ys[max.index] + v0) * 255 + (v1 >> 1)) / v1;  
    117.         newMid = newMin + (((255 ^ newMin) * hueCoef + 512) >> 10);  
    118.         newMax = 255;  
    119.   
    120.     }  
    121.     else if (newMin < 0)  
    122.     {  
    123.         INT hueCoef = (mid_min << 10) / max_min;  
    124.         INT tmp = ys[max.index] + ((ys[mid.index] * hueCoef + 512) >> 10);  
    125.         newMax = (gray + (tmp >> 1)) / tmp;  
    126.         newMid = (newMax * hueCoef + 512) >> 10;  
    127.         newMin = 1;  
    128.     }  
    129.     else  
    130.         newMid = newMin + mid_min;  
    131.   
    132.     ((LPBYTE)pd)[max.index] = newMax;  
    133.     ((LPBYTE)pd)[mid.index] = newMid;  
    134.     ((LPBYTE)pd)[min.index] = newMin;  
    135. }  
    136. //---------------------------------------------------------------------------  
    137.   
    138. // 图像黑白调整。  
    139. // 调整参数bwParams为元素数等于6的数组指针,分别为红,黄,绿,青,蓝,洋红  
    140. VOID ImageBWCopy(BitmapData *dest, CONST BitmapData *source, CONST PBWParams bwParams = NULL)  
    141. {  
    142.     // 拷贝像素灰度参数,并交换青色和洋红色  
    143.     INT params[6], *pparams;  
    144.     if (bwParams)  
    145.     {  
    146.         for (INT i = 0; i < 6; i ++)  
    147.             params[i] = (INT)(bwParams[i] * 1024 + 0.5);  
    148.         params[3] ^= params[5];  
    149.         params[5] ^= params[3];  
    150.         params[3] ^= params[5];  
    151.         pparams = params;  
    152.     }  
    153.     else  
    154.         pparams = (INT*)_BWDefault;  
    155.   
    156.     PARGBQuad pd, ps;  
    157.     UINT width, height;  
    158.     INT dstOffset, srcOffset;  
    159.     GetDataCopyParams(dest, source, width, height, pd, ps, dstOffset, srcOffset);  
    160.   
    161.     for (UINT y = 0; y < height; y ++, pd += dstOffset, ps += srcOffset)  
    162.     {  
    163.         for (UINT x = 0; x < width; x ++, pd ++, ps ++)  
    164.         {  
    165.             INT gray = GetBWGray(ps, pparams);  
    166.             pd->Blue = pd->Green = pd->Red =  
    167.                 (gray & ~0xff) == 0? gray : gray > 255? 255 : 0;  
    168.         }  
    169.     }  
    170. }  
    171. //---------------------------------------------------------------------------  
    172.   
    173. // 灰度图像染色。  
    174. VOID ImageTint(BitmapData *grayData, ARGB color)  
    175. {  
    176.     ARGBQuad colorTable[256];  
    177.     PARGBQuad p = colorTable;  
    178.   
    179.     for (INT i = 0; i < 256; i ++, p ++)  
    180.     {  
    181.         ColorMix(p, (PARGBQuad)&color, i);  
    182.         p->Alpha = 255;  
    183.     }  
    184.   
    185.     p = (PARGBQuad)grayData->Scan0;  
    186.     INT dataOffset = (grayData->Stride >> 2) - (INT)grayData->Width;  
    187.   
    188.     for (UINT y = 0; y < grayData->Height; y ++, p += dataOffset)  
    189.     {  
    190.         for (UINT x = 0; x < grayData->Width; x ++, p ++)  
    191.         {  
    192.             p->Color = colorTable[p->Blue].Color;  
    193.         }  
    194.     }  
    195. }  
    196. //---------------------------------------------------------------------------  
    197.   
    198. void __fastcall TForm1::FormCreate(TObject *Sender)  
    199. {  
    200.     Gdiplus::GdiplusStartupInput gdiplusStartupInput;  
    201.     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);  
    202.   
    203.     TrackBars[0] = TrackBar1;  
    204.     TrackBars[1] = TrackBar2;  
    205.     TrackBars[2] = TrackBar3;  
    206.     TrackBars[3] = TrackBar4;  
    207.     TrackBars[4] = TrackBar5;  
    208.     TrackBars[5] = TrackBar6;  
    209.     Edits[0] = Edit1;  
    210.     Edits[1] = Edit2;  
    211.     Edits[2] = Edit3;  
    212.     Edits[3] = Edit4;  
    213.     Edits[4] = Edit5;  
    214.     Edits[5] = Edit6;  
    215.   
    216.     // 从文件装入图像到tmp  
    217.     Bitmap *tmp = new Bitmap(L"source1.jpg");  
    218.     rect.Width = tmp->GetWidth();  
    219.     rect.Height = tmp->GetHeight();  
    220.     // 分别建立新的源和目标图像数据到srcData和dstData  
    221.     GetBitmapData(rect.Width, rect.Height, &srcData);  
    222.     GetBitmapData(rect.Width, rect.Height, &dstData);  
    223.     // 将tmp图像数据分别锁定拷贝到srcData和dstData  
    224.     tmp->LockBits(&rect,  
    225.         ImageLockModeRead | ImageLockModeWrite | ImageLockModeUserInputBuf,  
    226.         PixelFormat32bppARGB, &srcData);  
    227.     tmp->UnlockBits(&srcData);  
    228.     tmp->LockBits(&rect,  
    229.         ImageLockModeRead | ImageLockModeWrite | ImageLockModeUserInputBuf,  
    230.         PixelFormat32bppARGB, &dstData);  
    231.     tmp->UnlockBits(&dstData);  
    232.     delete tmp;  
    233.     // 分别用图像数据srcData和dstData建立位图Source和Dest  
    234.     // 注:图像数据结构用于数据处理,位图用于显示,这样即可绑定数据结构和位图,  
    235.     //     又能避免每次处理图像数据时的锁定和解锁操作  
    236.     Source = new Bitmap(srcData.Width, srcData.Height, srcData.Stride,  
    237.         PixelFormat32bppARGB, (BYTE*)srcData.Scan0);  
    238.     Dest = new Bitmap(dstData.Width, dstData.Height, dstData.Stride,  
    239.         PixelFormat32bppARGB, (BYTE*)dstData.Scan0);  
    240.   
    241.     ComboBox1Change(NULL);  
    242. }  
    243. //---------------------------------------------------------------------------  
    244.   
    245. void __fastcall TForm1::FormDestroy(TObject *Sender)  
    246. {  
    247.     delete Dest;  
    248.     delete Source;  
    249.     FreeBitmapData(&dstData);  
    250.     FreeBitmapData(&srcData);  
    251.     GdiplusShutdown(gdiplusToken);  
    252. }  
    253. //---------------------------------------------------------------------------  
    254.   
    255. // 执行图像黑白调整  
    256. void __fastcall TForm1::Execute(void)  
    257. {  
    258.     for (int i = 0; i < 6; i ++)             // 获取灰度选项条数据  
    259.         bwColors[i] = TrackBars[i]->Position / 100.0;  
    260.     ImageBWCopy(&dstData, &srcData, bwColors);  // 源图黑白调整到目标图  
    261.     if (CheckBox1->Checked && Sat)               // 如果色调选项被选,着色  
    262.         ImageTint(&dstData, MixColor.Color);  
    263.     PaintBox1Paint(NULL);                       // 显示图像  
    264. }  
    265. //---------------------------------------------------------------------------  
    266.   
    267. // 预设黑白调整选项改变  
    268. void __fastcall TForm1::ComboBox1Change(TObject *Sender)  
    269. {  
    270.     if (ComboBox1->ItemIndex == CustomIndex)  
    271.         return;  
    272.     MixColor.Color = DefaultTint;       // 设置缺省混合颜色  
    273.     MixColorToHSV();                    // 计算并设置缺省色相、饱和度控件  
    274.     Lock = TLockTypes() << ltEdit << ltTrack;  
    275.     try  
    276.     {  
    277.         for (int i = 0; i < 6; i ++) // 装入预设的选项数据到相应的控件  
    278.         {  
    279.             TrackBars[i]->Position = DefOptions[ComboBox1->ItemIndex][i];  
    280.             Edits[i]->Text = DefOptions[ComboBox1->ItemIndex][i];  
    281.         }  
    282.         if (CheckBox1->Checked)  
    283.             CheckBox1->Checked = false;  // 取消色调选项  
    284.         else  
    285.             Execute();  
    286.     }  
    287.     __finally  
    288.     {  
    289.         Lock.Clear();  
    290.     }  
    291. }  
    292. //---------------------------------------------------------------------------  
    293.   
    294. // 黑白调整数据选项条改变  
    295. void __fastcall TForm1::TrackBar1Change(TObject *Sender)  
    296. {  
    297.     if (Lock.Contains(ltTrack)) return;  
    298.     Lock = TLockTypes() << ltEdit;  
    299.     try  
    300.     {  
    301.         TTrackBar *bar = (TTrackBar*)Sender;  
    302.         Edits[bar->Tag]->Text = bar->Position;  
    303.         ComboBox1->ItemIndex = CustomIndex;  // 预设下拉框设置为自定义  
    304.         Execute();  
    305.     }  
    306.     __finally  
    307.     {  
    308.         Lock.Clear();  
    309.     }  
    310. }  
    311. //---------------------------------------------------------------------------  
    312.   
    313. // 黑白调整数据编辑框改变  
    314. void __fastcall TForm1::Edit1Change(TObject *Sender)  
    315. {  
    316.     if (Lock.Contains(ltEdit)) return;  
    317.     TEdit *edit = (TEdit*)Sender;  
    318.     if (edit->Text != "" && edit->Text != "-")  
    319.         TrackBars[edit->Tag]->Position = StrToInt(edit->Text);  
    320. }  
    321. //---------------------------------------------------------------------------  
    322.   
    323. void __fastcall TForm1::Edit1KeyPress(TObject *Sender, char &Key)  
    324. {  
    325.     if (Key >= ' ' && Key != '-' && (Key < '0' || Key > '9'))  
    326.         Key = 0;  
    327. }  
    328. //---------------------------------------------------------------------------  
    329.   
    330. void __fastcall TForm1::Edit1Exit(TObject *Sender)  
    331. {  
    332.     TEdit *edit = (TEdit*)Sender;  
    333.     if (edit->Text == "")  
    334.         edit->Text = TrackBars[edit->Tag]->Position;  
    335. }  
    336. //---------------------------------------------------------------------------  
    337.   
    338. // 混合颜色改变,画混合颜色,显示其RGB值  
    339. void __fastcall TForm1::MixColorChange(void)  
    340. {  
    341.     PaintBox2Paint(NULL);  
    342.     Label18->Caption = "R: " + IntToStr(MixColor.Red) +  
    343.                     ", G: " + MixColor.Green +  
    344.                     ", B: " + MixColor.Blue;  
    345.     Execute();  
    346. }  
    347. //---------------------------------------------------------------------------  
    348.   
    349. inline void RgbSwap(int &a, int &b)  
    350. {  
    351.     a ^= b;  
    352.     b ^= a;  
    353.     a ^= b;  
    354. }  
    355.   
    356. // 按混合颜色计算并改变HSV  
    357. void __fastcall TForm1::MixColorToHSV(void)  
    358. {  
    359.     int max, mid, min;  
    360.   
    361.     max = MixColor.Red;  
    362.     mid = MixColor.Green;  
    363.     min = MixColor.Blue;  
    364.     if (max < mid) RgbSwap(max, mid);  
    365.     if (max < min) RgbSwap(max, min);  
    366.     if (min > mid) RgbSwap(min, mid);  
    367.   
    368.     int max_min = max - min;  
    369.     if (max_min == 0)  
    370.     {  
    371.         Hue = 0;  
    372.         Sat = 0;  
    373.     }  
    374.     else  
    375.     {  
    376.         int H;  
    377.         if (max == MixColor.Red)  
    378.             H = ((MixColor.Green - MixColor.Blue) * 60 + 30) / max_min;  
    379.         else if (max == MixColor.Green)  
    380.             H = ((MixColor.Blue - MixColor.Red) * 60 + 30) / max_min + 120;  
    381.         else  
    382.             H = ((MixColor.Red - MixColor.Green) * 60 + 30) / max_min + 240;  
    383.         Hue = H < 0? H + 360 : H;  
    384.         Sat = (max_min * 100) / max;  
    385.   
    386.     }  
    387.     Bright = max;  
    388. }  
    389. //---------------------------------------------------------------------------  
    390.   
    391. inline ARGB RgbToColor(int r, int g, int b)  
    392. {  
    393.     return (r << 16) | (g << 8) | b;  
    394. }  
    395.   
    396. // 按HSV计算并改变混合颜色  
    397. void __fastcall TForm1::HSVToMixColor(void)  
    398. {  
    399.     if (Sat == 0)  
    400.     {  
    401.         MixColor.Blue = MixColor.Green = MixColor.Red = Bright;  
    402.     }  
    403.     else  
    404.     {  
    405.         int index = Hue / 60;  
    406.         int f = Hue % 60;  
    407.         if ((index & 1) == 0) f = 60 - f;  
    408.         int a = Bright;  
    409.         int b = (Bright * (6000 - Sat * f)) / 6000;  
    410.         int c = (Bright * (100 - Sat)) / 100;  
    411.         switch (index)  
    412.         {  
    413.             case 0:  
    414.                 MixColor.Color = RgbToColor(a, b, c);  
    415.                 break;  
    416.             case 1:  
    417.                 MixColor.Color = RgbToColor(b, a, c);  
    418.                 break;  
    419.             case 2:  
    420.                 MixColor.Color = RgbToColor(c, a, b);  
    421.                 break;  
    422.             case 3:  
    423.                 MixColor.Color = RgbToColor(c, b, a);  
    424.                 break;  
    425.             case 4:  
    426.                 MixColor.Color = RgbToColor(b, c, a);  
    427.                 break;  
    428.             case 5:  
    429.                 MixColor.Color = RgbToColor(a, c, b);  
    430.         }  
    431.     }  
    432.     MixColorChange();  
    433. }  
    434. //---------------------------------------------------------------------------  
    435.   
    436. int __fastcall TForm1::GetHue(void)  
    437. {  
    438.     return TrackBar7->Position;  
    439. }  
    440. //---------------------------------------------------------------------------  
    441.   
    442. int __fastcall TForm1::GetSat(void)  
    443. {  
    444.     return TrackBar8->Position;  
    445. }  
    446. //---------------------------------------------------------------------------  
    447.   
    448. void __fastcall TForm1::SetHue(int hue)  
    449. {  
    450.     if (Hue == hue) return;  
    451.     Lock = TLockTypes() << ltEdit << ltTrack;  
    452.     try  
    453.     {  
    454.         TrackBar7->Position = hue;  
    455.         Edit7->Text = hue;  
    456.     }  
    457.     __finally  
    458.     {  
    459.         Lock.Clear();  
    460.     }  
    461. }  
    462. //---------------------------------------------------------------------------  
    463.   
    464. void __fastcall TForm1::SetSat(int sat)  
    465. {  
    466.     if (Sat == sat) return;  
    467.     Lock = TLockTypes() << ltEdit << ltTrack;  
    468.     try  
    469.     {  
    470.         TrackBar8->Position = sat;  
    471.         Edit8->Text = sat;  
    472.     }  
    473.     __finally  
    474.     {  
    475.         Lock.Clear();  
    476.     }  
    477. }  
    478. //---------------------------------------------------------------------------  
    479.   
    480. // 色调选盒改变  
    481. void __fastcall TForm1::CheckBox1Click(TObject *Sender)  
    482. {  
    483.     Label14->Enabled = CheckBox1->Checked;  
    484.     Label15->Enabled = CheckBox1->Checked;  
    485.     Label16->Enabled = CheckBox1->Checked;  
    486.     Label17->Enabled = CheckBox1->Checked;  
    487.     Label18->Visible = CheckBox1->Checked;  
    488.     Edit7->Enabled = CheckBox1->Checked;  
    489.     Edit8->Enabled = CheckBox1->Checked;  
    490.     TrackBar7->SliderVisible = CheckBox1->Checked;  
    491.     TrackBar8->SliderVisible = CheckBox1->Checked;  
    492.   
    493.     if (CheckBox1->Checked)  
    494.         ComboBox1->ItemIndex = CustomIndex;  
    495.     MixColorChange();  
    496. }  
    497. //---------------------------------------------------------------------------  
    498.   
    499. // 色相选项条改变  
    500. void __fastcall TForm1::TrackBar7Change(TObject *Sender)  
    501. {  
    502.     if (!Lock.Contains(ltTrack))  
    503.         Edit7->Text = TrackBar7->Position;  
    504. }  
    505. //---------------------------------------------------------------------------  
    506.   
    507. // 饱和度选项条改变  
    508. void __fastcall TForm1::TrackBar8Change(TObject *Sender)  
    509. {  
    510.     if (!Lock.Contains(ltTrack))  
    511.         Edit8->Text = TrackBar8->Position;  
    512. }  
    513. //---------------------------------------------------------------------------  
    514.   
    515. // 色相或者饱和度编辑框改变  
    516. void __fastcall TForm1::Edit7Change(TObject *Sender)  
    517. {  
    518.     TEdit *edit = (TEdit*)Sender;  
    519.     if (Lock.Contains(ltEdit) || edit->Text == "")  
    520.         return;  
    521.     Lock = TLockTypes() << ltTrack;  
    522.     try  
    523.     {  
    524.         int val = StrToInt(edit->Text);  
    525.         TTrackBar *bar = edit->Tag == 0? TrackBar7 : TrackBar8;  
    526.         if (bar->Position != val)  
    527.             bar->Position = val;  
    528.         HSVToMixColor();  
    529.     }  
    530.     __finally  
    531.     {  
    532.         Lock.Clear();  
    533.     }  
    534. }  
    535. //---------------------------------------------------------------------------  
    536.   
    537. void __fastcall TForm1::Edit7KeyPress(TObject *Sender, char &Key)  
    538. {  
    539.     if (Key >= ' ' && (Key < '0' || Key > '9'))  
    540.         Key = 0;  
    541. }  
    542. //---------------------------------------------------------------------------  
    543.   
    544. // 调用颜色对话框选择混合颜色  
    545. void __fastcall TForm1::PaintBox2Click(TObject *Sender)  
    546. {  
    547.     if (CheckBox1->Checked && ColorDialog1->Execute(Handle))  
    548.     {  
    549.         MixColor.Color = (ARGB)ColorDialog1->Color;  
    550.         MixColor.Blue = MixColor.Red;  
    551.         MixColor.Red = (BYTE)ColorDialog1->Color;  
    552.         MixColorToHSV();  
    553.         MixColorChange();  
    554.     }  
    555. }  
    556. //---------------------------------------------------------------------------  
    557.   
    558. // 画黑白调整图像和源图像  
    559. void __fastcall TForm1::PaintBox1Paint(TObject *Sender)  
    560. {  
    561.     Gdiplus::Graphics *g = new Gdiplus::Graphics(PaintBox1->Canvas->Handle);  
    562.     try  
    563.     {  
    564.         g->DrawImage(Dest, rect);  
    565.         if (Sender != NULL)  
    566.         {  
    567.             g->TranslateTransform(0, rect.Height);  
    568.             g->DrawImage(Source, rect);  
    569.         }  
    570.     }  
    571.     __finally  
    572.     {  
    573.         delete g;  
    574.     }  
    575. }  
    576. //---------------------------------------------------------------------------  
    577.   
    578. // 画混合颜色  
    579. void __fastcall TForm1::PaintBox2Paint(TObject *Sender)  
    580. {  
    581.     if (CheckBox1->Checked)  
    582.         PaintBox2->Canvas->Brush->Color =  
    583.             (MixColor.Blue << 16) | (MixColor.Green << 8) | MixColor.Red;  
    584.     else  
    585.         PaintBox2->Canvas->Brush->Color = Color;  
    586.     PaintBox2->Canvas->Pen->Color = Color;  
    587.     PaintBox2->Canvas->Rectangle(PaintBox2->ClientRect);  
    588. }  
    589. //---------------------------------------------------------------------------  

        界面程序中,实现图像黑白调整功能主要靠Execute函数完成。

        下面是几张程序运行界面图:

        1、缺省黑白调整参数运行界面,其中右上边的下拉编辑框显示的是一些预设黑白效果选项:

        2、选择红外线效果黑白调整参数运行界面:

        3、使用缺省参数进行黑白调整后,再用所选颜色进行着色的界面:

        4、在上面界面基础上,色调不变,加大黄色调参数,使图中人物衣服颜色明亮一些,同时减少蓝色调参数,使人物的围脖颜色变暗一些:

     

        因水平有限,错误在所难免,欢迎指正和指导。邮箱地址:maozefa@hotmail.com

        这里可访问《C++图像处理 -- 文章索引


  • 相关阅读:
    Java高级架构师(一)第04节:Git基本原理和安装配置使用
    发光边框
    单位px 转换成 rem
    web app 自适应 弹性布局之rem
    移动端UC /QQ 浏览器的部分私有Meta 属性
    常用<meta>标签
    移动端<head>头部 常用<meta>标签
    移动平台对 META 标签的定义
    减去border边框
    伪类共用样式缩写形式
  • 原文地址:https://www.cnblogs.com/pamxy/p/2991456.html
Copyright © 2020-2023  润新知