使用Java在4 x 6纸张上打印1800 x 1200图像
我需要在4英寸x 6英寸的纸张(也称为4r)上打印1800 x 1200像素、300 dpi的图像 我尝试过的 我已经创建了一个使用Java在4 x 6纸张上打印1800 x 1200图像,java,printing,awt,Java,Printing,Awt,我需要在4英寸x 6英寸的纸张(也称为4r)上打印1800 x 1200像素、300 dpi的图像 我尝试过的 我已经创建了一个PrintRequestAttributeSet,它负责我的PrintableArea(4 x 6),打印机打印DPI,方向。我在底部附上了一个MCVE 问题 代码运行时,我会得到一个带有以下属性的PageFormat(适用于我的打印机): 宽度和高度稍小,因为我的打印机不支持零边距。(这就是我所考虑的。如果有人知道除此之外我可以强制零保证金的其他方法,请告诉我) 我提
PrintRequestAttributeSet
,它负责我的PrintableArea
(4 x 6),打印机打印DPI
,方向
。我在底部附上了一个MCVE
问题
代码运行时,我会得到一个带有以下属性的PageFormat
(适用于我的打印机):
宽度和高度稍小,因为我的打印机不支持零边距
。(这就是我所考虑的。如果有人知道除此之外我可以强制零保证金的其他方法,请告诉我)
我提供的页边距为0
,因为这些图像将通过支持零页边距的打印机(Photobooth打印机)打印
包括页边距在内的可打印面积约为4 x 6(根据需要)。当我缩放图像以在可打印区域内打印时,会出现问题
由于图像是1800 x 1200,它支持3:2的纵横比,这意味着创建图像是为了在4 x 6纸张上打印(旋转和缩放后)
现在,由于PageFormat
的pageWidth和pageHeight不能完全被ImageWidth和ImageHeight整除。我遇到了缩放问题
注意:我旋转图像,因为它必须在4 x 6而不是6 x 4上打印
这张本应占4x6空间的图像,拍摄的位置接近4x5。图像大小也大大减小
我如何克服这个问题
代码
请在此处找到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");
}
}
要运行该程序,只需向主程序提供一个1800x1200图像路径,它将打印到默认打印机。我认为您需要按比例缩放。像这样
double scaleX = pageWidth / imageWidth;
double scaleY = pageHeight / imageHeight;
double scale = Math.min(scaleX, scaleY);
g2d.scale(scale, scale);
更新:
mKorbel提到的另一个建议是单独缩放
尝试使用public Image getScaledInstance(int-width、int-height、int-hints)
BufferedImage的方法
传递
图像。平滑缩放作为提示。让我担心的事情
更改图形
上下文的缩放/旋转,无需先复制或事后重置。这实际上可能会影响后续渲染,因为可打印的可能会被多次调用
使用图形2D#缩放
。这真的不是最好的质量,一般来说也不是那么快。看见我也喜欢使用仿射翻译,但那只是我
不缓冲结果。好的,这与前面的注释有关,但是您的print
方法可能会被多次调用以打印一个页面,每次缩放图像都会带来成本,相反,您应该缩放一次并重新使用缩放结果
除非要实际旋转图像,否则可能要围绕页面中心旋转,而不是图像本身,这将影响0x0
的位置
现在请记住,当您旋转图形
上下文时,原点会发生变化,因此在本例中,原点将变为上/右角,而不是位于上/左角。现在你知道为什么我会孤立地旋转图像,而不是尝试与图形混为一谈了
我“认为”正在发生的是,在坐标的缩放、旋转和操作(交换高度和宽度)之间,事情变得一团糟……但坦率地说,当我有更好的解决方案时,我不会再胡闹了
下面的示例使用了一组个人库代码,因此其中一些代码可能有点复杂,但我对其他内容使用了单独的功能,因此它可以很好地结合在一起
因此,从7680x4800的图像开始,这将生成423x264的缩放图像
(红色边框仅为视觉指南,用于将结果转储到PDF以节省纸张;)
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.EventQueue;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.RenderingHints;
导入java.awt.Transparency;
导入java.awt.geom.AffineTransform;
导入java.awt.image.buffereImage;
导入java.awt.print.PageFormat;
导入java.awt.print.Printable;
导入java.awt.print.PrinterException;
导入java.awt.print.PrinterJob;
导入java.io.File;
导入java.io.IOException;
导入javax.imageio.imageio;
导入javax.print.attribute.HashPrintRequestAttributeSet;
导入javax.print.attribute.PrintRequestAttributeSet;
导入javax.print.attribute.standard.MediaPrintableArea;
导入javax.print.attribute.standard.orientationrequired;
导入javax.print.attribute.standard.PrintQuality;
导入javax.print.attribute.standard.PrinterResolution;
导入javax.swing.UIManager;
导入javax.swing.UnsupportedLookAndFeelException;
公共类ImgPrinter实现可打印{
缓冲图像img;
缓冲图像缩放;
@凌驾
公共整型打印(图形、页面格式、页面格式、整型页面索引)
抛出PrinterException{
int result=无此类页面;
Graphics2D g2d=(Graphics2D)graphics.create();
translate((int)(pageFormat.getImageableX()),(int)(pageFormat.getImageableY());
如果(pageIndex==0){
double pageWidth=pageFormat.getImageableWidth();
double pageHeight=pageFormat.getImageableHeight();
如果(缩放==null){
//交换宽度和高度以允许旋转。。。
系统输出打印项次(页面宽度+x+页面高度);
scaled=getScaledInstanceToFit(
img,
新维度((int)pageHeight,(int)pageWidth));
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");
}
}
double scaleX = pageWidth / imageWidth;
double scaleY = pageHeight / imageHeight;
double scale = Math.min(scaleX, scaleY);
g2d.scale(scale, scale);
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");
}
});
}
}