GDI+ 在Delphi程序的应用 -- 调整图像亮度
来源:互联网 发布:有关人工智能的新闻 编辑:程序博客网 时间:2024/05/16 07:05
GDI+ 在Delphi程序的应用 -- 调整图像亮度
调整图像的亮度可以有很多方法,最常用的方法就是对图像像素点的R、G、B三个分量同时进行增加(减少)某个值,达到调整亮度的目的。我在这里使用GDI+图像的扫描线来处理,核心处理采用了2个相同的过程,一个是Pascal过程,一个是嵌入汇编过程,通过比较,对小的图像几乎没有什么区别,对比较大的图像处理还是有一定的区别(具体测试效果见代码中的注释),这说明Delphi的代码优化还是很好的。
使用GDI+图像的扫描线处理必须调用TGpBitmap.LockBits和TGpBitmap.UnLockBits过程,而这2个过程的调用相当耗时,以2304 *1728大小的图片为例,耗时竟达188毫秒!而亮度调整过程最长只耗时63毫秒。由此可以看出使用GDI+图像扫描线处理图像并非十分理想。
需要说明的是,本例子及以后GDI+ for Delphi例子的Gdiplus单元是本人自己写的,与目前网上流通的版本有一定的区别,浏览着需要测试例子,可作适当修改,或者发邮件向本人索取Gdiplus单元。
说明:为了统一《GDI+ 在Delphi程序的应用》系列文章所用数据类型和图像处理格式,本文代码已重新修订,代码中所用Gdiplus单元下载地址及BUG更正见文章《GDI+ for VCL基础 -- GDI+ 与 VCL》。(2008.8.18记)
数据类型:
- type
- // 与GDI+ TBitmapData结构兼容的图像数据结构
- TImageData = packed record
- Width: LongWord; // 图像宽度
- Height: LongWord; // 图像高度
- Stride: LongWord; // 图像扫描线字节长度
- PixelFormat: LongWord; // 未使用
- Scan0: Pointer; // 图像数据地址
- Reserved: LongWord; // 保留
- end;
- PImageData = ^TImageData;
- // 获取TBitmap图像的TImageData数据结构,便于处理TBitmap图像
- function GetImageData(Bmp: TBitmap): TImageData;
- begin
- Bmp.PixelFormat := pf32bit;
- Result.Width := Bmp.Width;
- Result.Height := Bmp.Height;
- Result.Scan0 := Bmp.ScanLine[Bmp.Height - 1];
- Result.Stride := Result.Width shl 2;
- // Result.Stride := (((32 * Bmp.Width) + 31) and $ffffffe0) shr 3;
- end;
过程代码:
- // 调整图像亮度
- procedure Brightness(Data: TImageData; Value: Integer);
- asm
- push esi
- push edi
- mov edi, [eax + 16]
- mov esi, [eax + 4]
- imul esi, [eax]
- cld
- @PixelLoop:
- mov ecx, 3
- @RGBLoop:
- movzx eax, [edi]
- add eax, edx
- jns @@1
- xor eax, eax
- jmp @@2
- @@1:
- cmp eax, 255
- jle @@2
- mov eax, 255
- @@2:
- stosb
- loop @RGBLoop
- inc edi
- dec esi
- jnz @PixelLoop
- pop edi
- pop esi
- end;
- // 调整GDI+图像亮度
- procedure GdipBrightness(Bmp: TGpBitmap; Value: Integer);
- var
- Data: TBitmapData;
- begin
- if Value = 0 then Exit;
- Data := Bmp.LockBits(GpRect(0, 0, Bmp.Width, Bmp.Height), [imRead, imWrite], pf32bppARGB);
- try
- Brightness(TImageData(Data), Value);
- finally
- Bmp.UnlockBits(Data);
- end;
- end;
- // 调整TBitmap图像亮度
- procedure BitmapBrightness(Bmp: TBitmap; Value: Integer);
- begin
- if Value <> 0 then
- Brightness(GetImageData(Bmp), Value);
- end;
测试代码:
- // 为方便初学者理解前面的BASM代码,写了个处理GDI+图像亮度的纯Pas代码过程
- // 稍稍改动一下,也可用来处理TBitmap图像亮度
- procedure GdipBrightness_Pas(Bmp: TGpBitmap; Value: Integer);
- function SetRGBValue(Rgb: Byte): Integer;
- begin
- Result := Value + Rgb; // 像素颜色分量 + 亮度值
- if Result < 0 then // 像素颜色分量 >= 0 and <= 255
- Result := 0
- else if Result > 255 then
- Result := 255;
- end;
- var
- Data: TBitmapData;
- P: PRGBQuad;
- I, Count: LongWord;
- begin
- if Value = 0 then Exit;
- Data := Bmp.LockBits(GpRect(0, 0, Bmp.Width, Bmp.Height), [imRead, imWrite], pf32bppARGB);
- try
- Count := Data.Width * Data.Height;
- P := Data.Scan0;
- for I := 1 to Count do
- begin
- P^.rgbBlue := SetRGBValue(P^.rgbBlue);
- P^.rgbGreen := SetRGBValue(P^.rgbGreen);
- P^.rgbRed := SetRGBValue(P^.rgbRed);
- Inc(P);
- end;
- finally
- Bmp.UnlockBits(Data);
- end;
- end;
- // 测试GDI+图像
- procedure TForm1.Button1Click(Sender: TObject);
- var
- Image: TGpBitmap;
- g: TGpGraphics;
- begin
- Image := TGpBitmap.Create('D:/VclLib/GdiplusDemo/Media/20041001.jpg');
- g := TGpGraphics.Create(Handle, False);
- g.DrawImage(Image, 10, 10);
- // GdipBrightness_Pas(Image, 30);
- GdipBrightness(Image, 30);
- g.DrawImage(Image, 10, 220);
- Image.Free;
- g.Free;
- end;
- // 测试TBitmap图像
- procedure TForm1.Button2Click(Sender: TObject);
- var
- Image: TBitmap;
- begin
- Image := TBitmap.Create;
- Image.LoadFromFile('D:/VclLib/GdiplusDemo/Media/20041001.bmp');
- Canvas.Draw(10, 10, Image);
- BitmapBrightness(Image, -30);
- Canvas.Draw(10, 220, Image);
- Image.Free;
- end;
- GDI+ 在Delphi程序的应用 -- 调整图像亮度
- GDI+ 在Delphi程序的应用 -- 线性调整图像亮度
- GDI+ 在Delphi程序的应用 -- ColorMatrix与图像亮度
- GDI+ 在Delphi程序的应用 -- 图像饱和度调整
- GDI+ 在Delphi程序的应用 -- 图像二值化
- GDI+ 在Delphi程序的应用 -- 图像二值化
- GDI+ 在Delphi程序的应用 -- GDI+图像与GDI位图的相互转换
- GDI+ 在Delphi程序的应用 -- GDI+图像与GDI位图的相互转换
- GDI+ 在Delphi程序的应用 -- 仿Photoshop的明度调整
- GDI+在Delphi程序的应用 – 真彩色图像转索引图像
- GDI+ 在Delphi程序的应用 -- FontCollection
- GDI+ 在Delphi程序的应用 -- 图像的透明显示技巧
- GDI+ 在Delphi程序的应用 -- 多帧(页)图像的分解与合成
- GDI+在Delphi程序的应用:多帧(页)图像的分解与合成
- GDI+ 在Delphi程序的应用 -- ColorMatrix与图像灰度化
- GDI+ 在Delphi程序的应用 -- 多帧(页)图像动画播放
- GDI+ 在Delphi程序的应用 -- ColorMatrix与图像灰度化
- GDI+ 在Delphi程序的应用 -- Matrix应用心得
- linux文件系统维护zz tips
- 2007年1月28日
- linux下软件的基本安装和卸载zz (初学者看)
- [转载]在Redhat Linux AS 4下实现软件RAID tips
- 佩雷尔曼:一无所有的数学国王
- GDI+ 在Delphi程序的应用 -- 调整图像亮度
- Linux网络基础 zz 基于debian--仅供参考
- linux的安装方式zz (初学者看)
- 写给2007
- 真笨,多行多列的显示居然困扰了自己一段时间~~~
- 在应用程序中对xml文件的各种操作
- 2007-01-28
- CSS解决未知高度垂直居中终极方案, 适应多栏结构, 兼容IE 5/6/7, FF/OPERA/SAFARI
- 如何成为一名优秀的程序员(上)