Stampa barcode mediante Barcode4J

di il
9 risposte

Stampa barcode mediante Barcode4J

Saluti a tutti,
sto stampando diversi oggetti grafici su stampante utilizzando le classi Printer di Java.
Per i testi e formattatura della pagina è tutto ok.

Ho solo un problema relativo alla stampa di un barcode che risulta eccessivamente largo. (il confronto è fatto rispetto a quello stampato con un OCX a pagamento che ha una dimensione che è la metà (TEC-IT in un Report di Access2016)).

Esiste qualche soluzione in proposito. Si può effettuare una riduzione proporzionata della larghezza del barcode ?

Ho provato a modificare il valore "moduleWidth": barcode128Bean.setModuleWidth(UnitConv.in2mm(moduleWidth / dpi));
dpi = 72 (POINTS_PER_INCH)
moduleWidth = 1

Se riduco il valore moduleWidth (es.: 0.7, ottengo, come risultato, un taglio dell'immagine del barcode (parte iniziale).

Grazie per aver letto, ancor di più se mi date feedback.

9 Risposte

  • Re: Stampa barcode mediante Barcode4J

    cnesan ha scritto:


    Ho provato a modificare il valore "moduleWidth": barcode128Bean.setModuleWidth(UnitConv.in2mm(moduleWidth / dpi));
    dpi = 72 (POINTS_PER_INCH)
    moduleWidth = 1

    Se riduco il valore moduleWidth (es.: 0.7, ottengo, come risultato, un taglio dell'immagine del barcode (parte iniziale).
    Non è facile (per me) rispondere perché non conosco la Barcode4J. Puoi postare un breve codice (compilabile) che riproduce il problema? Per la libreria, non c'è problema, basta che mi dici la versione esatta. Se c'è sul Maven Central la trovo.
  • Re: Stampa barcode mediante Barcode4J

    Per il barcode: barcode4j-2.1.0

    Il codice è bello lungo e anche interessante. Cerco di metterlo su più risposte.
    
    package application;
    
    import support.PrintLabels;
    
    public class TestBarcode {
    	
    	public static void main(String[] args) {
    		boolean askDialog = false;
    		boolean askFormat = false;
    		try {
    			new PrintLabels(askDialog, askFormat, PrintLabels.makeData());
    		} catch (Exception e) {
    			System.out.println(e.getMessage());
    		}
    		System.exit(0);
    	}
    
    }
    
    
  • Re: Stampa barcode mediante Barcode4J

    
    package support;
    
    import java.awt.Font;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.RenderingHints;
    import java.awt.image.BufferedImage;
    import java.awt.print.PageFormat;
    import java.awt.print.Printable;
    
    import java.io.IOException;
    import java.util.ArrayList;
    
    import javax.swing.JOptionPane;
    
    import org.krysalis.barcode4j.impl.code128.Code128Bean;
    import org.krysalis.barcode4j.impl.code128.Code128Constants;
    import org.krysalis.barcode4j.output.bitmap.BitmapCanvasProvider;
    import org.krysalis.barcode4j.tools.UnitConv;
    
    
    
    public class Label implements Printable {
    	
    	private double spaceFromTop;				//Distance border top to border top first label (first top-left)
    	private double spaceFromLeft;				//Distance border left to border left first label (first top-left)
    	private double ofsX;						//Label Offset Y
    	private double ofsY;						//Label Offset Y
    	private double iofsX;						//Object Offset X 
    	private double iofsY;						//Object Offset Y
    	private double labelHeight;					//Altezza della label
    	private int labelWidth;						//Larghezza della label
    	private int qtyLabelOnPage;					//Quantita' di label presenti nel foglio
    	private int dpi;
    	private boolean borderOn = false;
    	private ArrayList<ArrayList<String>> info;	//Records/Fields
    	
    	public Label(double marginX, double marginY, ArrayList<ArrayList<String>> info, int dpi, boolean borderOn) {		
    		this.borderOn = borderOn;
    		this.labelHeight = 90;						//Altezza della label
    		this.labelWidth = 165;						//larghezza della label
    		this.qtyLabelOnPage = info.size();			//Quantita' di label presenti nel foglio deve corrispondere con la dimensione dell'array dati
    		this.spaceFromTop = 19f;					//Distanza della Label dal bordo superiore del foglio
    		this.spaceFromLeft = 25f;					//Distanza della Label dal bordo sinistro del foglio
    		if((this.spaceFromTop-marginY) > marginY) {			//Offset della label verticale
    			this.ofsY = this.spaceFromTop - marginY;
    		} else {
    			this.ofsY = marginY;	
    		}
    		if((this.spaceFromLeft-marginX) > marginX) {			//Offset della label orizzontale
    			this.ofsX = this.spaceFromLeft - marginX;	
    		} else {
    			this.ofsX = marginX;	
    		}
    		this.iofsX = 15;								//Offset di posizione per tutti gli oggetti stampati
    		this.iofsY = 10;								//Offset di posizione per tutti gli oggetti stampati		
    		this.info = info;
    		this.dpi = dpi;
    
    	}
    	
    	private double offSetX() {
    		return ofsX + iofsX;
    	}
    	
    	private double offSetY(int index) {
    		return ofsY + iofsY + labelHeight*index; 
    	}
    
    	/**
    	 * Metodo per la generazione degli oggetti e localizzazione sulla pagina fisica.
    	 */
    	public int print(Graphics g, PageFormat pf, int page) {
    		
    		//--- Create the Graphics2D object
    		Graphics2D g2d = (Graphics2D) g;
    		//g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
    		//g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
    		//g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    
    		//--- Translate the origin to 0,0 for the top left corner
    		g2d.translate(pf.getImageableX(), pf.getImageableY());
    		
    		//System.out.println("Page n." + page);
    		
    		//Dichiarazioni dei fonts da utilizzare per i testi
    		Font f1 = new Font("Times New Roman", Font.BOLD, 16);
    		Font f2 = new Font("Times New Roman", Font.PLAIN, 10);
    		Font f3 = new Font("Arial", Font.BOLD, 10);
    		Font f4 = new Font("Arial", Font.BOLD, 12);
    		Font f5 = new Font("Arial", Font.PLAIN, 10);
    		Font f6 = new Font("Arial", Font.BOLD, 10);
    		
    		for(int itemData = 0; itemData < qtyLabelOnPage; itemData++) {
    			//Composizione dei dati			
    			String address2 = info.get(itemData).get(5) + " " + info.get(itemData).get(6) + " " + info.get(itemData).get(7);			//String	ADDRESS2 Composizione
    			//String cmr = "SDA: " + info.get(itemData).get(28);
    			String packing = " BOX " + info.get(itemData).get(9) + "/" + info.get(itemData).get(10);
    			String quantity = " QTY: " + info.get(itemData).get(11);				
    			String barcodeData = info.get(itemData).get(13);															//String	BARCODE Composizione ID_Correlation
    
    			if(this.borderOn==true) {
    				g2d.drawRect(UnitConv.mm2px(ofsX, dpi), UnitConv.mm2px(ofsY + labelHeight*itemData, dpi), UnitConv.mm2px(this.labelWidth, dpi), UnitConv.mm2px(this.labelHeight, dpi));
    			}
    			
    			//Inizializzazione Font e inserimento stringa di stampa I/OFFSET Pos X, DPI                     I/OFFSET Pos Y, DPI
    			g2d.setFont(f1); g2d.drawString("Mia Società",					UnitConv.mm2px(this.offSetX() + 00, dpi),	UnitConv.mm2px(this.offSetY(itemData) + 10, dpi));	//String	BANCASELLA		
    			g2d.setFont(f2); g2d.drawString("SOC s.r.l.",					UnitConv.mm2px(this.offSetX() + 90, dpi),	UnitConv.mm2px(this.offSetY(itemData) + 10, dpi));	//String	STM		
    			g2d.setFont(f3); g2d.drawString("ID RAC",						UnitConv.mm2px(this.offSetX() + 0, dpi),	UnitConv.mm2px(this.offSetY(itemData) + 14, dpi));	//String	ID_GROUP
    			g2d.setFont(f4); g2d.drawString(info.get(itemData).get(1),		UnitConv.mm2px(this.offSetX() + 20, dpi),	UnitConv.mm2px(this.offSetY(itemData) + 14, dpi));	//Value		ID_GROUP
    			g2d.setFont(f5); g2d.drawString("Destinazione:",				UnitConv.mm2px(this.offSetX() + 50, dpi),	UnitConv.mm2px(this.offSetY(itemData) + 22, dpi));	//String	Destinazione
    			g2d.setFont(f5); g2d.drawString(info.get(itemData).get(2),		UnitConv.mm2px(this.offSetX() + 80, dpi),	UnitConv.mm2px(this.offSetY(itemData) + 22, dpi));	//Value		CO
    			g2d.setFont(f5); g2d.drawString(info.get(itemData).get(3),		UnitConv.mm2px(this.offSetX() + 80, dpi),	UnitConv.mm2px(this.offSetY(itemData) + 26, dpi));	//Value		NOMINATIVO
    			g2d.setFont(f5); g2d.drawString(info.get(itemData).get(4),		UnitConv.mm2px(this.offSetX() + 80, dpi),	UnitConv.mm2px(this.offSetY(itemData) + 30, dpi));	//Value		INDIRIZZO1
    			g2d.setFont(f5); g2d.drawString(address2,						UnitConv.mm2px(this.offSetX() + 80, dpi),	UnitConv.mm2px(this.offSetY(itemData) + 34, dpi));	//Value		POSTAL CODE + CITY + PROVINCE
    			
    			g2d.setFont(f5); g2d.drawString(info.get(itemData).get(12).substring(0, 8),	UnitConv.mm2px(this.offSetX() + 00, dpi),	UnitConv.mm2px(this.offSetY(itemData) + 43, dpi));	//Value		CMR
    			g2d.setFont(f5); g2d.drawString(info.get(itemData).get(12).substring(8),	UnitConv.mm2px(this.offSetX() + 49, dpi),	UnitConv.mm2px(this.offSetY(itemData) + 43, dpi));	//Value		CMR
    			g2d.setFont(f5); g2d.drawString(packing,									UnitConv.mm2px(this.offSetX() + 100, dpi),	UnitConv.mm2px(this.offSetY(itemData) + 43, dpi));	//Value		BOX/TOTBOX
    			g2d.setFont(f5); g2d.drawString(quantity,									UnitConv.mm2px(this.offSetX() + 100, dpi),	UnitConv.mm2px(this.offSetY(itemData) + 47, dpi));	//Value		QTY
    			g2d.setFont(f6); g2d.drawString(info.get(itemData).get(13).substring(1, 16),UnitConv.mm2px(this.offSetX() + 00, dpi), 	UnitConv.mm2px(this.offSetY(itemData) + 47, dpi));	//Value		ID_CORRELATION Start
    			g2d.setFont(f6); g2d.drawString(info.get(itemData).get(13).substring(16),	UnitConv.mm2px(this.offSetX() + 49, dpi), 	UnitConv.mm2px(this.offSetY(itemData) + 47, dpi));	//Value		ID_CORRELATION End
    			
    			//Stampa del barcode riportante ID_CORRELATION StartID_CORRELATION End (16+16 digit) come immagine
    			Code128Bean barcode128Bean = new Code128Bean();
    			barcode128Bean.setCodeset(Code128Constants.CODESET_A);
    			
    			//Configure the barcode generator adjust barcode width here
    			final double moduleWidth = 1f;
    			barcode128Bean.setModuleWidth(UnitConv.in2mm(moduleWidth / dpi));
    			barcode128Bean.doQuietZone(false);
    			barcode128Bean.setBarHeight(10);
    			barcode128Bean.setFontName("ARIAL");
    			barcode128Bean.setFontSize(5);
    			
    			try {
    				BitmapCanvasProvider canvas = new BitmapCanvasProvider(dpi, BufferedImage.TYPE_BYTE_BINARY, false, 0);
    				barcode128Bean.generateBarcode(canvas, barcodeData);
    				canvas.finish();
    				BufferedImage image = canvas.getBufferedImage();
    				g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
    				g2d.drawImage(image, UnitConv.mm2px(this.offSetX(),dpi), UnitConv.mm2px(this.offSetY(itemData) + 48,dpi), image.getWidth(), image.getHeight(), null);
    			} catch (IOException e2) {
    				JOptionPane.showMessageDialog(null, e2.getMessage());
    				return (NO_SUCH_PAGE);
    			}
    		}
    		return (PAGE_EXISTS);
    	}
    
    	
    }
    
    
  • Re: Stampa barcode mediante Barcode4J

    
    package support;
    
    import java.awt.print.Book;
    import java.awt.print.PageFormat;
    import java.awt.print.Paper;
    import java.awt.print.PrinterException;
    import java.awt.print.PrinterJob;
    import java.util.ArrayList;
    import javax.print.PrintService;
    import javax.swing.JOptionPane;
    
    public class PrintLabels {
    	
    	private final static int POINTS_PER_INCH = 72;	
    	private final static int MAXLABEL_FOR_PAGE = 3;
    	private final static double MARGIN_X = 5f;
    	private final static double MARGIN_Y = 5f;
    	private ArrayList<ArrayList<ArrayList<String>>> data_preparation = null;
    	private ArrayList<ArrayList<String>> data_forpage = null;
    	private ArrayList<ArrayList<String>> incomingData; 
    	
    	/**
    	 * Costruttore delle labels
    	 * 
    	 * @param askDialog		True viene visualizzato la Dialog della stampante, False viene usata la stampante predefinita.
    	 * @param askFormat		True viene visualizzato la Dialog del formato documento, False viene utilizzato il formato predefinito (A4).
    	 * @param incomingData	Type: ArrayList<ArrayList<String>> ~ Arguments: Record<Fields<Data>>
    	 * @throws Exception 	Generato se l'ArrayList incomingData e' vuoto o nullo.
    	 */
    	public PrintLabels(boolean askDialog, boolean askFormat, ArrayList<ArrayList<String>> incomingData) throws Exception {
    				
    		PrintService ps = PrintUtility.getDefaultPrinter();							//--- Get default printer to send PrintJob.setPrintService()
    		
    		this.incomingData = incomingData;											//--- Let Data Array
    		if(incomingData == null || incomingData.isEmpty()==true) throw new Exception("Incoming data is empty");
    		prepareData();																//--- Prepare data and record for page (3 label on page on 2°Array)
    		PrinterJob printJob = PrinterJob.getPrinterJob();							//--- Create a new PrinterJob object		
    		PageFormat documentPageFormat = printJob.defaultPage();						//--- Create a new PageFormat object
    		
    		//PageFormat documentPageFormat = printJob.pageDialog(printJob.defaultPage());//--- Create a new PageFormat object
    		Paper paper = new Paper();													//--- Create a new Paper object
    		Book book = new Book();														//--- Create a new book to add pages to
    		if(askFormat == false) {
    			paper.setSize(595.27f, 841.88f);										//--- Define page A4 Formula is (210 / 25.4) * 72 = 595.27f ~ (297 / 25.4) * 72 = 841.88f
    																					//    A4(210mm. - 297mm.) ~ 1mm. = 25.4inch ~ Value passed to Method is in 1/72inch
    			//--- Setup Document and Paper Object
    			documentPageFormat.setOrientation(PageFormat.PORTRAIT);														//Orientamento del documento	
    			paper.setImageableArea(0, 0, paper.getWidth() , paper.getHeight() );										//Definizione dell'area di stampa
    			documentPageFormat.setPaper(paper);																			//Oggetto Paper passato all'oggetto Document
    		} else {
    			printJob.pageDialog(documentPageFormat);
    		}
    		
    		//--- Add page into Book object
    		for(int i = 0; i < this.SizeData(); i++) {
    			book.append(new Label(MARGIN_X,MARGIN_Y,this.getData(i),POINTS_PER_INCH, false), documentPageFormat);					//--- Add page using the default page format for this print job
    		}
    		//System.out.println("NumberOfPages: " + book.getNumberOfPages());
    		printJob.setPageable(book);																					//--- Tell the printJob to use the book as the pageable object
    		
    		if(askDialog == false) {
    			try {			
    				printJob.setPrintService(ps);			
    				try {
    					printJob.print();
    				} catch (Exception PrintException) {
    					JOptionPane.showMessageDialog(null, PrintException.getMessage());
    					return;
    				}			
    			} catch (PrinterException e) {
    				JOptionPane.showMessageDialog(null, e.getMessage());
    				return;
    			}
    		} else {
    			//--- Show the print dialog box. If the user click the
    			//--- print button we then proceed to print else we cancel
    			//--- the process.
    			if (printJob.printDialog()) {
    				try {
    					printJob.print();
    				} catch (Exception PrintException) {
    					JOptionPane.showMessageDialog(null, PrintException.getMessage());
    					return;
    				}
    			}			
    		}		
    	}
    	
    	/**
    	 * Metodo che prepara i dati che saranno utilizzati per la stampa.
    	 * 
    	 * @return
    	 */
    	private void prepareData() {
    		int recordToPrepare = incomingData.size();
    		
    		data_preparation = new ArrayList<ArrayList<ArrayList<String>>>();		
    		for(int i = 0; i < recordToPrepare; i++) {			
    			data_forpage = new ArrayList<ArrayList<String>>();
    			int newLimit = i + MAXLABEL_FOR_PAGE;
    			if(newLimit>recordToPrepare) newLimit = recordToPrepare;
    			for(int k = i; k < newLimit; k++) {
    				data_forpage.add(incomingData.get(i));				
    				if(k < newLimit-1) i++;
    			}
    			data_preparation.add(data_forpage);
    		}		
    	}
    	
    	/**
    	 * Metodo che ritorna il record richiesto
    	 * 
    	 * @param index
    	 * @return
    	 */
    	private ArrayList<ArrayList<String>> getData(int index) {
    		return data_preparation.get(index);
    	}
    	
    	private int SizeData() {
    		return data_preparation.size();
    	}
    	
    	public static ArrayList<ArrayList<String>> makeData() {
    		ArrayList<ArrayList<String>> al = new ArrayList<ArrayList<String>>();
    		for(int i = 0; i < 100; i++) {
    			ArrayList<String> listField = new ArrayList<String>(); 
    			listField.add("45 " + i);
    			listField.add("AZ.AGRICOLE");		
    			listField.add("POSTAZIONE 45° " + i);
    			listField.add("ATT.NE MARIAROSA");
    			listField.add("VIA ACATE 19");
    			listField.add("80100");
    			listField.add("CASERTA");
    			listField.add("CE");
    			listField.add("F567891");
    			listField.add("1");
    			listField.add("7");
    			listField.add("140");
    			listField.add("5141520012520021");
    			listField.add("00000000005241520000000000895641");        	
    			al.add(listField);
    		}
    		return al;
    	}
    	
    }
    
    
  • Re: Stampa barcode mediante Barcode4J

    
    package support;
    
    import java.awt.print.PrinterJob;
    import javax.print.PrintService;
    import javax.print.PrintServiceLookup;
    
    import java.util.List;
    import java.util.ArrayList;
    
    public final class PrintUtility {
    
        /**
         * Retrieve a Print Service with a name containing the specified PrinterName; will return null if not found.
         * 
         * @return
         */
        public static PrintService findPrintService(String printerName) {
    
            printerName = printerName.toLowerCase();
    
            PrintService service = null;
    
            // Get array of all print services
            PrintService[] services = PrinterJob.lookupPrintServices();
    
            // Retrieve a print service from the array
            for (int index = 0; service == null && index < services.length; index++) {
    
                if (services[index].getName().toLowerCase().indexOf(printerName) >= 0) {
                    service = services[index];
                }
            }
    
            // Return the print service
            return service;
        }
    
        /**
         * Retrieve a default Printer Service
         * 
         * @return
         */
        public static PrintService getDefaultPrinter() {
        	PrintService defaultService = PrintServiceLookup.lookupDefaultPrintService();
        	return defaultService;
        }
        
        /**
         * Retrieves a List of Printer Service Names.
         * 
         * @return List
         */
        public static List<String> getPrinterServiceNameList() {
    
            // get list of all print services
            PrintService[] services = PrinterJob.lookupPrintServices();
            List<String> list = new ArrayList<String>();
    
            for (int i = 0; i < services.length; i++) {
                list.add(services[i].getName());
            }
    
            return list;
        }
    
        /**
         * Utility class; no construction!
         */
         private PrintUtility() {}
    }
    
  • Re: Stampa barcode mediante Barcode4J

    In pratica viene passato un ArrayList<ArrayList<String>> come base dati (in realtà è meglio usare un DB).

    La classe PrintLabels organizza i dati e genera istanze di tipo Labels da aggiungere a book passando i dati che il costruttore di Label deve gestire per ogni pagina (3 label per pagina).

    La classe Labels organizza l'impaginazione di ogni singola label nella pagina.

    La classe PrintUtility si occupa di effettuare le conversioni.

    Consiglio di impostare la stampante di default PDF.

    Il problema è che la larghezza del barcode è esagerata ma credo che faccio confusione ancora tra risoluzione/pollici/unità metodi grafici (1/72)

    Fammi sapere.
  • Re: Stampa barcode mediante Barcode4J

    cnesan ha scritto:


    Il problema è che la larghezza del barcode è esagerata ma credo che faccio confusione ancora tra risoluzione/pollici/unità metodi grafici (1/72)
    Sì, è probabile che sia così ....

    Comunque. Premesso, come detto, che NON conosco in dettaglio la Barcode4J, il punto sono tutti quei calcoli.
    Allora: setModuleWidth si aspetta una misura in millimetri (è ben indicato nel javadoc della Barcode4J) che non c'entra niente con la Printing API, di per sé. Quindi perché non imposti direttamente dei millimetri? Non servirebbero quei calcoli con il dpi.

    L'altro punto è che la Barcode4J ti genera una immagine bitmap. E il primo parametro del costruttore BitmapCanvasProvider è il dpi. Questo dpi, idem, NON c'entra direttamente con la Printing API.

    Faccio un esempio pratico, così ragioniamo meglio. Ho fatto una prova con il tuo codice, inserendo io dei valori nel codice. Se passo al setModuleWidth il valore 0.5 (mezzo millimetro) e poi al costruttore BitmapCanvasProvider passo 300 (intendendo quindi 300 dpi), ottengo una immagine di ben 2285 x 195 pixel (verificato in debugging!). Questi sono pixel puri e crudi, che avranno una dimensione fisica SOLO quando li "spalmi" su una superficie che si basa su un determinato valore di dpi per definire la densità fisica dei pixel (quindi: schermo, stampante, ecc..).

    Ora, dove li mettiamo questi 2285 pixel in orizzontale? Detto meglio: li spalmiamo su una superficie usando quale densità?
    Nella Printing API per default 1 unità vale 1/72 pollice. Questo NON vuol dire che la densità del dispositivo su cui stampi è 72 dpi!! Tu potresti stampare su una fantastica stampante laser a 1200 dpi. Semplicemente la Printing API ti dice che per default (se non cambi tu la matrice di trasformazione del Graphics) se vuoi stampare una cosa lunga 1 pollice devi stampare 72 unità. Tutto lì.

    Quindi, se tu vuoi ad esempio che la immagine complessiva del barcode occupi fisicamente 50mm in larghezza dovrai fare:

    50mm = ~1,9685 pollici

    Siccome, come detto, per default 1 unità = 1/72 pollice, allora dovresti stampare: 1,9685 * 72 = 141,732 unità

    Quindi se al g2d.drawImage passassi come width 142 unità, quei 2285 pixel verrebbero stampati su (circa) 50,09 millimetri.

    Problema che avrai già capito: ma drawImage riceve degli int! Così è un po' bruttino (oltre che scomodo). Appunto. In questi casi si "gioca" con la matrice di trasformazione (lo scalamento, in modo specifico). Ovvero al drawImage passi come width/height esattamente quei pixel cioè 2285 x 195.
    E poi ragioni così: quale è il fattore di scalamento da applicare (aggiungere!) sul Graphics della Printing API affinché 2285 unità (ora sono unità nella Printing API) vengano "spalmati" su 50 millimetri??

    Abbiamo detto che 50mm sono 141,732 unità con il default della Printing API, quindi se vogliamo concatenare a questo fattore di default il "nostro" fattore per avere 2285 pixel(unità) -> 50mm, dobbiamo fare: 141,732 / 2285 = 0,062027...... (è lungo, tronco per brevità).

    Se tu facessi g2d.scale(0.062027 , 0.062027); e poi stampi con drawImage 2285 x 195 unità, avresti circa 49,9997...mm x 4,2669....mm
    Chiaramente dovresti prima spostare l'origine degli assi (0,0) nel punto della superficie dove vuoi avere l'origine della immagine .. altrimenti fai casini.

    Quindi, scusa il post lungo ma ora chiudo (è tardi ..). Ho chiarito le idee o ... te le ho confuse di più?
  • Re: Stampa barcode mediante Barcode4J

    Grazie andbin,
    mi hai chiarito diversi aspetti che ignoravo.

    La cosa che mi ha colpito di più e mi ha portato fuori strada è stata la convinzione di dover passare a "g2d.drawImage()"
    1) la posizione x/y secondo le esigenze di posizionamento della immagine in pixel (ok)
    2) i valori concreti della immagine quali: "image.getWidth(), image.getHeight()" poichè credevo che con valori diversi avrei troncato l'img.

    L'altro aspetto è stata la confusione tra DPI richiesto dal metodo di "Barcode4J" per generare l'immagine Vs l'unità = 1/72'' richiesto dalle API di Java.

    Infatti, nei giorni scorsi, modificando DPI in origine, si producevano barcode tagliati/fuori pagina/fuori scala / etc. (un macello)

    A questo punto il parametro dpi viene utilizzato esclusivamente per formare l'img. mentre in altre parti utilizzero 72 come riferimento dei calcoli.

    Pertanto giusto per i posteri, la parte del codice è stato modificato così:
    
    			//Configure the barcode generator adjust barcode width here
    			final double moduleWidth = 0.5f; //mm.
    			final double widthBarcode = 60;  //mm.
    			final double heightBarcode = 10; //mm.
    			barcode128Bean.setModuleWidth(moduleWidth);
    			barcode128Bean.doQuietZone(false);
    			barcode128Bean.setBarHeight(10);
    			barcode128Bean.setFontName("ARIAL");
    			barcode128Bean.setFontSize(5);
    			
    			try {	//dpi = 600
    				BitmapCanvasProvider canvas = new BitmapCanvasProvider(dpi, BufferedImage.TYPE_BYTE_BINARY, false, 0);
    				barcode128Bean.generateBarcode(canvas, barcodeData);
    				canvas.finish();
    				BufferedImage image = canvas.getBufferedImage();
    				g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
    				
    				g2d.drawImage(image, 
    						(int)((this.offSetX()/25.4f) * 72), 
    						(int)(((this.offSetY(itemData) + 48)/25.4f) * 72), 
    						(int)((widthBarcode/25.4f)*72), 
    						(int)((heightBarcode/25.4f)*72), 
    						null);
    			} catch (IOException e2) {
    				JOptionPane.showMessageDialog(null, e2.getMessage());
    				return (NO_SUCH_PAGE);
    			}
    
    fermo restando il resto del codice.

    Domani mattina l'applico per vedere con il verificatore di barcode la leggibilità del barcode stampato.

    Grazie per l'intervento
  • Re: Stampa barcode mediante Barcode4J

    cnesan ha scritto:


    mi hai chiarito diversi aspetti che ignoravo.
    Bene

    cnesan ha scritto:


    La cosa che mi ha colpito di più e mi ha portato fuori strada è stata la convinzione di dover passare a "g2d.drawImage()"
    1) la posizione x/y secondo le esigenze di posizionamento della immagine in pixel (ok)
    2) i valori concreti della immagine quali: "image.getWidth(), image.getHeight()" poichè credevo che con valori diversi avrei troncato l'img.
    Allora: sulla posizione, sì, generalmente si specifica. Questo se la matrice di trasformazione è tale per cui "sai" calcolare la posizione partendo dalla origine predefinita. Se la matrice è quella di default, allora l'unità è 1/72 pollice, quindi è facile determinare dove posizionare le cose da stampare, se vuoi es. stare a 10cm dal bordo lo calcoli banalmente.
    Altrimenti si può specificare la posizione 0,0 tipicamente quando è già la matrice di trasformazione ad essere stata traslata, perché ad esempio applichi anche un fattore di scala molto "particolare" (es. calcolato con della logica) per cui sarebbe molto difficile/scomodo calcolare la posizione se l'origine degli assi fosse dov'era originalmente ma con quella scala "particolare" applicata.

    Sulla dimensione è bene chiarire una cosa. Se usi il drawImage che ha x, y, width e height, ad esempio così:

    g2d.drawImage(img, x, y, 72, 72, null);

    questi x/y/width/height sono nell'unità di misura del graphics. Non solo x e y .. anche width e height!!
    Quindi se la immagine fosse di 600x600 pixel, NON vuol dire che stampi solo 72x72 pixel della immagine. Vuol dire che stampi 600 pixel su 72 unità del graphics. Se è il default di 1/72 di pollice, quindi spalmeresti 600 pixel su 1 pollice, dando appunto (come caso specifico in questo esempio) 600 dpi come densità. Se la stampante fisica fosse appunto a 600 dpi otterresti una risoluzione "perfetta" sfruttando al massimo la stampante.
Devi accedere o registrarti per scrivere nel forum
9 risposte