Почему мое изображение штрих-кода не соответствует размеру бумаги, указанному в настройках принтера штрих-кода, когда я пытаюсь его напечатать?

Я использую Zen Barcode Rendering Framework для создания штрих-кодов в приложении Windows Form C#. У меня есть два текстовых поля (одно для самого штрих-кода и одно для соответствующего текста, который я хочу напечатать на этикетке со штрих-кодом). Точно так же я загружаю сгенерированное изображение штрих-кода в окно с изображением и пытаюсь распечатать его, но каждый раз, когда я нажимаю кнопку печати, результат не подходит (иногда принтер печатает белую пустую этикетку, а иногда штрих-код печатается не полностью. Интересно, я должен сказать, что для того, чтобы штрих-код отображался на этикетке, даже если она кажется неполной, мне приходится выбирать очень большие форматы бумаги). Вот мой код:

Код для события нажатия кнопки создания штрих-кода:

private void Button1_Click(object sender, EventArgs e)
{
        string barcode = textBox1.Text;

        Zen.Barcode.Code128BarcodeDraw brcd = Zen.Barcode.BarcodeDrawFactory.Code128WithChecksum;
        var barcodeImage = brcd.Draw(barcode, 50);

        int resultImageWidth;
        if(barcodeImage.Width >= textBox2.Text.Length*8)
        {
            resultImageWidth = barcodeImage.Width;
        }
        else
        {
            resultImageWidth = textBox2.Text.Length*8;
        }

        var resultImage = new Bitmap(resultImageWidth, barcodeImage.Height + 60); // 20 is bottom padding, adjust to your text

        using (var graphics = Graphics.FromImage(resultImage))
        using (var font = new Font("IranYekan", 10))
        using (var brush = new SolidBrush(Color.Black))
        using (var format = new StringFormat()
        {
            Alignment = StringAlignment.Center, // Also, horizontally centered text, as in your example of the expected output
            LineAlignment = StringAlignment.Far
        })
        {
            graphics.Clear(Color.White);
            graphics.DrawImage(barcodeImage, (resultImageWidth - barcodeImage.Width)/2, 0);
            graphics.DrawString(textBox1.Text, font, brush, resultImage.Width / 2, resultImage.Height-30, format);
            graphics.DrawString(textBox2.Text, font, brush, resultImage.Width / 2, resultImage.Height, format);
        }

        pictureBox1.Image = resultImage;

}

Код события нажатия кнопки печати:

private void Button2_Click(object sender, EventArgs e)
{
    PrintDialog pd = new PrintDialog();
    PrintDocument doc = new PrintDocument();
    doc.PrintPage += Doc_PrintPage;
    pd.Document = doc;
    if (pd.ShowDialog() == DialogResult.OK)
    {
        doc.Print();
    }
}

И моя функция Doc_PrintPage():

private void Doc_PrintPage(object sender, PrintPageEventArgs e)
{
    Bitmap bm = new Bitmap(pictureBox1.Width, pictureBox1.Height);
    pictureBox1.DrawToBitmap(bm, new Rectangle(0, 0, pictureBox1.Width, pictureBox1.Height));
    e.Graphics.DrawImage(bm, 0, 0);
    bm.Dispose();
}

Моя основная цель - полностью напечатать штрих-код с соответствующим текстом внутри границ бумаги, который выбирается при появлении диалогового окна печати.

Вы можете увидеть пользовательский интерфейс моего приложения на изображении ниже: введите здесь описание изображения

Вот мои распечатанные результаты, как вы видите, им не хватает качества, и изображение каждый раз не подходит правильно. Я использую Brother QL-700 введите здесь описание изображения введите здесь описание изображения введите здесь описание изображения введите описание изображения  здесь


person Naser.Sadeghi    schedule 04.08.2020    source источник
comment
Убедитесь, что у вас установлен последний драйвер производителя. Вы подключаетесь к IP-адресу принтера или используете драйвер принтера? Всегда следует использовать драйвер печати, который инициализирует принтер и настраивает параметры.   -  person jdweng    schedule 04.08.2020
comment
@jdweng Поскольку я установил драйвер принтера, я просто выбираю свой принтер из списка доступных принтеров и после установки соответствующего размера бумаги нажимаю «ОК» в диалоговом окне печати.   -  person Naser.Sadeghi    schedule 04.08.2020
comment
Есть ли у драйвера опция FIT Paper size. Я бы создал панель, а затем поле с изображением и текст на панели и распечатал панель.   -  person jdweng    schedule 04.08.2020
comment
Насколько я знаю, нет.   -  person Naser.Sadeghi    schedule 04.08.2020
comment
См. следующее: stackoverflow.com/questions /45743005/   -  person jdweng    schedule 04.08.2020
comment
Возможно, вам придется уменьшить изображение до размера (в пикселях) страницы печатного документа. Я полагаю, вы бы сделали это, применив графическое преобразование к e.Graphics.   -  person Ann L.    schedule 04.08.2020
comment
@ЭннЛ. К сожалению, это не сработало. Нет ли способа заставить изображение pictureBox печатать в масштабе выбранного размера бумаги?   -  person Naser.Sadeghi    schedule 08.08.2020
comment
Я только что обновил вопрос, чтобы показать результаты печати, которые я получаю.   -  person Naser.Sadeghi    schedule 08.08.2020
comment
Решающее значение для четкого штрих-кода на бумаге имеет то, что его размер не изменяется. Прямо сейчас размер get изменяется дважды. Во-первых, чтобы заставить его соответствовать картинке, уменьшая масштаб. Далее, чтобы соответствовать разрешению принтера, резервное масштабирование. Измените обработчик события PrintPage на e.Graphics.DrawImage(pictureBox1.Image, 0, 0) для очень быстрого улучшения. Как заставить Code128BarcodeDraw генерировать изображение с собственным разрешением принтера, не очевидно, чем больше вы его сделаете, тем лучше оно будет выглядеть.   -  person Hans Passant    schedule 08.08.2020
comment
DPI принтера сильно отличается от DPI экрана. Экран обычно имеет разрешение от 96 до 150 точек на дюйм, тогда как принтер — от 300 до 1200+ точек на дюйм.   -  person Andy    schedule 08.08.2020
comment
Если вы используете Brother QL-700, имейте в виду, что вам не следует создавать штрих-код в Zen Framework и отправлять его в виде изображения на принтер. Пробовали ли вы использовать P-touch Editor для отправки штрих-кодов на принтер?   -  person Brian Anderson    schedule 10.08.2020
comment
Кроме того, убедитесь, что этикетка выходит из принтера по одному символу штрих-кода за раз, и вы не печатаете штрих-код вертикально. Другими словами, штрих-код должен считываться в том направлении, в котором он напечатан. (Возможно, вы пытались напечатать повернутый штрих-код). Также убедитесь, что изображение не сжато.   -  person Brian Anderson    schedule 10.08.2020


Ответы (1)


Вот в чем проблема. Принтеры имеют DPI (точек на дюйм), который намного выше, чем у вашего экрана. Ваш экран обычно имеет разрешение 96-150 точек на дюйм, тогда как большинство принтеров имеют разрешение 600 точек на дюйм или выше. Вы пытаетесь отобразить изображение, созданное с разрешением 96 DPI, на устройство, которое использует для рендеринга 600+ DPI. Это будет выглядеть, ну, как то, что вы показываете на своих изображениях.

Объект Graphics, возвращаемый контекстом принтера, будет сильно отличаться от объекта Graphics, созданного для отображения информации на экране. Итак, что вам нужно сделать, так это визуализировать объект Graphics, а не объект Image, который вы создали для отображения на экране.

Итак, мы собираемся изменить ваш код:

private void BtnScreen_Click(object sender, EventArgs e)
{
    // if there was a previous image in the picture box, dispose of it now
    PicCode.Image?.Dispose();

    // create a 24 bit image that is the size of your picture box
    var img = new Bitmap(PicCode.Width, PicCode.Height, PixelFormat.Format24bppRgb);
    // wrap it in a graphics object
    using(var g = Graphics.FromImage(img))
    {
        // send that graphics object to the rendering code
        RenderBarcodeInfoToGraphics(g, TxtCode.Text, TxtInfo.Text,
            new Rectangle(0, 0, PicCode.Width, PicCode.Height));
    }

    // set the new image in the picture box
    PicCode.Image = img;
}

private void BtnPrinter_Click(object sender, EventArgs e)
{
    // create a document that will call the same rendering code but
    // this time pass the graphics object the system created for that device
    var doc = new PrintDocument();
    doc.PrintPage += (s, printArgs) =>
    {
        // send that graphics object to the rendering code using the size
        // of the media defined in the print arguments
        RenderBarcodeInfoToGraphics(printArgs.Graphics, TxtCode.Text,
            TxtInfo.Text, printArgs.PageBounds);
    };

    // save yourself some paper and render to a print-preview first
    using (var printPrvDlg = new PrintPreviewDialog { Document = doc })
    {
        printPrvDlg.ShowDialog();
    }

    // finally show the print dialog so the user can select a printer
    // and a paper size (along with other miscellaneous settings)
    using (var pd = new PrintDialog { Document = doc })
    {
        if (pd.ShowDialog() == DialogResult.OK) { doc.Print(); }
    }
}

/// <summary>
/// This method will draw the contents of the barcode parameters to any
/// graphics object you pass in.
/// </summary>
/// <param name="g">The graphics object to render to</param>
/// <param name="code">The barcode value</param>
/// <param name="info">The information to place under the bar code</param>
/// <param name="rect">The rectangle in which the design is bound to</param>
private static void RenderBarcodeInfoToGraphics(
    Graphics g, string code, string info, Rectangle rect)
{
    // Constants to make numbers a little less magical
    const int barcodeHeight = 50;
    const int marginTop = 20;
    const string codeFontFamilyName = "Courier New";
    const int codeFontEmSize = 10;
    const int marginCodeFromCode = 10;
    const string infoFontFamilyName = "Arial";
    const int infoFontEmSize = 12;
    const int marginInfoFromCode = 10;

    // white background
    g.Clear(Color.White);

    // We want to make sure that when it draws, the renderer doesn't compensate
    // for images scaling larger by blurring the image. This will leave your
    // bars crisp and clean no matter how high the DPI is
    g.InterpolationMode = InterpolationMode.NearestNeighbor;

    // generate barcode
    using (var img = BarcodeDrawFactory.Code128WithChecksum.Draw(code, barcodeHeight))
    {
        // daw the barcode image
        g.DrawImage(img,
            new Point(rect.X + (rect.Width / 2 - img.Width / 2), rect.Y + marginTop));
    }

    // now draw the code under the bar code
    using(var br = new SolidBrush(Color.Black))
    {
        // calculate starting position of text from the top
        var yPos = rect.Y + marginTop + barcodeHeight + marginCodeFromCode;

        // align text to top center of area
        var sf = new StringFormat
        {
            Alignment = StringAlignment.Center,
            LineAlignment = StringAlignment.Near
        };

        // draw the code, saving the height of the code text
        var codeTextHeight = 0;
        using (var font =
            new Font(codeFontFamilyName, codeFontEmSize, FontStyle.Regular))
        {
            codeTextHeight = (int)Math.Round(g.MeasureString(code, font).Height);

            g.DrawString(code, font, br,
                new Rectangle(rect.X, yPos, rect.Width, 0), sf);
        }

        // draw the info below the code
        using (var font =
            new Font(infoFontFamilyName, infoFontEmSize, FontStyle.Regular))
        {
            g.DrawString(info, font, br,
                new Rectangle(rect.X,
                    yPos + codeTextHeight + marginInfoFromCode, rect.Width, 0), sf);
        }
    }
}

Итак, как это выглядит в приложении:

приложение

Это приложение также имеет предварительный просмотр перед печатью. Я увеличил предварительный просмотр до печати до 150%, чтобы показать, что все остается четким:

предварительный просмотр

У меня нет принтера. Он вышел из желтого цвета, поэтому он отказывается печатать (почему это?), поэтому вместо этого я напечатал в PDF. Это тот PDF, увеличенный на 300%:

pdf печать

Как видите, штрих-код остается четким и чистым при печати на устройстве с разрешением 600 точек на дюйм, а также при увеличении масштаба этого устройства на 300%.

Имейте в виду, что StackOverflow масштабирует изображения при их отображении, поэтому они могут выглядеть размытыми. Нажмите на изображение, чтобы увидеть его в исходном масштабе.

Если у вас есть какие-либо вопросы, пожалуйста, дайте мне знать.

person Andy    schedule 08.08.2020
comment
Спасибо за подробный ответ Энди. Вы полностью заслужили 50 репутации. Если у меня возникнут какие-либо проблемы, я попытаюсь связаться с вами снова. - person Naser.Sadeghi; 11.08.2020
comment
@Naser.Sadeghi -- Добро пожаловать! Надеюсь, у вас все будет хорошо. Я всегда рядом, если вы столкнетесь с какими-либо неровностями. Удачи! - person Andy; 11.08.2020
comment
К сожалению, у меня все еще есть проблемы с печатью этого штрих-кода. Проблема с качеством была решена, но я по-прежнему не могу распечатать все изображение на бумаге любого заданного размера, когда я пытался вручную установить ширину и высоту, это не сработало, вместо этого я перечисляю все доступные размеры принтера и выбираю один. И результат все равно не правильный. - person Naser.Sadeghi; 15.08.2020
comment
Когда я печатаю в pdf, все в порядке, но в реальном принтере у меня все еще есть проблемы. - person Naser.Sadeghi; 15.08.2020
comment
@ Naser.Sadeghi - вам, вероятно, придется изменить размер штрих-кода. Вместо использования 50 попробуйте использовать 30... также отрегулируйте размер шрифтов Em. - person Andy; 16.08.2020