Обрезка и печать изображений без искажений в С#

Я использую WinForms. В моей форме у меня есть картинка, которую я использую для отображения документов изображений. Проблема заключается в том, когда я обрезаю изображение, а затем распечатываю документ, изображение слегка искажается. Если я не обрезаю документ изображения и не печатаю его регулярно, документ изображения не будет искажен.

Как обрезать и распечатывать документы изображений без их искажения?

Или есть лучший способ закодировать это, чтобы он мог обрезать и печатать без искажения документа изображения? Если да, то как я могу это сделать?

Примечания:

  • У моего Picturebox установлен Zoom, потому что изображения, с которыми я работаю, большие:

  • Пример документа изображения Размеры: 2500 x 3100

  • У моего фотобумага нет рамки

    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;
        }
    
    }
    

введите описание изображения здесь

Тест: Слегка искаженный:

введите описание изображения здесь

Тест: Не искажен:

введите описание изображения здесь

введите описание изображения здесь

Тест: На рисунке выше приведен тест. Это то, что произошло, когда я взял приведенный ниже код из pictureBox1_MouseUp:

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

И отредактировано/заменено (originalImage to pictureBox1.Image):

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

Ответы

Ответ 1

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

Скорее всего, там, где проблема началась. Это может привести к тому, что pictureBox1.Image будет перемасштабирован, чтобы приспособить его к размеру pictureBox1. Зависит от того, имеют ли рамки изображения границы и значение свойства SizeMode. Повторное масштабирование приводит к повторной выборке изображения, цвет пикселя в новом растровом изображении вычисляется из значений соседних пикселей исходного изображения в соответствии с выбранным интерполяционным модулем.

Это фактически размывает полученное изображение. Это хорошо работает на фотографии, но это текст, который критически зависит от пикселей сглаживания, чтобы выглядеть прилично на мониторе с низким разрешением. Небольшие изменения этих пикселей разрушают эффект, и они больше не плавно смешивают форму буквы с фоном. Они становятся более заметными, лучший способ описать, что полученный текст выглядит "жирным".

Я не вижу очевидной причины делать это вообще в опубликованном коде. Удалите инструкцию и замените originalImage на pictureBox1.Image.

Также будьте осторожны, что печать этого изображения может быть разочаровывающей. Теперь эти пиксели сглаживания превращаются в 6x6 капель чернил на бумаге. Это всегда выглядит хорошо, когда у тебя длинные руки. Пока размер шрифта такой маленький, и у вас нет контроля над выбором сглаживания, тогда вы можете сделать это очень мало. Печатный текст только когда-либо выглядит хорошо, когда вы используете PrintDocument и Graphics.DrawString().