Delphi图像处理 -- 填充浮雕

2024-03-03 22:40

本文主要是介绍Delphi图像处理 -- 填充浮雕,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

阅读提示:

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

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

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

    本文代码必须包括文章《Delphi图像处理 -- 数据类型及公用过程》中的ImageData.pas单元   

 

    这个填充浮雕效果过程代码已经完成好几天了,但是一直没敢在BLOG上发表,因为这是我在研究Photoshop浮雕效果做实验时,无意中写的一段代码,当时就感觉这个效果虽然不是我想要的Photoshop浮雕效果,但比Photoshop浮雕效果的应用价值应该不会差,可以说是各有特色。只是当时感觉处理速度较慢,同时顾虑该浮雕效果是我妙想天开,发表后会不会有引起嘲笑。经过了几天的改进和原理论证,我觉得该浮雕效果从原理上是说得通的,而改进后的速度一般情况下比彩色浮雕处理快,在浮雕深度较小(< 8)的时候,比灰色浮雕处理还快,所以还是决定发表在这里,供大家讨论其实用性,或给出改进意见。至于这种浮雕效果的名称,刚开始时因其效果类似石雕,准备取名石雕效果,经改进后,可用任何颜色或者图案进行填充浮雕画面,所以取名填充浮雕效果。

下面先给出浮雕过程处理代码

procedure GetSrcColor;
asmpush      esi           // esi = src.Scan0mov       eax, ecxsar       eax, 12imul      eax, ebxadd       esi, eax      // esi += (y / 4096 * src.Stride)mov       eax, edxsar       eax, 12shl       eax, 2add       esi, eax      // esi +=  (x / 4096 * 4)call      _GetBilinearColormovd      eax, xmm0movd      mm0, eaxpunpcklbw mm0, mm7      // return mm0 = ARGB (word * 4)pop       esi
end;// 实填充浮雕。Data 图像数据结构, Angle 角度, Size 长度, Color 填充色
procedure ImageSolidSculpture(var Data: TImageData; Angle: Single;Size: LongWord; Color: TARGB);
varx, y, Radius: Integer;xDelta, yDelta: Integer;width, height: Integer;dstOffset, divSize: Integer;src: TImageData;
beginif Size > 128 then Size := 128;divSize := DivTab[Size];Radius := (Size + 1) shr 1;        // 图像边框扩展半径Angle := PI * Angle / 180;xDelta := Round(Cos(Angle) * 4096);yDelta := Round(Sin(Angle) * 4096);x := (Radius shl 12) - xDelta * Size div 2;y := (Radius shl 12) - yDelta * Size div 2;width := x + (Data.Width shl 12);height := Data.Height;if Data.AlphaFlag thenArgbConvertPArgb(Data);src := _GetExpandData(Data, Radius);asmpush      esipush      edipush      ebxmov       eax, Datalea       edx, srccall      _SetCopyRegsmov       dstOffset, ebxmov       eax, Size       // mm3 = word * 4 = Size div to mulmovq      mm3, qword ptr MMDivTab[eax*8]pxor      xmm7, xmm7pxor      mm7, mm7        // xmm7 = mm7 = 0movd      mm2, Color      // mm2 = word Colorpunpcklbw mm2, mm7        mov       ebx, src.Stridemov       ecx, y          // for (; y < Height; y += 4096)
@@yLoop:                      // {mov       edx, x          //   for (; x < Width; x += 4096)
@@xLoop:                      //   {push      edxpush      ecxpush      edi             //     x1 = x, y1 = ypxor      mm1, mm1mov       edi, Size       //     for (i = Size - 1; Size > 0; i --)
@@addLoop:                    //     {call      GetSrcColor     //       mm1 += GetSrcColor(x1, y1)paddw     mm1, mm0add       ecx, yDelta     //       y1 += yDeltaadd       edx, xDelta     //       x1 += xDeltadec       edijnz       @@addLoop       //     }call      GetSrcColor     //     mm0 = GetSrcColor(x1, y1)pmulhuw   mm1, mm3        //     mm1 /= Sizepsubw     mm1, mm0        //     mm1 -= mm0paddw     mm1, mm2        //     mm1 += Colorpackuswb  mm1, mm7pop       edipop       ecxpop       edxmov       al, [edi].TARGBQuad.Alphamovd      [edi], mm1      //     *edi = mm1mov       [edi].TARGBQuad.Alpha, aladd       edi, 4          //     edi ++add       edx, 1000hcmp       edx, widthjl        @@xLoop         //   }add       edi, dstOffsetadd       ecx, 1000hdec       heightjnz       @@yLoopemmspop       ebxpop       edipop       esiend;FreeImageData(src);if Data.AlphaFlag thenPArgbConvertArgb(Data);
end;// 图案填充浮雕。Data 图像数据结构, Angle 角度, Size 长度, FillData 填充图像数据结构
procedure ImageTextureSculpt(var Data: TImageData; Angle: Single;Size: LongWord; const FillData: TImageData);// 调整fillData宽度和高度为其最大2的幂,并拷贝到Resultfunction AdjustFillData: TImageData;asmpush    esipush    edipush    ebxpush    eaxpush    eaxpush    eax           // NewImageData Result parammov     edi, fillDatabsr     ecx, [edi].TImageData.Widthxor     eax, eax      // mov eax, 1bts     eax, ecx      // shl eax, cl (width max bit)bsr     ecx, [edi].TImageData.Heightxor     edx, edx      // mov edx, 1bts     edx, ecx      // shl edx, cl (height max bit)mov     ecx, pf32bitcall    NewImageData  // Result = NewImageData(width, height, pf32bit)pop     eaxmov     edx, edicall    _SetCopyRegs@@cpyLoop:push    ecxrep     movsdpop     ecxadd     esi, eaxdec     edxjnz     @@cpyLooppop     eax// (Result.Width - 1) * 4: 宽度的最大余数*4,作为x*4的掩码mov     edx, [eax].TImageData.Widthdec     edxshl     edx, 2mov     [eax].TImageData.Width, edx// Result.Height - 1: 高度的最大余数作为y的掩码dec     [eax].TImageData.Heightpop     ebxpop     edipop     esiend;varx, y, Radius: Integer;xDelta, yDelta: Integer;width, height: Integer;dstOffset: Integer;src, back: TImageData;
beginif Size > 128 then Size := 128;Radius := (Size + 1) shr 1;        // 图像边框扩展半径Angle := PI * Angle / 180;xDelta := Round(Cos(Angle) * 4096);yDelta := Round(Sin(Angle) * 4096);x := (Radius shl 12) - xDelta * Size div 2;y := (Radius shl 12) - yDelta * Size div 2;width := x + (Data.Width shl 12);height := Data.Height;if Data.AlphaFlag thenArgbConvertPArgb(Data);src := _GetExpandData(Data, Radius);back := AdjustFillData;asmpush      esipush      edipush      ebxmov       eax, Datalea       edx, srccall      _SetCopyRegsmov       dstOffset, ebxmov       eax, Size       // mm3 = word * 4 = Size div to mulmovq      mm3, qword ptr MMDivTab[eax*8]pxor      xmm7, xmm7      // xmm7 = mm7 = 0pxor      mm7, mm7        mov       ebx, src.Stridemov       ecx, y          // for (; y < Height; y += 4096)
@@yLoop:                      // {mov       edx, x          //   for (; x < Width; x += 4096)
@@xLoop:                      //   {push      edxpush      ecx             push      edipush      edxpush      ecx             //     x1 = x, y1 = ymov       edi, Size       //     for (i = Size - 1; Size > 0; i --)pxor      mm1, mm1        //     {
@@addLoop:call      GetSrcColor     //       mm1 += GetSrcColor(x1, y1)paddw     mm1, mm0add       ecx, yDelta     //       y1 += yDeltaadd       edx, xDelta     //       x1 += xDeltadec       edijnz       @@addLoop       //     }
@@1:call      GetSrcColor     //     mm0 = GetSrcColor(x1, y1)pmulhuw   mm1, mm3        //     mm1 /= Sizepsubw     mm1, mm0        //     mm1 -= mm0pop       eaxpop       edxshr       eax, 12         //     fy = (y / 4096) & back.Height
//    shr       edx, 12         //     fx = (x / 4096) & back.Widthshr       edx, 10and       eax, back.TImageData.Height // height is y maskand       edx, back.TImageData.Width  // width is x*4 maskbsr       ecx, back.TImageData.Strideshl       eax, cl
//    shl       edx, 2add       eax, edxadd       eax, back.TImageData.Scan0movd      mm0, [eax]      //     mm0 = FillData.Scan0[fy * back.Stride + fx * 4]punpcklbw mm0, mm7paddw     mm0, mm1        //     mm0 += mm1packuswb  mm0, mm7pop       edipop       ecxpop       edxmov       al, [edi].TARGBQuad.Alphamovd      [edi], mm0      //     *edi = mm0mov       [edi].TARGBQuad.Alpha, aladd       edi, 4          //     edi ++add       edx, 1000hcmp       edx, widthjl        @@xLoop         //   }add       edi, dstOffsetadd       ecx, 1000hdec       heightjnz       @@yLoopemmspop       ebxpop       edipop       esiend;FreeImageData(back);FreeImageData(src);if Data.AlphaFlag thenPArgbConvertArgb(Data);
end;

 

从处理流程看,填充浮雕和彩色浮雕、灰色浮雕是一样的,但在像素处理上是不相同的。下面是用一个用45度角,2像素深度浮雕差值计算矩阵图来说明几种浮雕效果像素处理的差异 

各矩阵中,中间的点可以看作为要处理的像素。

灰度浮雕固定地取左上角点和右下角的差值加上128背景值 (无论深度多大,都是如此,只是矩阵中间的0多少的问题),如此一来,差异小的像素趋向于背景色,差异大的像素形成“黑白分明”的阴线和阳线,这就成了灰色的浮雕效果,浮雕深度越大,“黑白分明”的效果就越明显,当深度达到一个比较大的值时,画面上会形成加强了的正、负片以及图像原色彩3层画面的共存状态;

彩色浮雕也是固定的取邻近3个点的值减去2倍右下角点的值,由于被减的点数大于减的点数,在雕刻阴影形成时保留了很大的亮度,这就相当于给各像素加了一个不固定的背景值,所以形成彩色浮雕效果;

而填充浮雕的则是取主对角线除右下角外的各点之和的平均值,减去右下角点的值,再加上填充背景色,在背景色固定的前提下(假定128),会形成类似灰度浮雕的效果,但是由于是取主对角线除右下角外的各点之和的平均值,就相当于先对像素点做了一定的表面模糊后再减去右下角点的值,所以,当雕刻深度增大时,不会形成明显的“黑白分明”效应,而是有一定的模糊过渡带,即类似阴影的半影调。

下面是以45度角,深度为10,背景色128的灰度浮雕和填充浮雕效果比较图:

 

左上角是原图,左下角是灰度浮雕效果图,右上角是填充浮雕效果图,因为填充浮雕在浮雕效果处理前对原图作了灰度处理,为便于比较,所以右下角是灰度化后的灰色浮雕效果图。

从比较图上可以看出,当浮雕深度较大时,无论是否去色,灰度浮雕效果的阳线带和阴线带都很明显,而填充浮雕则存在过渡半影调,所以,看起来有石雕的效果。另外,从灰色背景上看,填充浮雕效果明显的平坦于灰色浮雕效果,这是因为填充浮雕处理有一定的表面模糊作用的缘故。

填充浮雕可以以任意颜色和图案作为背景填充,这就使得填充浮雕过程能产生各种效果的浮雕图,为了便于使用,我把填充浮雕过程写成了2个过程,分别用来处理实色填充和图案填充。

下面先对实色填充作几个图片处理测试:

TGpBitmap测试代码(仿玉石浮雕效果)

 

procedure TForm1.Button3Click(Sender: TObject);
varbmp: TGpBitmap;g: TGpGraphics;data: TImageData;
beginbmp := TGpBitmap.Create('..\media\graysource.bmp');g := TGpGraphics.Create(Canvas.Handle);g.DrawImage(bmp, 0, 0);data := LockGpBitmap(bmp);ImageSolidSculpture(data, 45, 10, $AEC0C8);UnlockGpBitmap(bmp, data);g.DrawImage(bmp, 0, data.Height);g.Free;bmp.Free;
end;

 

效果图如下,上面是原图,下面左边是45度,深度为5的浮雕效果,下面右边是45度,深度为10的浮雕效果。

 

 

原图:

 

你是否觉得象玉石浮雕?特别是右边图中那些重叠着的叶片, 真有着一种晶莹剔透的感觉!

 

下面是以角度30,深度8,填充颜色为$A5140A的仿玛瑙色浮雕效果图,测试代码就不贴了:

 

TBitmap填充图案测试代码:

 

procedure TForm1.Button4Click(Sender: TObject);
varbmp, fbmp: TBitmap;data, fdata: TImageData;
beginbmp := TBitmap.Create;fbmp := TBitmap.Create;bmp.LoadFromFile('..\media\graysource.bmp');fbmp.LoadFromFile('..\media\back-2.bmp');data := GetBitmapData(bmp);fData := GetBitmapData(fbmp);ImageTextureSculpt(data, 45, 5, fData);Canvas.Draw(0, 0, bmp);fbmp.Free;bmp.free;
end;


下面是使用4种不同填充图案调用ImageTextureSculpture过程分别形成的浮雕效果图(原图在文章前面),角度50,浮雕深度从左上角开始,依次是8657

 

填充浮雕前也可以不进行灰度处理,有时还能产生意想不到的效果,下面是使用图案填充的2幅效果:

填充背景图案:

通过几天的研究和测试,发现浮雕角度、深度和填充色(图案)的选择,应根据图片的实际情况确定,如上图中,左上角的填充图案颜色较深、较杂,这就需要把浮雕深度用大一点,反之,如左下角就要相应小一点;图像较平淡的,不宜用很深的浮雕;浮雕角度与图像光照方向基本对应;填充颜色(图案)也应按图像具体选用,如前面的玉雕效果图,如果换成其它图片,效果不一定那么好,反过来也可以说,那张图用玛瑙色效果就差多了。

关于填充效果图的介绍就到此为止,欢迎朋友们提出改进意见。

最后重申一下,该效果确是本人无意中搞出来的,如果已经有类似的方法,纯属巧合,本人不和你争“专利权”了。

    《Delphi图像处理》系列使用GDI+单元下载地址和说明见文章《GDI+ for VCL基础 -- GDI+ 与 VCL》。

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

    这里可访问《Delphi图像处理 -- 文章索引》。

 

这篇关于Delphi图像处理 -- 填充浮雕的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/771153

相关文章

参会邀请 | 第二届机器视觉、图像处理与影像技术国际会议(MVIPIT 2024)

第二届机器视觉、图像处理与影像技术国际会议(MVIPIT 2024)将于2024年9月13日-15日在中国张家口召开。 MVIPIT 2024聚焦机器视觉、图像处理与影像技术,旨在为专家、学者和研究人员提供一个国际平台,分享研究成果,讨论问题和挑战,探索前沿技术。诚邀高校、科研院所、企业等有关方面的专家学者参加会议。 9月13日(周五):签到日 9月14日(周六):会议日 9月15日(周日

渐变颜色填充

GradientFill函数可以对特定的矩形区域或者三角形区域进行渐变颜色的填充。我们先来看看GradientFill函数到底长得什么样子,帅不帅。 [cpp]  view plain copy print ? BOOL GradientFill(     _In_  HDC hdc,     _In_  PTRIVERTEX pVertex,     _In_  ULONG

【Godot4.3】多边形的斜线填充效果基础实现

概述 图案(Pattern)填充是一个非常常见的效果。其中又以斜线填充最为简单。本篇就探讨在Godot4.3中如何使用Geometry2D和CanvasItem的绘图函数实现斜线填充效果。 基础思路 Geometry2D类提供了多边形和多边形以及多边形与折线的布尔运算。按照自然的思路,多边形的斜线填充应该属于“多边形与折线的布尔运算”范畴。 第一个问题是如何获得斜线,这条斜线应该满足什么样

08_Tensorflow2图像处理秘籍:让图片‘听话’,AI也能成艺术家!

1. 图像数据处理 图像处理是指图像在神经网络训练之前的预处理,是人工智能视觉领域的重要组成部分。通过图像处理技术对图像数据集进行处理有两方面的作用:(1)将原始数据集处理成合格的、规范是数据集;(2)通过图像处理技术实现对原始数据集的增广。 # 库引入import matplotlib.pyplot as pltimport tensorflow as tf# 图像读取image_

python图像处理的图像几何变换

一.图像几何变换 图像几何变换不改变图像的像素值,在图像平面上进行像素变换。适当的几何变换可以最大程度地消除由于成像角度、透视关系乃至镜头自身原因所造成的几何失真所产生的负面影响。几何变换常常作为图像处理应用的预处理步骤,是图像归一化的核心工作之一[1]。 一个几何变换需要两部分运算: 空间变换:包括平移、缩放、旋转和正平行投影等,需要用它来表示输出图像与输入图像之间的像素映射关系。灰度插值

从零开始学cv-0:图像处理基础知识

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一,图像分类1.1、模拟图像1.2、数字图像 二、颜色模式(颜色存储)2.1、RGB模式(发光模式)2.2、CMYK模式2.3、HSB模式2.4、Lab模式2.5、位图模式(Bitmap Mode)2.6、灰度模式(Grayscale Mode)2.7、索引颜色模式(Indexed Color Mode)

数据处理与数据填充在Pandas中的应用

在数据分析和机器学习项目中,数据处理是至关重要的一步。Pandas作为Python中用于数据分析和操作的一个强大库,提供了丰富的功能来处理和清洗数据。本文将深入探讨Pandas在数据处理,特别是数据填充方面的应用。 在实际的数据集中,缺失值(Missing Values)或异常值(Outliers)是常见的问题。这些不完整或错误的数据如果不加以处理,会严重影响数据分析的准确性和机器学习模型的性能

图像处理基础篇-镜像仿射透视

一.图像镜像 图像镜像是图像旋转变换的一种特殊情况,通常包括垂直方向和水平方向的镜像。水平镜像通常是以原图像的垂直中轴为中心,将图像分为左右两部分进行堆成变换。如图7-1所示: 垂直镜像通常是以原图像的水平中轴线为中心,将图像划分为上下两部分进行堆成变换的过程,示意图如图7-2所示。 在Python中主要调用OpenCV的flip()函数实现图像镜像变换,函数原型如下: dst =

在c#下用opencv(emgecv)做图像处理环境配置

①首先要将编程环境配置好。 ⑴首先将vs2010下载安装,然后下载了emgucv-windows-universal-cuda 2.9.0.1922放在了D:\CV的目录下 (注意:emgucv-windows-universal-cuda 2.9.0.1922所放置的目录与后面的path配置有关,所以这里加以说明,也可以放在其他位置,但后面的path也要相应的改变)。 ⑵接着,要配置p

图像处理:基于直方图矫正的图像色彩均衡

from itertools import chainimport cv2import osimport numpy as npimport datetimeclass BrightnessBalance:def __init__(self):passdef arrayToHist(self,gray):'''计算灰度直方图,并归一化:param gray_path::return:'''