Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Guten Tag.
Habe den Thread "Probleme mit drucken aus Java" beendet, weil ich von Grund auf das mit dem drucken verstehen lernen muss.
Ich habe:
Java:
FileInputStream fls = new FileInputStream("/Pfad/bild.png");
bild.png - Abmessung: 13 x 8 cm (ca. 491 x 302 pixel)
Dieses versuche ich jetzt auf ein A4-Papier zu drucken.
X - Position = 5cm (ca. 189px) -> vom linken Rand
Y - Position = 12cm (ca. 454px) -> vom oberen Rand
Breite und Höhe Originalgrösse. (13 x 8 cm)
Habe etliche Links gefunden! (konnte es aber mit meinen Kenntinssen nicht umsetzen)
Egal wie ich es anstelle, es wird mir immer das Bild auf das ganze Blatt aufgezogen!
Nicht mal die 4mm nicht Druckbarerbereich (links, oben, rechts und unten) wird berücksichtigt!
Er druckt immer die X/Y-Kordinaten bei (17 / 11 mm)
Gibt es Jemand der mir hier ein kleines Skript geben könnte, welches ich dann testen und analysieren könnte?
Da ich kein Profi bin könnte ich so ev. herausfinden, welche Parameter für was Zuständig sind um das gewünschte Ergebnis zu erhalten.
Vielen Dank!
Es wäre so hilfreich, damit ich endlich ein stück weiter kommen könnte... ☺️
Nein. Das Bild ist 491x302px grosz. Vielleicht sind noch Metadaten hinterlegt welche die DPI angeben, aber ob diese Hinweise von druckenden Programmen beachtet werden oder nicht, ist Sache des Programms (und des Druckers manchmal).
package panelPrint;
import java.awt.Component;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import javax.imageio.ImageIO;
import javax.print.Doc;
import javax.print.DocFlavor;
import javax.print.DocPrintJob;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.SimpleDoc;
import javax.print.attribute.AttributeSet;
import javax.print.attribute.DocAttributeSet;
import javax.print.attribute.HashAttributeSet;
import javax.print.attribute.HashDocAttributeSet;
import javax.print.attribute.standard.Media;
import javax.print.attribute.standard.MediaPrintableArea;
import javax.print.attribute.standard.MediaSize;
import javax.print.attribute.standard.MediaSizeName;
import javax.print.attribute.standard.MediaTray;
import javax.print.attribute.standard.PrintQuality;
import javax.print.attribute.standard.PrinterName;
public class PanelPrint {
double px2mm = 0.2645833333333; // 1px = 0.2645833333333 mm
double dpFaktor = 72.0;
/**
* Sollte die übergebene Komponente samt Objekten drucken (<i>hier ein JPanel</i>)
* @param printObjekt Die zu druckende Komponente.
* @param printerName Der Druckername (<i>hier <b>Canon_MF720Cdw</b></i>)
* @param tray Das Papierfach (<i>"Einzug 1", "Einzug 2" oder "Mehrzweck Papierfach"</i>
* @param isoTyp Das Papierformat. (<i>A4, C5, usw</i>)
* @param myPfad Pfad zum Anwendungsorder in dem das erstellte BufferedImage als "print.png" gespeichert wird.
*/
public PanelPrint(Component printObjekt, String printerName, String tray, String isoTyp, String myPfad) {
System.out.println("Wirft die aktuelle Position und Grösse des printObjekt:");
System.out.println("\tprintObjekt X = "+printObjekt.getX()+" px \tmm = "+(printObjekt.getX()*px2mm));
System.out.println("\tprintObjekt Y = "+printObjekt.getY()+" px \tmm = "+(printObjekt.getY()*px2mm));
System.out.println("\tprintObjekt W = "+printObjekt.getWidth()+" px\tmm = "+(printObjekt.getWidth()*px2mm));
System.out.println("\tprintObjekt H = "+printObjekt.getHeight()+" px\tmm = "+(printObjekt.getHeight()*px2mm));
AttributeSet aset = new HashAttributeSet();
aset.add(new PrinterName(printerName, null));
PrintService[] services = PrintServiceLookup.lookupPrintServices(DocFlavor.INPUT_STREAM.PNG, aset);
if (services.length >= 1) {
DocPrintJob pj = services[0].createPrintJob();
MediaSizeName msnISO = null;
switch(isoTyp) {
case "A4":
msnISO = MediaSizeName.ISO_A4;
break;
case "C5":
msnISO = MediaSizeName.ISO_C5;
break;
}
MediaSize ms = MediaSize.getMediaSizeForName(msnISO);
int msWidth = Math.round(ms.getX(MediaSize.MM));
int msHeight = Math.round(ms.getY(MediaSize.MM));
PrintService drucker = null;
drucker = getPrinter(printerName);
//Hier habe ich versucht den Druckbaren bereich fest zu legen!
MediaPrintableArea mpa = new MediaPrintableArea(4, 4, msWidth, msHeight, MediaPrintableArea.MM);
DocAttributeSet das = new HashDocAttributeSet();
das.add(msnISO);
das.add(mpa);
das.add(PrintQuality.HIGH);
das.add(getMediaTray(drucker, tray));
FileInputStream fls = null;
File tmpSave = new File(myPfad+"print.png");
try {
//Erstellt ein Buffered-Image und speichert es als "../print.png"
ImageIO.write(getSnapShot(printObjekt), "png", tmpSave);
//Liest das "../print.png" in FileInputStream (fls) ein.
fls = new FileInputStream(tmpSave);
if(fls != null && tmpSave.exists()) {
Doc doc = new SimpleDoc(fls, DocFlavor.INPUT_STREAM.PNG, das);
pj.print(doc, null);
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
if(tmpSave.exists()) {
// tmpSave.delete();
System.exit(0);
}
}
}
/**
* Erstellt aus einer Komponente ein <b><font color='blue'>BufferedImage</font></b>
* @param view Die Komponente (<i>JFrame, JDialog, JPanel, JLabel, etc.</i>)
* @return Das erstellte <b>BufferedImage</b>.
*/
private BufferedImage getSnapShot(Component view)
{
int w = (int) (view.getWidth());
int h = (int) (view.getHeight());
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
synchronized (view.getTreeLock())
{
view.paint(image.createGraphics());
}
return image;
}
//-----------------------------------------------------------------------------------------------
private PrintService getPrinter(String printerName) {
AttributeSet aset = new HashAttributeSet();
aset.add(new PrinterName(printerName, null));
PrintService[] services = PrintServiceLookup.lookupPrintServices(null, aset);
for (PrintService service : services) {
if (service.getName().equals(printerName)) {
return service;
}
}
return null;
}
private MediaTray getMediaTray(PrintService printer, String trayName) {
DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PAGEABLE;
Object o = printer.getSupportedAttributeValues(Media.class, flavor, null);
if (o != null && o.getClass().isArray()) {
for (Media media : (Media[]) o) {
if (media instanceof MediaTray) {
if(media.toString().equals(trayName)) {
return (MediaTray) media;
}
}
}
}
return null;
}
}
Die Ausgabe Zeilen 41 - 45 ergibt:
Wirft die aktuelle Position und Grösse des printObjekt:
printObjekt X = 15 px mm = 3.9687499999994995
printObjekt Y = 15 px mm = 3.9687499999994995
printObjekt W = 850 px mm = 224.89583333330498
printObjekt H = 596 px mm = 157.6916666666468
Nachtrag:
Egal ob A4 oder C5!
z.B. ist beim übereinanderlegen der Ausdrucke sind die gedruckten Texte exakt gleich gross! Nur beim C5 wird ringsum alles abgeschnitten.
Fazit iwo fehlen im Obigen Code ANGABEN oder es wurden falsche Angaben gesetzt! ??? Verstehs nicht.
grosz = groß -> der Buchstabe ß wird ja auch sz genannt und das ist eine mögliche Schreibweise, wenn z.B. kein ß zur Verfügung ist weil man z.B. eine US Tastatur hat oder so - da ist das ß dann ein ALT + 225 (Zehnertastatur).
grosz = groß -> der Buchstabe ß wird ja auch sz genannt und das ist eine mögliche Schreibweise, wenn z.B. kein ß zur Verfügung ist weil man z.B. eine US Tastatur hat oder so - da ist das ß dann ein ALT + 225 (Zehnertastatur).
Auf der CH-Tastatur (auf einem Linux) kann das ß auch mit [Alt Gr] + s geschrieben werden. Wenn ich gewusst hätte dass ich das NACH meiner Pensionierung noch gebrauchen könnte, hätte ich vor mehr als 48 Jahren, in der Schule besser aufgepasst, wo und wie das eingesetzt werden soll/muss!
😄😄😄😄😄
Aber egal was ich da zusammenbaue, es kommt nur Müll raus.
Gibt es denn kein einfaches funktionierendes Script welches mir ein PNG (sagen wir 150x150 pixel) zentriert auf einem A4 Papier ohne Druckerdialog ausdrucken kann?
Das PNG lade ich mit: FileInputStream fls = new FileInputStream("/Pfad/bild.png");
Anhand eines funktionierenden Script könnte ich lernen was, wie, wo gesetzt werden muss um das zu erreichen.
Mit Faulheit hat das nichts zu tun.
Wenn sowas mit JAVA gar nicht geht, welche Script-Sprachen könnten mir dann empfohlen werden?
Ein PNG-Bild ist ein Rasterbild, das aus einzelnen Bildpunkten (Pixel) besteht. Da diese rechteckig angeordnet werden, hat ein solches Bild eine "Breite" und "Höhe" in Pixel.
Die Größe eines Pixels ist nicht definiert, sondern ist abhängig von der in dpi (dots per inch) angegebenen Auflösung des Aufnahme- bzw. Ausgabegeräts.
Dazu muss man verstehen, dass AWT mit verschiedenen Koordinatensystemen arbeitet, die im Gegensatz zu Rasterbildern auf individuellen Pixeln basieren. Anwendungen arbeiten im sog. "User Space", ein Koordinatensystem, das unabhängig vom Ausgabegerät eine Auflösung von etwa 72 dpi hat. Die Auflösung bezieht sich dabei auf ganzzahlige Koordinaten. Zeichnest Du also in einem Graphics-Objekt eine Linie von (100, 100) bis (172, 100), dann sollte diese Linie auf jedem Gerät etwa 1 Zoll lang sein. Die Linie kann aber aus mehr als 72 Bildpunkten bestehen.
Nebenbei: die 72 dpi stimmen nicht immer. Bei Geräten, die den 72 dpi relativ nahe kommen, wird einfach die Auflösung des Geräts verwenden. Bei einem 90 dpi Monitor könnte es z. B. standardmäßig zu 90 dpi im User Space kommen. Das soll hier aber einfach mal vernachlässigt werden, schließlich reden wir hier vom Drucker.
Der PrintService kennt die Auflösung des Druckers und stellt für den Druck ein Graphics-Objekt zur Verfügung, auf das eine affine Transformation angewendet wird, so dass die 72 dpi im User Space auf die Auflösung des Druckers umgerechnet wird. Wenn man das selbst nachvollziehen will, muss man berücksichtigen, dass sich die Auflösung des Druckers in der Regel auf die einzelnen Farbpunkte bezieht. Ein Bildpunkt wird im Vierfarbdruck mit vier Punkten gedruckt (CMYK), macht sich halt besser, wenn man 1200 dpi statt 300 dpi anpreisen kann... (und technisch betrachtet ist es ja auch nicht falsch). Bezogen auf die 72 dpi im User Space erhält man bei einem 1200 dpi Vierfarbdruck also einen Faktor von 300 / 72. Ein Zoll entspricht 72 Punkten bei 72 dpi und 300 Punkten bei 300 dpi, also das 4,16666....-fache.
In den meisten Fällen muss diese Umrechnerei den Entwickler nicht weiter interessieren: er zeichnet eine Linie zwischen zwei Punkten und den Rest erledigt das System. Bei Bildern ist das aber etwas anders, da dieses wie oben erwähnt aus diskreten Bildpunkten bestehten d. h. jeder einzelne Bildpunkt muss auf den User Space abgebildet werden.
Wenn man ein Bild nun einfach 1:1 auf den User Space überträgt, d. h. jede Koordinate im Bild unverändert in den User Space übernimmt (und das ist standardmäßig der Fall), dann wird das Bild in 72 dpi aufgelöst. D. h. ein Bild mit einer Größe von 491 x 302 Pixel würde 6,82 Zoll (17,32 cm) breit und 4,19 Zoll (10,65 cm) hoch ausgegeben werden.
Um das zu verhindern, muss das Bild skaliert ausgegeben werden (nicht das Bild selbst skalieren, denn dann würde die Qualität leiden!).