在C#中可以使用new Bitmap和Bitmap.clone的方法来获取一个Bitmap的备份,这两者实际上是有很大差别的。

代码如下:

Bitmap src = new Bitmap(@"C:\Users\Administrator\Desktop\樱花.png");
            Bitmap a = new Bitmap(src);
            BitmapData bgraData = a.LockBits(new Rectangle(0, 0, a.Width, a.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
            Bitmap r = new Bitmap(a.Width, a.Height);
            BitmapData rData = r.LockBits(new Rectangle(0, 0, r.Width, r.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
            byte* pSrc = (byte*)bgraData.Scan0;
            byte* pR = (byte*)rData.Scan0;
            for (int j = 0; j < a.Height; j++)
                for (int i = 0; i < a.Width; i++)
                    pR[0] = pSrc[0];//第一个像素点的b通道值为0
                    pR[1] = pSrc[1];
                    pR[2] = pSrc[2];
                    pR[3] = pSrc[3];
                    pR += 4;
                    pSrc += 4;
            r.UnlockBits(rData);
            a.UnlockBits(bgraData);

上述代码使用new Bitmap()的方法创建了src图像的备份对象,读取第一个像素的b通道值为0,alpha通道=0;

在看下面代码:

Bitmap src = new Bitmap(@"C:\Users\Administrator\Desktop\樱花.png");
            Bitmap a = (Bitmap)src.Clone();
            BitmapData bgraData = a.LockBits(new Rectangle(0, 0, a.Width, a.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
            Bitmap r = new Bitmap(a.Width, a.Height);
            BitmapData rData = r.LockBits(new Rectangle(0, 0, r.Width, r.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
            byte* pSrc = (byte*)bgraData.Scan0;
            byte* pR = (byte*)rData.Scan0;
            for (int j = 0; j < a.Height; j++)
                for (int i = 0; i < a.Width; i++)
                    pR[0] = pSrc[0];//第一个像素b通道值为25
                    pR[1] = pSrc[1];
                    pR[2] = pSrc[2];
                    pR[3] = pSrc[3];
                    pR += 4;
                    pSrc += 4;
            r.UnlockBits(rData);
            a.UnlockBits(bgraData);

上述代码使用src.clone()来创建了src的备份图像对象,但是读取第一个像素的b通道值为25,这里跟第一种方法就出现了偏差。

最后放上原图:

这张原图的第一个像素rgba的值分别为25,25,25,0

我们可以看到上述两种方法只有第二种是对的,因此在读取有透明度通道的PNG对象时,使用clone()方法,最好不要使用new Bitmap方法。

这里给自己的踩坑做个记录。

在C#中可以使用new Bitmap和Bitmap.clone的方法来获取一个Bitmap的备份,这两者实际上是有很大差别的。代码如下:Bitmap src = new Bitmap(@&quot;C:\Users\Administrator\Desktop\樱花.png&quot;); Bitmap a = new Bitmap(src); BitmapData bg...
01.以文件流的方式,假设在sdcard下有 test. png 图片 FileInputStream fis = new FileInputStream("/sdcard/test. png "); Bitmap bitmap = Bitmap Factory.decodeStream(fis); 02. 以R文件的方式,假设 res/drawable下有 test.jpg文件 Bitmap
// 创建一个具有透明背景的 Bitmap 对象 Bitmap target Bitmap = new Bitmap ( bitmap .Width, bitmap .Height); // 设置Graphics对象的CompositingMode为SourceOver以支持透明度 using (Graphics graphics = Graphics.FromImage(target Bitmap )) graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver; // 设置透明度(0为完全透明,255为不透明) float opacity = 0.5f; // 创建颜色矩阵并设置透明度 ColorMatrix colorMatrix = new ColorMatrix(); colorMatrix.Matrix33 = opacity; // 创建颜色矩阵属性 ImageAttributes imageAttributes = new ImageAttributes(); imageAttributes.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType. Bitmap ); // 绘制具有透明度的 PNG 图片 到目标 Bitmap 上 graphics.DrawImage( bitmap , new Rectangle(0, 0, bitmap .Width, bitmap .Height), 0, 0, bitmap .Width, bitmap .Height, GraphicsUnit.Pixel, imageAttributes); // 保存目标 Bitmap 图片 文件 target Bitmap .Save("path_to_output_file. png "); Console.WriteLine("半透明 PNG 图片 绘制完成。"); 在这个示例中,你需要将 `"path_to_ png _file. png "` 替换为你实际的 PNG 图片 路径。首先,创建一个源 Bitmap 对象并加载 PNG 图片 。然后,创建一个目标 Bitmap 对象,它具有与源 Bitmap 相同的尺寸。 通过设置Graphics对象的CompositingMode属性为SourceOver,我们启用了透明度支持。然后,我们通过创建一个ColorMatrix对象,并将其第三行的值设置为所需的透明度来设置透明度。接下来,我们创建了一个ImageAttributes对象,并使用SetColorMatrix方法将ColorMatrix应用于图像。 最后,使用Graphics对象的DrawImage方法将具有透明度的 PNG 图片 绘制到目标 Bitmap 上,并保存目标 Bitmap 图片 文件。 请确保提供的 PNG 图片 具有透明度(即 图片 中的某些区域是透明的),以便在绘制时产生半透明效果。 bobo-teng: 剩下的代码如下“int srcPoint[] = {423, 789, 479, 795, 0, 0, 0, 1215, 831, 0, 831, 1215}; int dragPoint[] = {418, 788, 485, 795, 0, 0, 0, 1215, 831, 0, 831, 1215}; int pointNum = 6; double intensity = 1.0; // 变形强度 int preScale = 1; // 假设需要预缩放 int gridSize = 5; // 1; // 网格大小 int method = 0; // 方法(0代表rigid, 其他代表similarity) // 执行图像处理的函数 —— 假设这个函数已经正确定义和实现 int result = f_TMLSImagewarpping(srcData, width, height, stride, dstData, outW, outH, outStride, srcPoint, dragPoint, pointNum, intensity, preScale, gridSize, method); // 保存变换后的图像 cv::imwrite("output_image.png", tarImg);” 深度学习AI美颜系列---AI瘦身效果算法揭秘 bobo-teng: 大佬的效果是真好,可惜我复现不了,我加了qq了 深度学习AI美颜系列---AI瘦身效果算法揭秘 bobo-teng: 大佬我基于你的代码,我写了一个main函数,但是跑出来的效果,下半身颜色都变了,而且变形的效果也不是我预料的那样,坐标设置没问题吧,我的图像大小是832x1216, srcpoint中最后一个点831,1215. 代码如下“int main() { std::cout << "Current path is " << fs::current_path() << '\n'; cv::Mat oriImg = cv ::imread("../底模3-boots4_merge_bra4.jpg"); // 检查图像是否成功加载 if (oriImg.empty()) { std::cerr << "Failed to load image!" << std::endl; return -1; int width = oriImg.cols; int height = oriImg.rows; int stride = oriImg.step; // 每行的实际字节数 // 创建输出图像 cv::Mat tarImg(height, width, oriImg.type()); unsigned char* srcData = oriImg.data; unsigned char* dstData = tarImg.data; int outW = width; // 输出图像宽度 int outH = height; // 输出图像高度 int outStride = stride; // 在这个例子中,假设outStride等于outW // 给定的源点和目标点数组 // int srcPoint[] = {409, 789, 353, 795, 0, 0, 0, 1215, 831, 0, 831, 1215}; // int dragPoint[] = {414, 788, 347, 795, 0, 0, 0, 1215, 831, 0, 831, 1215}; int srcPoint[] = {423, 789, 479, 795, 0, 0, 0, 1215, 831” 深度学习AI美颜系列---AI瘦身效果算法揭秘 Trent1985: 跟参数设置有关系 深度学习AI美颜系列---AI瘦身效果算法揭秘 bobo-teng: 大佬,你这个的点对这么稀疏能达到平滑的效果吗,我的用mls,会出现变化的点位置的像素拉过去了,其他的地方后知后觉,整体不平滑