您现在的位置:首页 >> 图形媒体 >> 图形媒体 >> 内容

Delphi的TBitmap对象改进的图像线性亮度调整方法

时间:2011/9/3 15:00:40 点击:

  核心提示:线性图像亮度一般是将图像像素的RGB转换为HSL(HSV)等颜色空间,对L(V)部分进行增减调整后,再转换为RGB颜色空间,优点是调整过图像层次感很强;缺点是代码较复杂,调整速度慢,而且当图像亮度增减...

线性图像亮度一般是将图像像素的RGB转换为HSL(HSV)等颜色空间,对L(V)部分进行增减调整后,再转换为RGB颜色空间,优点是调整过图像层次感很强;缺点是代码较复杂,调整速度慢,而且当图像亮度增减量较大时有很大的失真

针对上面两种方法的优缺点,本人参照Photoshop的对比度、饱和度调整原理,对图像亮度调整方法进行了改进,经测试,效果还不错:主要有不失真调整范围宽、有较好的层次感、尽可能减少图像信息损失量、运算速度较快及代码也不太复杂等。

 

下面给出采用Delphi的TBitmap对象调整亮度的Delphi测试代码(BASM过程),如果使用GDI+则更简单,因TImageData与GDI+的TBitmapData是兼容的

 

  TImageData = packed record 
    Width: Integer;           // 像素宽度  
    Height: Integer;          // 像素高度  
    Stride: Integer;          // 扫描宽度  
    PixelFormat: Integer;     // 像素信息的格式  
    Scan0: Pointer;           // 扫描行首地址  
    Reserved: Integer;        // 保留  
  end;  
  PImageData = ^TImageData;  
 
procedure FillAlpha(Data: TImageData);  
asm 
    mov     ecx, [eax].TImageData.Width  
    imul    ecx, [eax].TImageData.Height  
    mov     edx, [eax].TImageData.Scan0  
    add     edx, 3 
    mov     eax, 255 
    cld  
  @PixelLoop:  
    mov     [edx], al  
    add     edx, 4 
    loop    @PixelLoop  
end;  
 
function GetBitmapData(Bitmap: TBitmap): TImageData;  
var 
  FillFlag: Boolean;  
begin 
  FillFlag := Bitmap.PixelFormat <> pf32bit;  
  Bitmap.PixelFormat := pf32bit;  
  Result.Width := Bitmap.Width;  
  Result.Height := Bitmap.Height;  
  Result.Stride := Result.Width shl 2;  
  Result.Scan0 := Bitmap.ScanLine[Result.Height - 1];  
  Result.PixelFormat := -1;   // Windows bitmap format flag  
  Result.Reserved := 0;  
  if FillFlag then FillAlpha(Result);  
end;  
 
procedure ImageLinearBrightness(Data: TImageData; Value: Integer);  
asm 
        push    esi  
        push    edi  
    push    ebx  
      
        test    edx, edx            // if (Value == 0) return  
        jz      @end 
    mov   ebx, edx  
    mov   edi, eax  
        jl      @@2 
        cmp     ebx, 255            // if (Value > 0)  
        jle     @@1                 // {  
        mov     ebx, 255            //   if (Value > 255) Value = 255  
    @@1:  
        mov     eax, 65536          //   Value = 65536 / (256 - Value) - 256  
        mov     ecx, 256 
        sub     ecx, ebx  
        cdq  
        div     ecx  
        sub     eax, 256 
        mov     ebx, eax            // }  
    @@2:  
    mov   esi, [edi].TImageData.Height  
    imul  esi, [edi].TImageData.Width  
    mov   edi, [edi].TImageData.Scan0  
        cld  
    @PixelLoop:  
        mov     ecx, 3 
    @RGBLoop:  
        movzx   eax, [edi]          // rgb = rgb + rgb * value / 256  
        mov     edx, eax  
        imul    eax, ebx  
        sar     eax, 8 
        add     eax, edx  
        jns     @@3 
        xor     eax, eax  
        jmp     @@4 
    @@3:  
        cmp     eax, 255 
        jle     @@4 
        mov     eax, 255 
    @@4:  
        stosb  
        loop    @RGBLoop  
        inc     edi  
    dec   esi  
        jnz     @PixelLoop  
 
    @end:  
    pop     ebx  
        pop     edi  
        pop     esi  
end;  
 
procedure TForm1.Button1Click(Sender: TObject);  
var 
  Bmp: TBitmap;  
  Jpg: TJPEGImage;  
  Data: TImageData;  
begin 
  Bmp := TBitmap.Create;  
  Jpg := TJPEGImage.Create;  
  Jpg.LoadFromFile('D:\001-1.jpg');  
  Bmp.Assign(Jpg);  
  Jpg.Free;  
  Data := GetBitmapData(Bmp);  
  ImageLinearBrightness(Data, 100);  
  Canvas.Draw(0, 0, Bmp);  
  Bmp.Free;  
end; 

作者:maozefa 来源:转载
共有评论 0相关评论
发表我的评论
  • 大名:
  • 内容:
本类推荐
  • 没有
本类固顶
  • 没有
  • 盒子文章(www.2ccc.com) © 2024 版权所有 All Rights Reserved.
  • 沪ICP备05001939号