我需要在4"x 6"纸(也称为4r)上打印1800 x 1200像素,300 dpi图像
我试过了什么
我创建了一个PrintRequestAttributeSet这需要照顾我的PrintableArea(4×6) ,.Printer print DPI Orientation我在底部贴了一个MCVE.
问题
虽然代码有效,但我得到了PageFormat以下属性(对于我的打印机):
x= 12.0
y= 12.32
w= 276.0
h= 419.67
Run Code Online (Sandbox Code Playgroud)
宽度和高度都少,因为我的打印机不支持Zero Margin.(这是我考虑过的.如果有人知道除此之外我可以强迫零利润的方式,请告诉我)
我正在提供margin as 0,因为这些图像将通过支持零保证金的打印机打印(Photobooth打印机).
aset.add(new MediaPrintableArea(0, 0, 4, 6, MediaPrintableArea.INCH));
Run Code Online (Sandbox Code Playgroud)
包括边距的可打印区域大约为4 x 6.当我缩放图像以在可打印区域内打印时,会出现问题.
由于图像为1800 x 1200,因此它支持3:2的宽高比,这意味着创建的图像可以在4 x 6纸张上打印(旋转和缩放后).以供参考.
现在,由于PageFormatImageWidth和ImageHeight 的pageWidth和pageHeight 不能完全整除.我正在解决扩展问题.
注意:我旋转图像是因为它必须以4 x 6而不是6 x 4打印.
应该占据4 x 6空间的图像占用接近4 x 5的图像.图像尺寸也大大减小.
我该如何克服这个问题?
码
请在这里找到MCVE:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.MediaPrintableArea;
import javax.print.attribute.standard.OrientationRequested;
import javax.print.attribute.standard.PrintQuality;
import javax.print.attribute.standard.PrinterResolution;
public class ImgPrinter implements Printable {
Image img;
@Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)
throws PrinterException {
Graphics2D g2d = (Graphics2D) graphics;
g2d.translate((int) (pageFormat.getImageableX()),
(int) (pageFormat.getImageableY()));
if (pageIndex == 0) {
double pageWidth = pageFormat.getImageableWidth();
double pageHeight = pageFormat.getImageableHeight();
/**
* Swapping width and height, coz the image is later rotated
*/
double imageWidth = img.getHeight(null);
double imageHeight = img.getWidth(null);
double scaleX = pageWidth / imageWidth;
double scaleY = pageHeight / imageHeight;
g2d.scale(scaleX, scaleY);
g2d.rotate(Math.toRadians(90), img.getWidth(null) / 2,
img.getHeight(null) / 2);
g2d.drawImage(img, 0, 0, null);
return Printable.PAGE_EXISTS;
}
return Printable.NO_SUCH_PAGE;
}
public void printPage(String file, String size) {
try {
Image img = ImageIO.read(new File(file));
this.img = img;
PrintRequestAttributeSet aset = createAsetForMedia(size);
PrinterJob pj = PrinterJob.getPrinterJob();
PageFormat pageFormat = pj.getPageFormat(aset);
pj.setPrintable(this, pageFormat);
pj.print();
} catch (PrinterException ex) {
ex.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private PrintRequestAttributeSet createAsetForMedia(String size) {
PrintRequestAttributeSet aset = null;
try {
aset = new HashPrintRequestAttributeSet();
aset.add(PrintQuality.NORMAL);
aset.add(OrientationRequested.PORTRAIT);
/**
* Suggesting the print DPI as 300
*/
aset.add(new PrinterResolution(300, 300, PrinterResolution.DPI));
/**
* Setting the printable area and the margin as 0
*/
if (size.equals("3r")) {
aset.add(new MediaPrintableArea(0, 0, 3, 5,
MediaPrintableArea.INCH));
} else if (size.equals("4r")) {
aset.add(new MediaPrintableArea(0, 0, 4, 6,
MediaPrintableArea.INCH));
} else if (size.equals("5r")) {
aset.add(new MediaPrintableArea(0, 0, 5, 7,
MediaPrintableArea.INCH));
} else if (size.equals("6r")) {
aset.add(new MediaPrintableArea(0, 0, 6, 8,
MediaPrintableArea.INCH));
}
} catch (Exception e) {
e.printStackTrace();
}
return aset;
}
public static void main(String[] args) {
new ImgPrinter().printPage("/Some_URL/sam.jpg",
"4r");
}
}
Run Code Online (Sandbox Code Playgroud)
要运行该程序,只需为主程序提供1800x1200图像路径,它将打印到默认打印机.
让我担心的事情...
Graphics而无需先复制它或在事后重置它。这实际上可能会影响后续的渲染,因为printable可能会被多次调用......Graphics2D#scale。这确实不是最好的质量,通常也不是那么快。请参阅Image.getScaledInstance() 的危险。我也更喜欢使用AffineTransform,但这只是我......print方法可能会被多次调用来打印单个页面,每次缩放图像的成本很高,相反,您应该缩放一次并重新使用缩放后的结果。0x0。Graphics,原点会发生变化,因此在这种情况下,它将变为顶/右上角,而不是位于顶/左上角。现在你知道为什么我会单独旋转图像而不是尝试弄乱上下文Graphics:P我“认为”正在发生的是,在坐标的缩放、旋转和操作(交换高度和宽度)之间,事情变得很糟糕……但坦率地说,当我有更好的解决方案...
下面的示例使用了一堆个人库代码,因此其中一些代码可能有点复杂,但我将单独的功能用于其他事情,因此它可以很好地结合在一起......
因此,从 7680x4800 的图像开始,这会生成 423x264 的缩放图像

(红色边框仅供视觉参考,在将结果转储为 PDF 以节省纸张时使用;))
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.MediaPrintableArea;
import javax.print.attribute.standard.OrientationRequested;
import javax.print.attribute.standard.PrintQuality;
import javax.print.attribute.standard.PrinterResolution;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ImgPrinter implements Printable {
BufferedImage img;
BufferedImage scaled;
@Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)
throws PrinterException {
int result = NO_SUCH_PAGE;
Graphics2D g2d = (Graphics2D) graphics.create();
g2d.translate((int) (pageFormat.getImageableX()), (int) (pageFormat.getImageableY()));
if (pageIndex == 0) {
double pageWidth = pageFormat.getImageableWidth();
double pageHeight = pageFormat.getImageableHeight();
if (scaled == null) {
// Swap the width and height to allow for the rotation...
System.out.println(pageWidth + "x" + pageHeight);
scaled = getScaledInstanceToFit(
img,
new Dimension((int)pageHeight, (int)pageWidth));
System.out.println("In " + img.getWidth() + "x" + img.getHeight());
System.out.println("Out " + scaled.getWidth() + "x" + scaled.getHeight());
}
double imageWidth = scaled.getWidth();
double imageHeight = scaled.getHeight();
AffineTransform at = AffineTransform.getRotateInstance(
Math.toRadians(90),
pageWidth / 2d,
pageHeight / 2d
);
AffineTransform old = g2d.getTransform();
g2d.setTransform(at);
double x = (pageHeight - imageWidth) / 2d;
double y = (pageWidth - imageHeight) / 2d;
g2d.drawImage(
scaled,
(int)x,
(int)y,
null);
g2d.setTransform(old);
// This is not affected by the previous changes, as those were made
// to a different copy...
g2d.setColor(Color.RED);
g2d.drawRect(0, 0, (int)pageWidth - 1, (int)pageHeight - 1);
result = PAGE_EXISTS;
}
g2d.dispose();
return result;
}
public void printPage(String file, String size) {
try {
img = ImageIO.read(new File(file));
PrintRequestAttributeSet aset = createAsetForMedia(size);
PrinterJob pj = PrinterJob.getPrinterJob();
PageFormat pageFormat = pj.getPageFormat(aset);
pj.setPrintable(this, pageFormat);
if (pj.printDialog()) {
pj.print();
}
} catch (PrinterException ex) {
ex.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private PrintRequestAttributeSet createAsetForMedia(String size) {
PrintRequestAttributeSet aset = null;
try {
aset = new HashPrintRequestAttributeSet();
aset.add(PrintQuality.NORMAL);
aset.add(OrientationRequested.PORTRAIT);
/**
* Suggesting the print DPI as 300
*/
aset.add(new PrinterResolution(300, 300, PrinterResolution.DPI));
/**
* Setting the printable area and the margin as 0
*/
if (size.equals("3r")) {
aset.add(new MediaPrintableArea(1, 1, 3, 5,
MediaPrintableArea.INCH));
} else if (size.equals("4r")) {
aset.add(new MediaPrintableArea(1, 1, 4, 6,
MediaPrintableArea.INCH));
} else if (size.equals("5r")) {
aset.add(new MediaPrintableArea(1, 1, 5, 7,
MediaPrintableArea.INCH));
} else if (size.equals("6r")) {
aset.add(new MediaPrintableArea(1, 1, 6, 8,
MediaPrintableArea.INCH));
}
} catch (Exception e) {
e.printStackTrace();
}
return aset;
}
public static BufferedImage getScaledInstanceToFit(BufferedImage img, Dimension size) {
double scaleFactor = getScaleFactorToFit(img, size);
return getScaledInstance(img, scaleFactor);
}
public static BufferedImage getScaledInstance(BufferedImage img, double dScaleFactor) {
return getScaledInstance(img, dScaleFactor, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
}
public static double getScaleFactorToFit(BufferedImage img, Dimension size) {
double dScale = 1;
if (img != null) {
int imageWidth = img.getWidth();
int imageHeight = img.getHeight();
dScale = getScaleFactorToFit(new Dimension(imageWidth, imageHeight), size);
}
return dScale;
}
public static double getScaleFactorToFit(Dimension original, Dimension toFit) {
double dScale = 1d;
if (original != null && toFit != null) {
double dScaleWidth = getScaleFactor(original.width, toFit.width);
double dScaleHeight = getScaleFactor(original.height, toFit.height);
dScale = Math.min(dScaleHeight, dScaleWidth);
}
return dScale;
}
public static double getScaleFactor(int iMasterSize, int iTargetSize) {
return (double) iTargetSize / (double) iMasterSize;
}
protected static BufferedImage getScaledInstance(BufferedImage img, double dScaleFactor, Object hint) {
BufferedImage imgScale = img;
int iImageWidth = (int) Math.round(img.getWidth() * dScaleFactor);
int iImageHeight = (int) Math.round(img.getHeight() * dScaleFactor);
if (dScaleFactor <= 1.0d) {
imgScale = getScaledDownInstance(img, iImageWidth, iImageHeight, hint);
} else {
imgScale = getScaledUpInstance(img, iImageWidth, iImageHeight, hint);
}
return imgScale;
}
protected static BufferedImage getScaledDownInstance(BufferedImage img,
int targetWidth,
int targetHeight,
Object hint) {
// System.out.println("Scale down...");
int type = (img.getTransparency() == Transparency.OPAQUE)
? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
BufferedImage ret = (BufferedImage) img;
if (targetHeight > 0 || targetWidth > 0) {
int w = img.getWidth();
int h = img.getHeight();
do {
if (w > targetWidth) {
w /= 2;
if (w < targetWidth) {
w = targetWidth;
}
}
if (h > targetHeight) {
h /= 2;
if (h < targetHeight) {
h = targetHeight;
}
}
BufferedImage tmp = new BufferedImage(Math.max(w, 1), Math.max(h, 1), type);
Graphics2D g2 = tmp.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
g2.drawImage(ret, 0, 0, w, h, null);
g2.dispose();
ret = tmp;
} while (w != targetWidth || h != targetHeight);
} else {
ret = new BufferedImage(1, 1, type);
}
return ret;
}
protected static BufferedImage getScaledUpInstance(BufferedImage img,
int targetWidth,
int targetHeight,
Object hint) {
int type = BufferedImage.TYPE_INT_ARGB;
BufferedImage ret = (BufferedImage) img;
int w = img.getWidth();
int h = img.getHeight();
do {
if (w < targetWidth) {
w *= 2;
if (w > targetWidth) {
w = targetWidth;
}
}
if (h < targetHeight) {
h *= 2;
if (h > targetHeight) {
h = targetHeight;
}
}
BufferedImage tmp = new BufferedImage(w, h, type);
Graphics2D g2 = tmp.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
g2.drawImage(ret, 0, 0, w, h, null);
g2.dispose();
ret = tmp;
tmp = null;
} while (w != targetWidth || h != targetHeight);
return ret;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
new ImgPrinter().printPage("/Volumes/Disk02/Dropbox/Wallpapers/animepaper.net_wallpaper_art_anime_aria_duanwu_festival_205050_wonderngo_7680x4800-a8aecc9c.jpg",
"4r");
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
你知道什么会更容易,以横向模式打印页面并以 :P 开头
| 归档时间: |
|
| 查看次数: |
1407 次 |
| 最近记录: |