C#,图片分层(Layer Bitmap)绘制,反色、高斯模糊及凹凸贴图等处理的高速算法与源程序
图像反色Invert
对图像处理的过程中会遇到一些场景需要将图片反色,反色就是取像素的互补色,比如当前像素是0X00FFFF,对其取反色就是0XFFFFFF – 0X00FFFF = 0XFF0000,依次对图像中的每个像素这样做,最后得到的就是原始图像的反色。
高斯模糊(Gauss Blur)算法
高斯模糊(英语:Gaussian Blur),也叫高斯平滑,是在Adobe Photoshop、GIMP以及Paint.NET等图像处理软件中广泛使用的处理效果,通常用它来减少图像噪声以及降低细节层次。这种模糊技术生成的图像,其视觉效果就像是经过一个毛玻璃在观察图像,这与镜头焦外成像效果散景以及普通照明阴影中的效果都明显不同。高斯平滑也用于计算机视觉算法中的预先处理阶段,以增强图像在不同比例大小下的图像效果(参见尺度空间表示以及尺度空间实现)。 从数学的角度来看,图像的高斯模糊过程就是图像与正态分布做卷积。由于正态分布又叫作高斯分布,所以这项技术就叫作高斯模糊。图像与圆形方框模糊做卷积将会生成更加精确的焦外成像效果。由于高斯函数的傅立叶变换是另外一个高斯函数,所以高斯模糊对于图像来说就是一个低通滤波器。
凹凸贴图bump map
所有物体表面多少都会有一点凹凸的质感,但建模时如果需要再现这些质感,一个一个建或雕刻就太麻烦了。 bump maps这个参数就是利用光线和阴影的控制去制造凹凸质感的假象,但毕竟是利用光线,所以如果是特写镜头或特定角度(平面)还是会漏馅。
参考:
C#,图片像素(Bitmap Pixel)的读取与绘制的快速方法与源程序https://blog.csdn.net/beijinghorn/article/details/125253281
源代码 Layer.cs:
using System;
using System.Text;
using System.Collections;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
class Layer : ICloneable
{
internal FastBitmap _bitmap;
private FastBitmap _mask;
public Double _opacity;
private Int32 _offsetx, _offsety;
public Layer(Int32 width, Int32 height)
{
_bitmap = new FastBitmap(width, height, PixelFormat.Format32bppArgb);
Clear(Color.Transparent);
_opacity = 1.0;
}
public Double Opacity
{
get { return _opacity; }
set { _opacity = value; }
}
public FastBitmap Bitmap
{
get { return _bitmap; }
}
public FastBitmap Mask
{
get { return _mask; }
set { _mask = value; }
}
public Int32 OffsetX
{
get { return _offsetx; }
set { _offsetx = value; }
}
public Int32 OffsetY
{
get { return _offsety; }
set { _offsety = value; }
}
public Object Clone()
{
Layer clone = new Layer(_bitmap.Width, _bitmap.Height);
clone._bitmap = (FastBitmap)_bitmap.Clone();
return clone;
}
public void Clear(Color c)
{
_bitmap.Lock();
for (Int32 y = 0; y < _bitmap.Height; y++)
for (Int32 x = 0; x < _bitmap.Width; x++)
_bitmap.SetPixel(x, y, c);
_bitmap.Unlock();
}
public void DrawText(Int32 x, Int32 y, String text, Font font,
Brush brush)
{
Graphics g = Graphics.FromImage(_bitmap._bitmap);
g.DrawString(text, font, brush, x, y, StringFormat.GenericTypographic);
g.Dispose();
}
public void FillRectangle(Int32 x, Int32 y, Int32 width,
Int32 height, Brush brush)
{
Graphics g = Graphics.FromImage(_bitmap._bitmap);
g.FillRectangle(brush, x, y, width, height);
g.Dispose();
}
public Color GetPixel(Int32 x, Int32 y)
{
return _bitmap.GetPixel(x, y);
}
public void Invert()
{
_bitmap.Lock();
for (Int32 y = 0; y < _bitmap.Height; y++) {
for (Int32 x = 0; x < _bitmap.Width; x++) {
Color c = _bitmap.GetPixel(x, y);
_bitmap.SetPixel(x, y, Color.FromArgb(c.A,
255 - c.R, 255 - c.G, 255 - c.B));
}
}
_bitmap.Unlock();
}
private Single Gauss(Single x, Single middle, Single width)
{
if (width == 0)
return 1F;
Double t = - (1.0 / width) * ((middle - x) * (middle - x));
return (Single)Math.Pow(Math.E, t);
}
public void Blur(Int32 horz, Int32 vert)
{
Single weightsum;
Single[] weights;
FastBitmap t = (FastBitmap)_bitmap.Clone();
_bitmap.Lock();
t.Lock();
weights = new Single[horz * 2 + 1];
for (Int32 i = 0; i < horz * 2 + 1; i++) {
Single y = Gauss(-horz + i, 0, horz);
weights[i] = y;
}
for (Int32 row = 0; row < _bitmap.Height; row++) {
for (Int32 col = 0; col < _bitmap.Width; col++) {
Double r = 0;
Double g = 0;
Double b = 0;
weightsum = 0;
for (Int32 i = 0; i < horz * 2 + 1; i++) {
Int32 x = col - horz + i;
if (x < 0) {
i += -x;
x = 0;
}
if (x > _bitmap.Width - 1)
break;
Color c = _bitmap.GetPixel(x, row);
r += c.R * weights[i];
g += c.G * weights[i];
b += c.B * weights[i];
weightsum += weights[i];
}
r /= weightsum;
g /= weightsum;
b /= weightsum;
Byte br = (Byte)Math.Round(r);
Byte bg = (Byte)Math.Round(g);
Byte bb = (Byte)Math.Round(b);
if (br > 255) br = 255;
if (bg > 255) bg = 255;
if (bb > 255) bb = 255;
t.SetPixel(col, row, Color.FromArgb(br, bg, bb));
}
}
weights = new Single[vert * 2 + 1];
for (Int32 i = 0; i < vert * 2 + 1; i++) {
Single y = Gauss(-vert + i, 0, vert);
weights[i] = y;
}
for (Int32 col = 0; col < _bitmap.Width; col++) {
for (Int32 row = 0; row < _bitmap.Height; row++) {
Double r = 0;
Double g = 0;
Double b = 0;
weightsum = 0;
for (Int32 i = 0; i < vert * 2 + 1; i++) {
Int32 y = row - vert + i;
if (y < 0) {
i += -y;
y = 0;
}
if (y > _bitmap.Height - 1)
break;
Color c = t.GetPixel(col, y);
r += c.R * weights[i];
g += c.G * weights[i];
b += c.B * weights[i];
weightsum += weights[i];
}
r /= weightsum;
g /= weightsum;
b /= weightsum;
Byte br = (Byte)Math.Round(r);
Byte bg = (Byte)Math.Round(g);
Byte bb = (Byte)Math.Round(b);
if (br > 255) br = 255;
if (bg > 255) bg = 255;
if (bb > 255) bb = 255;
_bitmap.SetPixel(col, row, Color.FromArgb(br, bg, bb));
}
}
t.Dispose();
_bitmap.Unlock();
}
private Byte GetBumpMapPixel(FastBitmap bmp, Int32 x, Int32 y)
{
if (x < 0)
x = 0;
if (x > _bitmap.Width - 1)
x = _bitmap.Width - 1;
if (y < 0)
y = 0;
if (y > _bitmap.Height - 1)
y = _bitmap.Height - 1;
return bmp.GetIntensity(x, y);
}
public void BumpMap(Layer bumpmap, Int32 azimuth, Int32 elevation,
Int32 bevelwidth, Boolean lightzalways1)
{
bumpmap._bitmap.Lock();
_bitmap.Lock();
for (Int32 row = 0; row < _bitmap.Height; row++) {
for (Int32 col = 0; col < _bitmap.Width; col++) {
Byte[] x = new Byte[6];
x[0] = GetBumpMapPixel(bumpmap._bitmap, col - 1, row - 1);
x[1] = GetBumpMapPixel(bumpmap._bitmap, col - 1, row - 0);
x[2] = GetBumpMapPixel(bumpmap._bitmap, col - 1, row + 1);
x[3] = GetBumpMapPixel(bumpmap._bitmap, col + 1, row - 1);
x[4] = GetBumpMapPixel(bumpmap._bitmap, col + 1, row - 0);
x[5] = GetBumpMapPixel(bumpmap._bitmap, col + 1, row + 1);
Single normal_x = x[0] + x[1] + x[2] - x[3] - x[4] - x[5];
x[0] = GetBumpMapPixel(bumpmap._bitmap, col - 1, row + 1);
x[1] = GetBumpMapPixel(bumpmap._bitmap, col - 0, row + 1);
x[2] = GetBumpMapPixel(bumpmap._bitmap, col + 1, row + 1);
x[3] = GetBumpMapPixel(bumpmap._bitmap, col - 1, row - 1);
x[4] = GetBumpMapPixel(bumpmap._bitmap, col - 0, row - 1);
x[5] = GetBumpMapPixel(bumpmap._bitmap, col + 1, row - 1);
Single normal_y = x[0] + x[1] + x[2] - x[3] - x[4] - x[5];
Single normal_z = (6F * 255F) / bevelwidth;
Single length = (Single)Math.Sqrt(
normal_x * normal_x +
normal_y * normal_y +
normal_z * normal_z);
if (length != 0) {
normal_x /= length;
normal_y /= length;
normal_z /= length;
}
Double azimuth_rad = azimuth / 180.0 * Math.PI;
Double elevation_rad = elevation / 180.0 * Math.PI;
Single light_x = (Single)(Math.Cos(azimuth_rad) *
Math.Cos(elevation_rad));
Single light_y = (Single)(Math.Sin(azimuth_rad) *
Math.Cos(elevation_rad));
Single light_z = 1F;
if (!lightzalways1)
light_z = (Single)Math.Sin(elevation_rad);
Single cos_light_normal = 0;
cos_light_normal += normal_x * light_x;
cos_light_normal += normal_y * light_y;
cos_light_normal += normal_z * light_z;
Color c = _bitmap.GetPixel(col, row);
Single r = c.R;
Single g = c.G;
Single b = c.B;
r *= cos_light_normal;
g *= cos_light_normal;
b *= cos_light_normal;
Byte red = (Byte)Math.Min(Math.Round(r), 255);
Byte green = (Byte)Math.Min(Math.Round(g), 255);
Byte blue = (Byte)Math.Min(Math.Round(b), 255);
_bitmap.SetPixel(col, row, Color.FromArgb(red, green, blue));
}
}
_bitmap.Unlock();
bumpmap._bitmap.Unlock();
}
}
源代码 Layers.cs:
using System;
using System.Text;
using System.Collections;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
class Layers
{
LayeredImage _image;
ArrayList _layers = new ArrayList();
public Layers(LayeredImage image)
{
_image = image;
}
public Int32 Count
{
get { return _layers.Count; }
}
public Layer Add()
{
Layer layer = new Layer(_image.Width, _image.Height);
_layers.Add(layer);
return layer;
}
public Layer Copy(Layer layer)
{
Layer copy = (Layer)layer.Clone();
_layers.Add(copy);
return copy;
}
public Layer this[Int32 i]
{
get { return (Layer)_layers[i]; }
}
}
源代码 LayeredImage.cs:
using System;
using System.Text;
using System.Collections;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
class LayeredImage
{
Int32 _width, _height;
Bitmap _checkerboard;
Layers _layers;
public LayeredImage(Int32 width, Int32 height)
{
_width = width;
_height = height;
_layers = new Layers(this);
_checkerboard = new Bitmap(32, 32, PixelFormat.Format24bppRgb);
Color darkgray = Color.FromArgb(102,102,102);
Color lightgray = Color.FromArgb(153,153,153);
for (Int32 i = 0; i < 32; i++) {
for (Int32 j = 0; j < 32; j++) {
if ((i < 16 && j < 16) || (i >= 16 && j >= 16))
_checkerboard.SetPixel(j, i, lightgray);
else
_checkerboard.SetPixel(j, i, darkgray);
}
}
Layer bglayer = _layers.Add();
Graphics g = Graphics.FromImage(bglayer._bitmap._bitmap);
TextureBrush brush = new TextureBrush(_checkerboard);
g.FillRectangle(brush, 0, 0, _width, _height);
brush.Dispose();
g.Dispose();
}
public Int32 Width
{
get { return _width; }
}
public Int32 Height
{
get { return _height; }
}
public Layers Layers
{
get { return _layers; }
}
internal FastBitmap Flatten()
{
FastBitmap final = new FastBitmap(_width, _height,
PixelFormat.Format24bppRgb);
final.Lock();
for (Int32 i = 0; i < _layers.Count; i++) {
Layer l = _layers[i];
l._bitmap.Lock();
if (l.Mask != null)
l.Mask.Lock();
}
for (Int32 y = 0; y < _height; y++) {
for (Int32 x = 0; x < _width; x++) {
Color c0 = _layers[0]._bitmap.GetPixel(x, y);
for (Int32 i = 1; i < _layers.Count; i++) {
Layer layer = _layers[i];
Color c1 = Color.Transparent;
if (x >= layer.OffsetX &&
x <= layer.OffsetX + layer._bitmap.Width - 1 &&
y >= layer.OffsetY &&
y <= layer.OffsetY + layer._bitmap.Height - 1) {
c1 = layer._bitmap.GetPixel(x - layer.OffsetX,
y - layer.OffsetY);
}
if (c1.A == 255 && layer.Opacity == 1.0 &&
layer.Mask == null) {
c0 = c1;
} else {
Double tr, tg, tb, a;
a = c1.A / 255.0 * layer.Opacity;
if (layer.Mask != null) {
a *= layer.Mask.GetIntensity(x, y) / 255.0;
}
tr = c1.R * a + c0.R * (1.0 - a);
tg = c1.G * a + c0.G * (1.0 - a);
tb = c1.B * a + c0.B * (1.0 - a);
tr = Math.Round(tr);
tg = Math.Round(tg);
tb = Math.Round(tb);
tr = Math.Min(tr, 255);
tg = Math.Min(tg, 255);
tb = Math.Min(tb, 255);
c0 = Color.FromArgb((Byte)tr, (Byte)tg, (Byte)tb);
}
}
final.SetPixel(x, y, c0);
}
}
for (Int32 i = 0; i < _layers.Count; i++) {
Layer l = _layers[i];
l._bitmap.Unlock();
if (l.Mask != null)
l.Mask.Unlock();
}
final.Unlock();
return final;
}
}
相关文章
- C#中缓存的使用 ajax请求基于restFul的WebApi(post、get、delete、put) 让 .NET 更方便的导入导出 Excel .net core api +swagger(一个简单的入门demo 使用codefirst+mysql) C# 位运算详解 c# 交错数组 c# 数组协变 C# 添加Excel表单控件(Form Controls) C#串口通信程序
- C# DateTime的11种构造函数 [Abp 源码分析]十五、自动审计记录 .Net 登陆的时候添加验证码 使用Topshelf开发Windows服务、记录日志 日常杂记——C#验证码 c#_生成图片式验证码 C# 利用SharpZipLib生成压缩包 Sql2012如何将远程服务器数据库及表、表结构、表数据导入本地数据库
- 利用反射快速给Model实体赋值 使用 Task 简化异步编程 Guid ToString 格式知多少?(GUID 格式) Parallel Programming-实现并行操作的流水线(生产者、消费者) c# 无损高质量压缩图片代码 8种主要排序算法的C#实现 (一) 8种主要排序算法的C#实现 (二)
- 浅谈c#的三个高级参数ref out 和Params C#中is与as的区别分析 “登陆”与“登录”有何区别 经典SQL语句大全(绝对的经典)
- c#运用反射获取属性和设置属性值
- C#中的函数式编程:序言(一)
- 【卷土重来之C#学习笔记】(二)c#编程概述
- c# 中?、??与?:的使用
- C#,图像二值化(10)——全局阈值的灰度平均值算法(Gray-Average Thresholding)及其源代码
- C#,图论与图算法,用于检查给定图是否为欧拉图(Eulerian Graph)的算法与源程序
- C#,图论与图算法,计算无向连通图中长度为n环的算法与源代码
- C#,斐波那契数列(Fibonacci Sequence)的八种算法与源代码
- C#,双向链表(Doubly Linked List)归并排序(Merge Sort)算法与源代码
- C#,数值计算,矩阵的乔莱斯基分解(Cholesky decomposition)算法与源代码
- C#,数据检索算法之跳跃搜索(Jump Search)的源代码
- C#,计算几何,随机点集之三角剖分的德劳内(Delaunay)算法的源代码
- C#,字符串匹配(模式搜索)Sunday算法的源代码
- C#,码海拾贝(15)——“对称正定矩阵”的求逆和“托伯利兹矩阵”求逆的“埃兰特”方法之C#源代码,《C#数值计算算法编程》源代码升级改进版
- C#类型转化
- C# Winform picturebox 通过button按钮 点击显示图片
- C#中服务端接受前端JSON字符串转换成字典集合
- Unity 热更 C#(编译型语言) 和 lua(解释型语言) 比较
- C#访问远程主机资源的方法,多种方式
- C#并发编程-异步编程基础-报告进度
- C#,单元测试入门