在C#中无失真的裁剪和打印图像文档

时间:2023-02-10 00:17:43

I'm using WinForms. In my form I have a picturebox I use to display image documents. The problem is when I crop the image and then print the document out the image becomes slightly distorted. If I don't crop the image document and print it regularly the image document does not become distorted.

我正在使用WinForms。在我的表格中,我有一个用于显示图像文档的图片框。问题是当我裁剪图像然后打印文档时图像变得稍微扭曲。如果我不裁剪图像文档并定期打印,图像文档不会变形。

How do I crop and print the image documents without them being distorted?

如何裁剪和打印图像文档而不会使图像文档失真?

Or is there a better way to code this so it can crop and print without the image document being distorted? If so, how can i do it?

或者是否有更好的方法来编码,以便它可以裁剪和打印而不会使图像文档失真?如果是这样,我该怎么办?

Notes:

笔记:

  • My picturebox is set to Zoom because the images i work with is big:

    我的图片框设置为缩放,因为我使用的图像很大:

  • Example of image document Dimensions: 2500 x 3100

    图像文档示例尺寸:2500 x 3100

  • My picturebox does not have a border

    我的图片框没有边框

    int _cropX, _cropY, _cropWidth, _cropHeight;
    public Pen _cropPen;
    private State _currentState;
    
    private enum State
    {
        Crop
    }
    
    private void Open_btn_Click(object sender, EventArgs e)
    {
        // open file dialog 
        OpenFileDialog open = new OpenFileDialog();
    
        if (open.ShowDialog() == DialogResult.OK)
        {
            // display image in picture box
            pictureBox1.Image = new Bitmap(open.FileName);
        }
    }
    
    private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
    {
        try
        {
            if (Crop_Checkbox.Checked == true)
            {
                Cursor = Cursors.Default;
                if (_currentState == State.Crop)
                {
                    if (_cropWidth < 1)
                    {
                        return;
                    }
    
                    Rectangle rect = new Rectangle(_cropX, _cropY, _cropWidth, _cropHeight);
                    //First we define a rectangle with the help of already calculated points
    
                    Bitmap originalImage = new Bitmap(pictureBox1.Image, pictureBox1.Width, pictureBox1.Height);
                    //Original image
    
                    Bitmap img = new Bitmap(_cropWidth, _cropHeight);
                    // for cropinf image
    
                    Graphics g = Graphics.FromImage(img);
                    // create graphics
    
                    g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                    g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
                    g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                    //set image attributes
    
                    g.DrawImage(originalImage, 0, 0, rect, GraphicsUnit.Pixel);
    
                    pictureBox1.Image = img;
                    pictureBox1.Width = img.Width;
                    pictureBox1.Height = img.Height;
                }
    
            }
            else
            {
                Cursor = Cursors.Default;
            }
        }
        catch (Exception)
        {
    
        }
    }
    
    private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
    {
        if (Crop_Checkbox.Checked == true)
        {
            if (_currentState == State.Crop)
            {
                Cursor = Cursors.Cross;
                if (e.Button == System.Windows.Forms.MouseButtons.Left)
                {
                    //X and Y are the coordinates of Crop
                    pictureBox1.Refresh();
                    _cropWidth = e.X - _cropX;
                    _cropHeight = e.Y - _cropY;
                    pictureBox1.CreateGraphics().DrawRectangle(_cropPen, _cropX, _cropY, _cropWidth, _cropHeight);
                }
    
            }
        }
        else
        {
            Cursor = Cursors.Default;
        }
    
    }
    
    private void Crop_Checkbox_CheckedChanged(object sender, EventArgs e)
    {
        if (Crop_Checkbox.Checked == true)
        {
            this.Cursor = Cursors.Cross;
        }
    }
    
    private void Print_btn_Click(object sender, EventArgs e)
    {
        System.Drawing.Printing.PrintDocument myPrintDocument1 = new System.Drawing.Printing.PrintDocument();
        PrintDialog myPrinDialog1 = new PrintDialog();
        myPrintDocument1.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(printDocument1_PrintPage);
        myPrinDialog1.Document = myPrintDocument1;
    
    
        if (myPrinDialog1.ShowDialog() == DialogResult.OK)
        {
            myPrintDocument1.Print();
        }
    }
    
    private void printDocument1_PrintPage(object sender, PrintPageEventArgs e)
    {
        e.Graphics.DrawImage(pictureBox1.Image, 10, 10); //(Standard paper size is 850 x 1100 or 2550 x 3300 pixels)
    }
    
    private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
    {
        if (Crop_Checkbox.Checked == true)
        {
            if (_currentState == State.Crop)
            {
                if (e.Button == System.Windows.Forms.MouseButtons.Left)
                {
                    Cursor = Cursors.Cross;
                    _cropX = e.X;
                    _cropY = e.Y;
    
                    _cropPen = new Pen(Color.FromArgb(153, 180, 209), 3); //2 is Thickness of line
    
                    _cropPen.DashStyle = DashStyle.DashDotDot;
                    pictureBox1.Refresh();
                }
            }
        }
        else
        {
            Cursor = Cursors.Default;
        }
    
    }
    

在C#中无失真的裁剪和打印图像文档

Test: Slightly Distorted:

测试:略有失真:

在C#中无失真的裁剪和打印图像文档

Test: Not Distorted:

测试:未扭曲:

在C#中无失真的裁剪和打印图像文档

在C#中无失真的裁剪和打印图像文档

Test: The picture above is a test. This is what happened when i took the below code out from pictureBox1_MouseUp:

测试:上图是测试。这是当我从pictureBox1_MouseUp中取出以下代码时发生的事情:

Bitmap originalImage = new Bitmap(pictureBox1.Image, pictureBox1.Width, pictureBox1.Height);

And edited/replaced (originalImage to pictureBox1.Image):

并编辑/替换(originalImage to pictureBox1.Image):

g.DrawImage(pictureBox1.Image, 0, 0, rect, GraphicsUnit.Pixel);

1 个解决方案

#1


1  

Bitmap originalImage = new Bitmap(pictureBox1.Image, pictureBox1.Width, pictureBox1.Height);

That is most likely where the problem started. This can cause pictureBox1.Image to be rescaled to force-fit it to the pictureBox1 size. Depends on whether the picturebox has borders and its SizeMode property value. Rescaling causes the image to be resampled, the color of a pixel in the new bitmap is calculated from the values of its neighboring pixels in the original image as directed by the selected InterpolationMode.

这很可能是问题开始的地方。这可能导致pictureBox1.Image重新调整以强制适应pictureBox1大小。取决于图片框是否具有边框及其SizeMode属性值。重新缩放使得图像被重新采样,新位图中的像素的颜色根据所选择的InterpolationMode的指示从原始图像中的其相邻像素的值计算。

This in effect blurs the resulting image. That works well on a photo but this is text that critically depends on anti-aliasing pixels to look decent on a low-resolution monitor. Slight changes to those pixels ruins the effect and they no longer smoothly blend the letter shape against the background anymore. They become more visible, best way to describe it is that the resulting text looks "fat".

这实际上模糊了所得到的图像。这对照片效果很好,但这是一个严重依赖于抗锯齿像素的文本,在低分辨率显示器上看起来不错。对这些像素的轻微更改会破坏效果,并且它们不再能够平滑地将字母形状与背景混合。它们变得更加明显,描述它的最佳方式是生成的文本看起来“胖”。

I see no obvious reason to do this at all in the posted code. Delete the statement and replace originalImage with pictureBox1.Image.

我发现在发布的代码中根本没有明显的理由这样做。删除语句并用pictureBox1.Image替换originalImage。

Also beware that printing this image is likely to be disappointing. Now those anti-aliasing pixels get turned into 6x6 blobs of ink on paper. That only ever looks good when you have long arms. As long as the font size is this small and you have no control over the anti-aliasing choice then there's very little you can do about that. Printed text only ever looks good when you use PrintDocument and Graphics.DrawString().

还要注意打印此图像可能会令人失望。现在,这些抗锯齿像素在纸上变成了6x6的墨水斑点。只有长臂才能看起来很好看。只要字体大小很小并且您无法控制抗锯齿选择,那么您就无法做到这一点。使用PrintDocument和Graphics.DrawString()时,打印文本只会看起来很好。

#1


1  

Bitmap originalImage = new Bitmap(pictureBox1.Image, pictureBox1.Width, pictureBox1.Height);

That is most likely where the problem started. This can cause pictureBox1.Image to be rescaled to force-fit it to the pictureBox1 size. Depends on whether the picturebox has borders and its SizeMode property value. Rescaling causes the image to be resampled, the color of a pixel in the new bitmap is calculated from the values of its neighboring pixels in the original image as directed by the selected InterpolationMode.

这很可能是问题开始的地方。这可能导致pictureBox1.Image重新调整以强制适应pictureBox1大小。取决于图片框是否具有边框及其SizeMode属性值。重新缩放使得图像被重新采样,新位图中的像素的颜色根据所选择的InterpolationMode的指示从原始图像中的其相邻像素的值计算。

This in effect blurs the resulting image. That works well on a photo but this is text that critically depends on anti-aliasing pixels to look decent on a low-resolution monitor. Slight changes to those pixels ruins the effect and they no longer smoothly blend the letter shape against the background anymore. They become more visible, best way to describe it is that the resulting text looks "fat".

这实际上模糊了所得到的图像。这对照片效果很好,但这是一个严重依赖于抗锯齿像素的文本,在低分辨率显示器上看起来不错。对这些像素的轻微更改会破坏效果,并且它们不再能够平滑地将字母形状与背景混合。它们变得更加明显,描述它的最佳方式是生成的文本看起来“胖”。

I see no obvious reason to do this at all in the posted code. Delete the statement and replace originalImage with pictureBox1.Image.

我发现在发布的代码中根本没有明显的理由这样做。删除语句并用pictureBox1.Image替换originalImage。

Also beware that printing this image is likely to be disappointing. Now those anti-aliasing pixels get turned into 6x6 blobs of ink on paper. That only ever looks good when you have long arms. As long as the font size is this small and you have no control over the anti-aliasing choice then there's very little you can do about that. Printed text only ever looks good when you use PrintDocument and Graphics.DrawString().

还要注意打印此图像可能会令人失望。现在,这些抗锯齿像素在纸上变成了6x6的墨水斑点。只有长臂才能看起来很好看。只要字体大小很小并且您无法控制抗锯齿选择,那么您就无法做到这一点。使用PrintDocument和Graphics.DrawString()时,打印文本只会看起来很好。