gpt4 book ai didi

delphi - 如何在TPrinter上以实际尺寸打印图像?

转载 作者:行者123 更新时间:2023-12-03 15:54:47 27 4
gpt4 key购买 nike

向大家问好!

如何在TPrinter上以真实尺寸打印Delphi中的图片?从 TImage Canvas 上我得到了很好的结果,但是如果我在 TPrinter Canvas 上绘画,我得到了糟糕的结果,图片比位图的实际尺寸太小。

为什么会发生这种情况我需要做什么来修复错误?

更新

是的,我从第一篇文章的提示中看到了问题。我无法在我的项目中使用 JCL/JVCL 代码,但我从中得到了想法。

我创建临时TImage,并根据打印机的DPI系数计算它的尺寸:

var
i, iRow, iCol, // Counter
iBorderSize, // Ident from left/top borders
iImgDistance, // Ident between images in grid
iRows, // Rows Count
iColumns, // Colun count
iLeft, iTop: Integer; // For calc
bmp: TBitmap;
bStop, bRowDone, bColDone: Boolean;
Img1: TImage;
scale: Double;

function CalcY: Integer;
begin
if (iRow = 1) then
Result := iBorderSize
else
Result := iBorderSize + (iImgDistance * (iRow - 1)) +
(bmp.Height * (iRow - 1));
end;

function CalcX: Integer;
begin
if (iCol = 1) then
Result := iBorderSize
else
Result := iBorderSize + (iImgDistance * (iCol - 1)) +
(bmp.Width * (iCol - 1));
end;

begin
iBorderSize := StrToInt(BorderSizeEdit.Text);
iImgDistance := StrToInt(ImgsDistanceEdit.Text);
iRows := StrToInt(RowsCountEdit.Text);
iColumns := StrToInt(ColCountEdit.Text);
iRow := 1;
iCol := 1;
iLeft := iBorderSize;
iTop := iBorderSize;

if Printer.Orientation = poPortrait then
scale := GetDeviceCaps(Printer.Handle, LOGPIXELSX) /
Screen.PixelsPerInch
else
scale := GetDeviceCaps(Printer.Handle, LOGPIXELSY) /
Screen.PixelsPerInch;

bmp := TBitmap.Create;
Img1 := TImage.Create(nil);
Img1.Height := Trunc(Printer.PageHeight / scale); //Calc canvas size
Img1.Width := Trunc(Printer.PageWidth / scale); //Calc canvas size
Img1.Canvas.Brush.Color := clWhite;
Img1.Canvas.FillRect(Rect(0, 0, Img1.Width, Img1.Height));
try
bmp.LoadFromFile(ExtractFilePath(ParamStr(0)) + 'Source.bmp');
for i := 1 to 18 do
begin
if (iRow <= iRows) then
begin
iTop := CalcY;
iLeft := CalcX;
Img1.Canvas.Draw(iLeft, iTop, bmp);
if not((iRow = iRows) and (iCol = iColumns)) then
begin
if (iCol = iColumns) then
begin
Inc(iRow);
iCol := 1;
end
else
Inc(iCol);
end
else
begin
PrintImage(Img1, 100);
iRow := 1;
iCol := 1;
Img1.Canvas.Brush.Color := clWhite;
Img1.Canvas.FillRect(Rect(0, 0, Img1.Width, Img1.Height));
end;
end;
end;
finally
FreeAndNil(bmp);
FreeAndNil(Img1);
end;
end;

并在 TPrinter.Canvas 上绘制它。

您可以看到下面的结果:

You can see results below:

结果不错,但并不完美。

正如你所看到的,在最后一列中,所有图像都没有绘制到最后,有些部分从纸上漏掉了,没有绘制出来。

我认为这是因为我在根据打印机的 DPI 系数计算 TImage.Canvas 的尺寸时使用 Trunc 来获取 double 的整数部分。

通过实验我知道值为 0.20。 0.20 是最后一列图像的一部分(以像素为单位),未绘制。如果我更改代码,则会通过以下方式获得比例因子:

  if Printer.Orientation = poPortrait then
scale := GetDeviceCaps(Printer.Handle, LOGPIXELSX) /
Screen.PixelsPerInch - 0.20
else
scale := GetDeviceCaps(Printer.Handle, LOGPIXELSY) /
Screen.PixelsPerInch - 0.20;

我有,我需要的是:

I have that, what I need:

我认为值 0.20 不是一个常数,它会在每台 PC 上发生变化。如何计算这个值?需要什么来解决这个问题?

最佳答案

这里的基本问题是缩放问题。或多或少,计算出图像分辨率要扩展多少,然后将其拉伸(stretch)到打印机 Canvas 上。像这样的东西可以将图像拉伸(stretch)到打印机 Canvas 的尺寸。

procedure TForm1.Button2Click(Sender: TObject);
var
MyRect: TRect;
scale: Double;
begin
if PrintDialog1.Execute then
begin
Printer.BeginDoc;
scale := Printer.PageWidth / Bitmap1.Width;
ShowMessage(FloatToStr(scale));
{ horizontal pixels, vertical pixels, bit depth 600 x 600 x 24}
MyRect.Left := 0;
MyRect.Top := 0;
MyRect.Right := trunc(Bitmap1.Width * scale);
MyRect.Bottom := trunc(Bitmap1.Height * scale);
Printer.Canvas.StretchDraw(MyRect, Bitmap1);
Printer.EndDoc;
end;

当然,您必须检查“Right”和“Bottom”,以确保它们不会超过您的 PageWidth 和 PageHeight,具体取决于您使用的缩放类型(6.25 或 600/96 似乎适合简单地制作图像与屏幕的相对大小相同,假设这些数字与您的打印机和屏幕相匹配),假设您希望将图像保留在一页上,而不是将其马赛克碎片到多页上。

我不知道这是否完全有效,因为我没有不同数量的设备(即不同的 DPI)来测试两个方向,但这似乎是您想要动态获取两个 DPI 数字的方法。

if Printer.Orientation = poPortrait then
scale := GetDeviceCaps(Printer.Handle, LOGPIXELSX) / PixelsPerInch
else
scale := GetDeviceCaps(Printer.Handle, LOGPIXELSY) / pixelsperinch;

然后,当然,你可以像上面那样相乘。

关于delphi - 如何在TPrinter上以实际尺寸打印图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18002679/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com