【发布时间】:2019-12-30 07:02:53
【问题描述】:
我正在处理在图像上绘制字符串的任务。
但结果图像与我写下的源代码不同。
下图显示字体大小差异。
红色文字以NanumSquare字体18px在窗口油漆中书写。
红色文字下方的黑色文字date也是NanumSquare字体18px。它是用 C# 源代码编写的。
以下是我的源代码。 C#。
static void Main(string[] args)
{
DrawTextToImageSave("webPrint_back.png");
}
public static void DrawTextToImageSave(string path)
{
//png to bitmap
Image Dummy = Image.FromFile(path);
using (Bitmap bitmap = (Bitmap)Dummy)
{//load the image file
using (Graphics graphics = Graphics.FromImage(bitmap))
{
graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
var titleFont = new Font("NanumSquareOTF ExtraBold", 25);
var bodyFont = new Font("NanumSquareOTF Regular", 25);
graphics.DrawString("DATE", titleFont, System.Drawing.Brushes.Black, new PointF(401.5f, 863.5f)); //comment 1
graphics.DrawString(DateTime.Now.ToString("yyyy.MM.dd"), bodyFont, System.Drawing.Brushes.Black, new PointF(345, 885f));
graphics.DrawString("LOCATION", titleFont, System.Drawing.Brushes.Black, new PointF(344, 919.5f));
graphics.DrawString(System.DateTime.Now.ToString("yyyyMMddHHmmss") , bodyFont, System.Drawing.Brushes.Black, new PointF(267f, 946f));
WriteableBitmap bitmapimg = Generator128Code("STACKOVERFLOW", 110, 110);
bitmapimg = resize_image(bitmapimg, 1.4); //comment 2
var stream = new MemoryStream();
var encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmapimg));
encoder.Save(stream);
byte[] buffer = stream.GetBuffer();
var qrBitmap = new System.Drawing.Bitmap(new MemoryStream(buffer));
graphics.DrawImage(qrBitmap, 485f, 855f);
}
bitmap.Save( "output_WebPrintBack.png", ImageFormat.Png);
}
}
参见评论 1。我预计它会准确地绘制 18px 字体。但事实并非如此。
我在用 zxing 绘制 qrcode 时也遇到了同样的问题。
如果没有 comment2 代码,我会得到 ~90 px 二维码大小。
public static WriteableBitmap Generator128Code(string contents, int width, int height)
{
if (string.IsNullOrEmpty(contents))
{
return null;
}
EncodingOptions options = null;
BarcodeWriter writer = null;
options = new QrCodeEncodingOptions
{
CharacterSet = "UTF-8",
Width = width,
Height = height,
ErrorCorrection = ErrorCorrectionLevel.H,
Margin = 0
};
writer = new BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
Options = options
};
WriteableBitmap bitmap = writer.Write(contents);
return bitmap;
}
static WriteableBitmap resize_image(WriteableBitmap img, double scale)
{
BitmapSource source = img;
var s = new ScaleTransform(scale, scale);
var res = new TransformedBitmap(img, s);
return convert_BitmapSource_to_WriteableBitmap(res);
}
static WriteableBitmap convert_BitmapSource_to_WriteableBitmap(BitmapSource source)
{
// Calculate stride of source
int stride = source.PixelWidth * (source.Format.BitsPerPixel / 8);
// Create data array to hold source pixel data
byte[] data = new byte[stride * source.PixelHeight];
// Copy source image pixels to the data array
source.CopyPixels(data, stride, 0);
// Create WriteableBitmap to copy the pixel data to.
WriteableBitmap target = new WriteableBitmap(source.PixelWidth
, source.PixelHeight, source.DpiX, source.DpiY
, source.Format, null);
// Write the pixel data to the WriteableBitmap.
target.WritePixels(new Int32Rect(0, 0
, source.PixelWidth, source.PixelHeight)
, data, stride, 0);
return target;
}
将 x 1.4 乘以它的大小,我可以得到我想要的类似结果。
为什么会出现这种差异?
原始图像的大小也是 638px * 1010px。下图是原图。
感谢您的阅读。我为我糟糕的英语水平道歉。
编辑
以下源代码可通过 Console .net 框架执行。
我用这个源代码重试,但结果是一样的。 :( ...
以下源代码是完整的源代码。
您需要名为“webPrint_back.png”的 png 文件。和大小 638x1010 。 https://dummyimage.com/
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using ZXing;
using ZXing.Common;
using ZXing.QrCode;
using ZXing.QrCode.Internal;
using BarcodeWriter = ZXing.Presentation.BarcodeWriter;
namespace bitmapTest
{
class Program
{
static void Main(string[] args)
{
DrawTextToImageSave("webPrint_back.png");
}
public static void DrawTextToImageSave(string path)
{
//png to bitmap
Image Dummy = Image.FromFile(path);
using (Bitmap bitmap = (Bitmap)Dummy)
{//load the image file
using (Graphics graphics = Graphics.FromImage(bitmap))
{
graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
var titleFont = new Font("NanumSquareOTF ExtraBold", 18);
var bodyFont = new Font("NanumSquareOTF Regular", 18);
graphics.DrawString("DATE", titleFont, System.Drawing.Brushes.Black, new PointF(401.5f, 863.5f)); //comment 1
graphics.DrawString(DateTime.Now.ToString("yyyy.MM.dd"), bodyFont, System.Drawing.Brushes.Black, new PointF(345, 885f));
graphics.DrawString("LOCATION", titleFont, System.Drawing.Brushes.Black, new PointF(344, 919.5f));
graphics.DrawString(System.DateTime.Now.ToString("yyyyMMddHHmmss") , bodyFont, System.Drawing.Brushes.Black, new PointF(267f, 946f));
WriteableBitmap bitmapimg = Generator128Code("STACKOVERFLOW", 110, 110);
bitmapimg = resize_image(bitmapimg, 1.4); //comment 2
var stream = new MemoryStream();
var encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmapimg));
encoder.Save(stream);
byte[] buffer = stream.GetBuffer();
var qrBitmap = new System.Drawing.Bitmap(new MemoryStream(buffer));
graphics.DrawImage(qrBitmap, 485f, 855f);
}
bitmap.Save( "output_WebPrintBack.png", ImageFormat.Png);
}
}
public static WriteableBitmap Generator128Code(string contents, int width, int height)
{
if (string.IsNullOrEmpty(contents))
{
return null;
}
EncodingOptions options = null;
BarcodeWriter writer = null;
options = new QrCodeEncodingOptions
{
CharacterSet = "UTF-8",
Width = width,
Height = height,
ErrorCorrection = ErrorCorrectionLevel.H,
Margin = 0
};
writer = new BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
Options = options
};
WriteableBitmap bitmap = writer.Write(contents);
return bitmap;
}
static WriteableBitmap resize_image(WriteableBitmap img, double scale)
{
BitmapSource source = img;
var s = new ScaleTransform(scale, scale);
var res = new TransformedBitmap(img, s);
return convert_BitmapSource_to_WriteableBitmap(res);
}
static WriteableBitmap convert_BitmapSource_to_WriteableBitmap(BitmapSource source)
{
// Calculate stride of source
int stride = source.PixelWidth * (source.Format.BitsPerPixel / 8);
// Create data array to hold source pixel data
byte[] data = new byte[stride * source.PixelHeight];
// Copy source image pixels to the data array
source.CopyPixels(data, stride, 0);
// Create WriteableBitmap to copy the pixel data to.
WriteableBitmap target = new WriteableBitmap(source.PixelWidth
, source.PixelHeight, source.DpiX, source.DpiY
, source.Format, null);
// Write the pixel data to the WriteableBitmap.
target.WritePixels(new Int32Rect(0, 0
, source.PixelWidth, source.PixelHeight)
, data, stride, 0);
return target;
}
}
}
【问题讨论】:
-
如果你能分享minimal reproducible example,那就太棒了。我无法按原样重现该问题,因为当我将您提供的代码复制并粘贴到控制台应用程序中时,它无法编译(例如,
resize_image缺失)。 -
@mjwills 谢谢,我编辑了我的帖子。我检查了一下,效果很好。但需要 png 文件“webPrint_back.png”
标签: c# wpf bitmap system.drawing