C# 手写图像复制源码

6lilu9 2020-01-22 09:58:34
想写段代码实现图像复制的过程,结果不理想,效果如下:


代码如下:
        private void button1_Click(object sender, EventArgs e)
{
// 引用源图像
Bitmap source = this.MainPictureBox.Image as Bitmap;//MainPictureBox为第一个图片框
//---------------------一、获取像素集Pixels-----------------------------------
// Get width and height of bitmap
Width = source.Width;
Height = source.Height;
// Create rectangle to lock
System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, Width, Height);
// get total locked pixels count
int PixelCount = Width * Height;

// Lock bitmap and return bitmap data
BitmapData bitmapData = source.LockBits(rect, ImageLockMode.ReadWrite,
source.PixelFormat);

// get source bitmap pixel format size
int Depth = System.Drawing.Bitmap.GetPixelFormatSize(source.PixelFormat);
// create byte array to copy pixel values
int step = Depth / 8;
byte[] SorPixels = new byte[PixelCount * step];
IntPtr Iptr = bitmapData.Scan0;

// Copy data from pointer to array
Marshal.Copy(Iptr, SorPixels, 0, SorPixels.Length);

//--------------------------二、每个像素循环赋值--------------------------
byte[] desPixels = new byte[PixelCount * step];
for (int Yc = 0; Yc < source.Height; Yc++) //纵
for (int Xr = 0; Xr < source.Width; Xr++) //横
{

int x_left = Xr;
int x_right = x_left + 1;
int y_down = Yc;
int y_up = y_down + 1;
double weight_1 = y_up - Yc;
double weight_2 = Yc - y_down;
double weight_3 = x_right - Xr;
double weigth_4 = Xr - x_left;
//MessageBox.Show(weight_1.ToString() + weight_2.ToString() + weight_3.ToString() + weigth_4.ToString());


Color color_left_up = GetPixel(x_left, y_up, SorPixels, Depth);
Color color_left_down = GetPixel(x_left, y_down, SorPixels, Depth);
Color color_right_up = GetPixel(x_right, y_up, SorPixels, Depth);
Color color_right_down = GetPixel(x_right, y_down, SorPixels, Depth);

byte A = (byte)((color_left_down.A * weight_1 + color_left_up.A * weight_2) * weight_3 + (color_right_down.A * weight_1 + color_right_up.A * weight_2) * weigth_4);
byte R = (byte)((color_left_down.R * weight_1 + color_left_up.R * weight_2) * weight_3 + (color_right_down.R * weight_1 + color_right_up.R * weight_2) * weigth_4);
byte G = (byte)((color_left_down.G * weight_1 + color_left_up.G * weight_2) * weight_3 + (color_right_down.G * weight_1 + color_right_up.G * weight_2) * weigth_4);
byte B = (byte)((color_left_down.B * weight_1 + color_left_up.B * weight_2) * weight_3 + (color_right_down.B * weight_1 + color_right_up.B * weight_2) * weigth_4);

//转换为图像坐标系
// after.SetPixel(after.Width - Xr - 1, Yc, Color.FromArgb(A, R, G, B));
//after.SetPixel(Xr, after.Height - Yc-1, Color.FromArgb(A, R, G, B));

// Get color components count
int cCount = Depth / 8;
// Get start index of the specified pixel
int i = ((Yc * Width) + Xr) * cCount; //******我怀疑这里出错了*************
desPixels[i] = B;
desPixels[i + 1] = G;
desPixels[i + 2] = R;

//after.SetPixel(Xr, Yc, Color.FromArgb(A, R, G, B));
////after.SetPixel(Yc, Xr,Color.FromArgb(A, R, G, B));
//desPixels
}


//--------------------------三、生成新图像--------------------------
Bitmap desImage = new Bitmap(source.Width, source.Height);
// Get width and height of bitmap
Width = desImage.Width;
Height = desImage.Height;
// Create rectangle to lock
System.Drawing.Rectangle Desrect = new System.Drawing.Rectangle(0, 0, Width, Height);
// get total locked pixels count
int DesPixelCount = Width * Height;

// Lock bitmap and return bitmap data
BitmapData DesbitmapData = desImage.LockBits(Desrect, ImageLockMode.ReadWrite,
desImage.PixelFormat);

// get source bitmap pixel format size
Depth = System.Drawing.Bitmap.GetPixelFormatSize(desImage.PixelFormat);
// create byte array to copy pixel values
step = Depth / 8;
Iptr = DesbitmapData.Scan0;
Marshal.Copy(desPixels, 0, Iptr, desPixels.Length);
// Unlock bitmap data

desImage.UnlockBits(DesbitmapData);
source.UnlockBits(bitmapData);
this.TestPic.Image = desImage;
this.Refresh();
}
public Color GetPixel(int x, int y, byte[] Pixels, int Depth)
{
Color clr = Color.Empty;

// Get color components count
int cCount = Depth / 8;

// Get start index of the specified pixel
//int i = ((y * Width) + x) * cCount;
int i = ((y * Width) + x) * cCount;

if (i < Pixels.Length - cCount)
{
//throw new IndexOutOfRangeException();
byte b = Pixels[i];
byte g = Pixels[i + 1];
byte r = Pixels[i + 2];
clr = Color.FromArgb(r, g, b);
}
else
{ Console.WriteLine(i.ToString()); }
return clr;
}


烦请高手看两眼,跪谢!!
...全文
403885 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
github_36000833 2020-01-22
  • 打赏
  • 举报
回复
这里有两个概念: 1、图像的每行的字节,不总是等于pixels * bytesPerPixel。 2、DesbitmapData.Scan0,不总是指向图像内存数据的开端。 为了读取效率,图像行都会以4个字节为单位来补齐。 假设一个123*123大小的图像,每个像素为RGB三个字节。每行的数据长度不是123*3=369,而是补齐后的372。这也是你图像出错的原因之一。你可以用DesbitmapData.Stride来获取每行的字节数。 某些图像的Stride可以是负数,这种情况下,Scan0指向最后一行。

// 当Stride为正数:
Scan0 -> ************************
         ************************
         ************************
         ************************

// 当Stride为负数,Scan0指向最后一行:
         ************************
         ************************
         ************************
Scan0 -> ************************
6lilu9 2020-01-22
  • 打赏
  • 举报
回复

        private void button1_Click(object sender, EventArgs e)
        {
            // 引用源图像
            Bitmap source = this.MainPictureBox.Image as Bitmap;//MainPictureBox为第一个图片框
                                                                //---------------------一、获取像素集Pixels-----------------------------------
                                                                // Get width and height of bitmap
            int reWidth = source.Width;
            int reHeight = source.Height;
            // Create rectangle to lock
            System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, reWidth, reHeight);
            // get total locked pixels count
            int PixelCount = reWidth * reHeight;

            // Lock bitmap and return bitmap data
            BitmapData bitmapData = source.LockBits(rect, ImageLockMode.ReadWrite,
                                         source.PixelFormat);

            // get source bitmap pixel format size
            int Depth = System.Drawing.Bitmap.GetPixelFormatSize(source.PixelFormat);
            // create byte array to copy pixel values
            int step = Depth / 8;
            byte[] SorPixels = new byte[PixelCount * step];
            IntPtr Iptr = bitmapData.Scan0;

            // Copy data from pointer to array
            Marshal.Copy(Iptr, SorPixels, 0, SorPixels.Length);

            //--------------------------二、每个像素循环赋值--------------------------
            byte[] desPixels = new byte[PixelCount * step];
            for (int Yc = 0; Yc < source.Height; Yc++)     //纵
            {
                for (int Xr = 0; Xr < source.Width; Xr++)  //横
                {

                    int x_left = Xr;
                    int x_right = x_left + 1;
                    int y_down = Yc;
                    int y_up = y_down + 1;
                    double weight_1 = y_up - Yc;
                    double weight_2 = Yc - y_down;
                    double weight_3 = x_right - Xr;
                    double weigth_4 = Xr - x_left;
                    //MessageBox.Show(weight_1.ToString() + weight_2.ToString() + weight_3.ToString() + weigth_4.ToString());


                    Color color_left_up = GetPixel(x_left, y_up, SorPixels, Depth);
                    Color color_left_down = GetPixel(x_left, y_down, SorPixels, Depth);
                    Color color_right_up = GetPixel(x_right, y_up, SorPixels, Depth);
                    Color color_right_down = GetPixel(x_right, y_down, SorPixels, Depth);

                    byte A = (byte)((color_left_down.A * weight_1 + color_left_up.A * weight_2) * weight_3 + (color_right_down.A * weight_1 + color_right_up.A * weight_2) * weigth_4);
                    byte R = (byte)((color_left_down.R * weight_1 + color_left_up.R * weight_2) * weight_3 + (color_right_down.R * weight_1 + color_right_up.R * weight_2) * weigth_4);
                    byte G = (byte)((color_left_down.G * weight_1 + color_left_up.G * weight_2) * weight_3 + (color_right_down.G * weight_1 + color_right_up.G * weight_2) * weigth_4);
                    byte B = (byte)((color_left_down.B * weight_1 + color_left_up.B * weight_2) * weight_3 + (color_right_down.B * weight_1 + color_right_up.B * weight_2) * weigth_4);

                    //转换为图像坐标系
                    // after.SetPixel(after.Width - Xr - 1, Yc, Color.FromArgb(A, R, G, B));
                    //after.SetPixel(Xr, after.Height - Yc-1, Color.FromArgb(A, R, G, B));

                    // Get color components count
                    int cCount = Depth / 8;
                    // Get start index of the specified pixel
                    int i = ((Yc * reWidth) + Xr) * cCount;  //******我怀疑这里出错了*************
                    desPixels[i] = B;
                    desPixels[i + 1] = G;
                    desPixels[i + 2] = R;
                }
            }

            //--------------------------三、生成新图像--------------------------
            Bitmap desImage = new Bitmap(source.Width, source.Height, source.PixelFormat);
            // Get width and height of bitmap
            reWidth = desImage.Width;
            reHeight = desImage.Height;
            // Create rectangle to lock
            System.Drawing.Rectangle Desrect = new System.Drawing.Rectangle(0, 0, reWidth, reHeight);
            // get total locked pixels count
            int DesPixelCount = reWidth * reHeight;

            // Lock bitmap and return bitmap data
            BitmapData DesbitmapData = desImage.LockBits(Desrect, ImageLockMode.ReadWrite,
                                         desImage.PixelFormat);
           
            // get source bitmap pixel format size
            Depth = System.Drawing.Bitmap.GetPixelFormatSize(desImage.PixelFormat);
            // create byte array to copy pixel values
            step = Depth / 8;
            Iptr = DesbitmapData.Scan0;

            Marshal.Copy(desPixels, 0, Iptr, desPixels.Length);
            // Unlock bitmap data

            desImage.UnlockBits(DesbitmapData);
            source.UnlockBits(bitmapData);
            this.TestPic.Image = desImage;
            //this.Refresh();
        }
        public Color GetPixel(int x, int y, byte[] Pixels, int Depth)
        {
            Color clr = Color.Empty;

            // Get color components count
            int cCount = Depth / 8;

            // Get start index of the specified pixel
            //int i = ((y * Width) + x) * cCount;
            int i = ((y * Width) + x) * cCount;

            if (i < Pixels.Length - cCount)
            {
                //throw new IndexOutOfRangeException();
                byte b = Pixels[i];
                byte g = Pixels[i + 1];
                byte r = Pixels[i + 2];
                clr = Color.FromArgb(r, g, b);
            }
            else
            { Console.WriteLine(i.ToString()); }
            return clr;
        }
未搞定,找不出原因,也没听懂
引用 1 楼 github_36000833 的回复:
这里有两个概念: [/code]
原因,只能处理到这里了。 因为从未用C#作过图像处理,搞了两天没搞定(不夸张,真2天) 此问题留存 留作以后有时间研究。
引用 1 楼 github_36000833 的回复:
这里有两个概念: [/code]

4,816

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 图表区
社区管理员
  • 图表区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧