【发布时间】:2020-09-21 16:15:18
【问题描述】:
也许我做得比现在更难,但我有很多时间将所有内容放在一起布局,甚至出现在我的 pdf 上。
在我的代码中,CreatePdf 被称为创建徽章正面的一次,然后是徽章背面的一次。 pdf的所有对象部分都存储在数据库中,然后在此方法中循环。
原始方法仅使用“图形”对象来创建 pdf,使用 iText CreateDrawingImage 生成的条码效果很好……除了所有条码都非常模糊。为了解决这个问题,使用 CreateImageWithBarcode 将方法更改为同时使用图形对象和 iText 图像。
问题是,无论我对 iText 图像做什么,它都不会在我想要的 pdf 上布局。条形码应该位于徽章的底部,但对于 iText 图像,条形码会自行移动到 pdf 的顶部,在图形项目的顶部。
当我将所有不同的项目类型更改为全部使用 iText 图像时,没有正确布局,甚至没有显示在 pdf 上。
我更喜欢用图表来展示它,但是 iText CreateDrawingImage 的结果是不可用的。在 switch 语句下面,“C128”、“Code39”和“I25”是我遇到问题的项目。如果有人知道我如何解决这些问题来布置一个干净的徽章,那将不胜感激。如果有一种干净的方法可以让 CreateDrawingImage 创建清晰的条形码,那将是首选。
在 VS 2019 C# 中使用 iTextSharp 5.5.13.1 进行开发
private byte[] CreatePDF(BadgeLayoutDTO badgeLayout, Document doc, PdfContentByte cb)
{
if (badgeLayout == null)
return null;
var width = Convert.ToInt32(badgeLayout.Width);
var height = Convert.ToInt32(badgeLayout.Height);
var offset = -50;
// Create the new bitmap
using (Image image = new Bitmap(width, height))
{
var graph = Graphics.FromImage(image);
// Draw a border around the badge if specified
if (badgeLayout.Outline > 0)
{
var pen = new Pen(Brushes.Black, badgeLayout.Outline);
graph.DrawRectangle(pen, 0, 0, width - 1, height - 1);
}
foreach (var field in badgeLayout.BdgFieldList.OrderBy(x => x.FldPosition.FldTop))
{
var x = Convert.ToInt32(field.FldPosition.FldLeft * RatioHorz + badgeLayout.OffsetHorz / 2);
var y = Convert.ToInt32(field.FldPosition.FldTop * RatioVert + badgeLayout.OffsetVert / 2);
var w = Convert.ToInt32((field.FldPosition.FldRight - field.FldPosition.FldLeft) * RatioHorz);
var h = Convert.ToInt32((field.FldPosition.FldBottom - field.FldPosition.FldTop) * RatioVert);
switch (field.FldType)
{
case "ShadedRoundRectangle":
case "RoundRect":
{
const float xradius = 5;
const float yradius = 5;
var brush = new SolidBrush(AccessToHex(field.FldColor.BkColor)); // Fill Color
var pen = new Pen(AccessToHex(field.FldColor.ForeColor),
field.FldPosition.FldSize + 3); // Border color
var rect = new System.Drawing.Rectangle(x, y, w, h);
using (pen)
{
var path = MakeRoundedRect(rect, xradius, yradius, true, true, true, true);
graph.FillPath(brush, path);
graph.DrawPath(pen, path);
}
break;
}
case "ShadeRect":
{
var brush = new HatchBrush(HatchStyle.Cross, AccessToHex(field.FldColor.BkColor - 100),
AccessToHex(field.FldColor.BkColor));
var pen = new Pen(AccessToHex(field.FldColor.ForeColor),
field.FldPosition.FldSize + 3); // Border color
var rect = new System.Drawing.Rectangle(x, y, w, h);
graph.DrawRectangle(pen, rect);
graph.FillRectangle(brush, rect);
break;
}
case "Rectangle":
{
var brush = new SolidBrush(AccessToHex(field.FldColor.BkColor));
var pen = new Pen(AccessToHex(field.FldColor.ForeColor),
field.FldPosition.FldSize + 3); // Border color
var rect = new System.Drawing.Rectangle(x, y, w, h);
graph.DrawRectangle(pen, rect);
graph.FillRectangle(brush, rect);
break;
}
case "Ellipse":
{
var brush = new SolidBrush(AccessToHex(field.FldColor.BkColor));
var pen = new Pen(AccessToHex(field.FldColor.ForeColor),
field.FldPosition.FldSize + 3); // Border color
var rect = new System.Drawing.Rectangle(x, y, w, h);
graph.DrawEllipse(pen, rect);
graph.FillEllipse(brush, rect);
break;
}
case "ShadedEllipse":
{
var brush = new HatchBrush(HatchStyle.Cross, AccessToHex(field.FldColor.BkColor - 100),
AccessToHex(field.FldColor.BkColor));
var pen = new Pen(AccessToHex(field.FldColor.ForeColor),
field.FldPosition.FldSize + 3); // Border color
var rect = new System.Drawing.Rectangle(x, y, w, h);
graph.DrawEllipse(pen, rect);
graph.FillEllipse(brush, rect);
break;
}
case "Image":
{
if (field.FldData?.FldDataValue == null)
continue;
var dbimage = _filePicture.Get(field.FldData.FldDataValue.ToString(), 36);
//var imageJ = iTextSharp.text.Image.GetInstance(dbimage.FileImage);
//imageJ.SetAbsolutePosition(x, y + offset);
//var rect = new Rectangle(0, 0, w, h);
//imageJ.ScaleToFit(rect);
//doc.Add(imageJ);
using (var ms = new MemoryStream(dbimage.FileImage))
{
var newImage = Image.FromStream(ms);
// Resize image to proper aspect ratio
var aspect = ResizeKeepAspect(newImage.Size, w, h);
var aspectImage = ResizeImage(newImage, new Size(aspect.Width, aspect.Height));
// Create Point for upper-left corner of image.
var ulCorner = new Point(x, y);
// Draw image to screen.
graph.DrawImage(aspectImage, ulCorner);
}
break;
}
case "QRCode":
{
if (field.FldData?.FldDataValue == null)
continue;
QRCodeGenerator qrGenerator = new QRCodeGenerator();
QRCodeData qrCodeData = qrGenerator.CreateQrCode(field.FldData?.FldDataValue.ToString(), QRCodeGenerator.ECCLevel.Q);
QRCode qrCode = new QRCode(qrCodeData);
Bitmap dbImage = qrCode.GetGraphic(20);
var aspect = ResizeKeepAspect(dbImage.Size, w, h);
var aspectImage = ResizeBadgeImage(dbImage, new Size(aspect.Width, aspect.Height));
using (var ms2 = new MemoryStream())
{
try
{
aspectImage.Save(ms2, System.Drawing.Imaging.ImageFormat.Jpeg);
var signatureImage = iTextSharp.text.Image.GetInstance(ms2.ToArray());
signatureImage.SetAbsolutePosition(x, y + offset - 100);
doc.Add(signatureImage);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
break;
}
case "C128":
{
if (field.FldData?.FldDataValue == null)
continue;
var dbImage = (new Barcode128()
{
Code = field.FldData?.FldDataValue.ToString()
});
iTextSharp.text.Image image128 = dbImage.CreateImageWithBarcode(cb, null, BaseColor.WHITE);
image128.SetAbsolutePosition(x, y + offset);
var rect = new Rectangle(0, 0, w, h);
image128.ScaleToFit(rect);
doc.Add(image128);
break;
}
case "Code39":
{
if (field.FldData?.FldDataValue == null)
continue;
var dbImage = (new Barcode39
{
Code = field.FldData?.FldDataValue.ToString()
});
iTextSharp.text.Image image128 = dbImage.CreateImageWithBarcode(cb, null, BaseColor.WHITE);
image128.SetAbsolutePosition(x, y + offset);
var rect = new Rectangle(0, 0, w, h);
image128.ScaleToFit(rect);
doc.Add(image128);
break;
}
case "I25":
{
if (field.FldData?.FldDataValue == null)
continue;
var dbImage = (new BarcodeInter25()
{
Code = field.FldData?.FldDataValue.ToString()
});
iTextSharp.text.Image image128 = dbImage.CreateImageWithBarcode(cb, null, BaseColor.WHITE);
image128.SetAbsolutePosition(x, y + offset);
var rect = new Rectangle(0, 0, w, h);
image128.ScaleToFit(rect);
doc.Add(image128);
break;
}
case "Picture":
{
if (field.FldData?.FldDataValue == null)
continue;
var dbimage = _filePicture.Get(field.FldData.FldDataValue.ToString(), 48);
//var imageJ = iTextSharp.text.Image.GetInstance(dbimage.FileImage);
//imageJ.SetAbsolutePosition(x, y + offset);
//var rect = new Rectangle(0, 0, w, h);
//imageJ.ScaleToFit(rect);
//doc.Add(imageJ);
using (var ms = new MemoryStream(dbimage.FileImage))
{
var newImage = Image.FromStream(ms);
// Resize image to proper aspect ratio
var aspect = ResizeKeepAspect(newImage.Size, w, h);
var aspectImage = ResizeImage(newImage, new Size(aspect.Width, aspect.Height));
//var rect = new Rectangle(0, 0, w, h);
// Create Point for upper-left corner of image.
var ulCorner = new Point(x, y);
// Draw image to screen.
graph.DrawImage(aspectImage, ulCorner);
}
break;
}
case "Signature":
{
if (field.FldData?.FldDataValue == null)
continue;
var dbimage = _filePicture.Get(field.FldData.FldDataValue.ToString(), 36);
if (dbimage == null) continue;
//iTextSharp.text.Image imageJ = new Jpeg(dbimage.FileImage);
//imageJ.SetAbsolutePosition(x, y + offset);
//var rect = new Rectangle(0, 0, w, h);
//imageJ.ScaleToFit(rect);
//doc.Add(imageJ);
using (var ms = new MemoryStream(dbimage.FileImage))
{
var newImage = Image.FromStream(ms);
// Resize image to proper aspect ratio
var aspect = ResizeKeepAspect(newImage.Size, w, h);
var aspectImage = ResizeImage(newImage, new Size(aspect.Width, aspect.Height));
// Create Point for upper-left corner of image.
var ulCorner = new Point(x, y);
// Draw image to screen.
graph.DrawImage(aspectImage, ulCorner);
}
break;
}
case "TextCenter":
case "TextLeft":
case "TextRight":
{
var text = GetText(field);
// Assume here that screen DPI is 96...
// If DPI is different, rendering issues might occur...
// Badge designer in Desktop assumes 300 DPI
var fontSizeDpiRatioFix = 300 / 96; //HACK
var fontSize = -field.FldPosition.FldSize * fontSizeDpiRatioFix * 1.03;
Font font;
try
{
font = FindFont(graph, text, new Size(w, h),
new Font(new FontFamily(field.FldFont.FontName), (float)fontSize,
GetFontParam(field.FldFont.FontParms)));
}
catch (Exception exc)
{
font = System.Drawing.SystemFonts.DefaultFont;
}
//Create rectangles
var rect1 = new System.Drawing.Rectangle(x, y, w, h);
//Construct string format and alignment
var strFormat1 = new StringFormat
{
Alignment = StringAlignment.Center,
LineAlignment = StringAlignment.Center,
Trimming = StringTrimming.EllipsisCharacter
};
// Draw GDI+ objects
graph.DrawRectangle(new Pen(Color.Transparent), rect1);
graph.DrawString(text, font,
new SolidBrush(AccessToHex(field.FldColor.ForeColor)), rect1, strFormat1);
//Disposes of objects
font.Dispose();
break;
}
}
}
using (var ms = new MemoryStream())
{
image.Save(ms, ImageFormat.Png);
return ms.ToArray();
}
}
【问题讨论】:
-
为什么不在帖子中添加一些换行符以使其可读?
-
您是否考虑过位图图像和pdf页面中的坐标系可能会有很大差异?位图图像 API 通常将原点 (0,0) 定位在 top 左侧,并且 y 坐标向下 增加。另一方面,PDF 可以在任何地方(通常在左下角)具有原点,并且y 坐标向上 增加。位图图像 API 通常通过对象的 top 左角来定位对象,pdf 则通过它们的 bottom 左角来定位。此外,您必须考虑稍后将位图添加到 pdf 时使用的转换。
-
因此,在从添加到位图切换到添加到 PDF 时,您必须大幅转换坐标。