package com.ns.utils; import java.awt.image.BufferedImage; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; import java.util.Vector; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.rendering.ImageType; import org.apache.pdfbox.rendering.PDFRenderer; import com.google.zxing.BarcodeFormat; import com.google.zxing.BinaryBitmap; import com.google.zxing.DecodeHintType; import com.google.zxing.LuminanceSource; import com.google.zxing.MultiFormatReader; import com.google.zxing.NotFoundException; import com.google.zxing.Result; import com.google.zxing.client.j2se.BufferedImageLuminanceSource; import com.google.zxing.common.HybridBinarizer; public class QRCodeZxingUtil { public static Map<String, String> scanQRCode(String dir, String fileName, String textKey) { Map<String, String> mp = new HashMap<String, String>(); // Hints for scanning Vector<BarcodeFormat> decodeFormat = new Vector<BarcodeFormat>(); decodeFormat.add(BarcodeFormat.QR_CODE); Hashtable<DecodeHintType, Object> hintMap = new Hashtable<DecodeHintType, Object>(); hintMap.put(DecodeHintType.TRY_HARDER, true); hintMap.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormat); MultiFormatReader qrcodeReader = new MultiFormatReader(); qrcodeReader.setHints(hintMap); // We try for several images of the PDF page at several DPI settings, // starting at the lowest setting, this might help for speed... int[] dpiSettings = { 96, 150, 200, 250, 300, 350 }; for (int i = 0; i < dpiSettings.length; i++) { try { // Try lowest DPI first. BufferedImage pageImage = getPageImage(dir, fileName, dpiSettings[i]); if (pageImage != null) { LuminanceSource source = new BufferedImageLuminanceSource(pageImage); BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); // By using decodeWithState, we keep the Hints that we set earlier. Result result = qrcodeReader.decodeWithState(bitmap); String text = result.getText(); // System.out.println(" Sucess at DPI -> " + dpiSettings[i]); pageImage.flush(); if (text != null && text.length() > 0) { mp.put(textKey, text); mp.put("DPI", Integer.toString(dpiSettings[i])); } } if (mp.containsKey(textKey)) { return mp; } } catch (IOException e) { System.out.print(" IOException at DPI -> " + dpiSettings[i]); } catch (NotFoundException e) { System.out.print(" NotFoundException at DPI -> " + dpiSettings[i]); } } return null; } private static BufferedImage getPageImage(String dir, String fileName, int dpi) throws IOException { BufferedImage image = null; Path docPath = Paths.get(dir.concat(fileName)); PDDocument pdfDoc = PDDocument.load(docPath.toFile()); try { PDFRenderer renderer = new PDFRenderer(pdfDoc); image = renderer.renderImageWithDPI(0, dpi, ImageType.BINARY); // entire page info } finally { pdfDoc.close(); } return image; } }
Category Archives: Bonus
QR code decoding by pdmodel
package com.ns.utils; import java.awt.image.BufferedImage; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDResources; import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObject; import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectImage; import com.ns.service.QRCodeDecoder; public class QRCodePdModelUtil { @SuppressWarnings("unchecked") public static Map<String, String> scanQRCode(String dir, String fileName, String textKey) { Map<String, String> map = new HashMap<String, String>(); List<PDPage> pages = null; BufferedImage qrCodeImg = null; String qrCode = null; PDDocument pdfDoc = null; try { Path docPath = Paths.get(dir.concat(fileName)); pdfDoc = PDDocument.load(docPath.toFile()); QRCodeDecoder decoder = new QRCodeDecoder(); pages = pdfDoc.getDocumentCatalog().getAllPages(); int dpi = 0; int dpiEffective = 0; int dpiLow = 0; for (PDPage page : pages) { try { if (null == qrCode) { qrCodeImg = page.convertToImage(BufferedImage.TYPE_BYTE_GRAY, 100); qrCode = decoder.getCompressedQRCode(qrCodeImg); } if (null == qrCode) { dpi = detectPageDPI(page); dpiEffective = dpi; dpiLow = dpi - 5; for (; dpiLow < dpiEffective; dpiEffective--) { qrCodeImg = page.convertToImage(BufferedImage.TYPE_BYTE_GRAY, dpiEffective); qrCode = decoder.getCode(qrCodeImg); if (null != qrCode) { break; } } } if (null == qrCode) { qrCodeImg = page.convertToImage(BufferedImage.TYPE_BYTE_GRAY, 400); qrCode = decoder.getCompressedQRCode(qrCodeImg); } System.out.println("Code:::" + qrCode); if (null != qrCode) { map.put("DPI", Integer.toString(dpi)); map.put(textKey, qrCode); return map; } } catch (Exception e) { System.out.println(e.getMessage()); } finally { qrCodeImg = null; qrCode = null; } } } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { if (null != pdfDoc) { try { pdfDoc.close(); } catch (IOException e) { e.printStackTrace(); } } pages = null; } return null; } private static int detectPageDPI(PDPage page) { PDResources res = page.getResources(); Collection<PDXObject> xObjects = res.getXObjects().values(); int imgHeight = 0; for (PDXObject xObject : xObjects) { if (xObject instanceof PDXObjectImage) { imgHeight = ((PDXObjectImage) xObject).getHeight(); } } float pageHeight = page.getMediaBox().getHeight() / 72; int dpi = (int) (imgHeight / pageHeight); if (200 > dpi) { dpi = 200; } if (300 < dpi) { dpi = 300; } return dpi; } }
package com.ns.service; import java.awt.RenderingHints; import java.awt.RenderingHints.Key; import java.awt.image.BufferedImage; import java.awt.image.BufferedImageOp; import java.awt.image.ConvolveOp; import java.awt.image.Kernel; import java.awt.image.RasterFormatException; import java.util.HashMap; import java.util.Map; import org.springframework.stereotype.Service; import com.google.zxing.BinaryBitmap; import com.google.zxing.ChecksumException; import com.google.zxing.FormatException; import com.google.zxing.LuminanceSource; import com.google.zxing.NotFoundException; import com.google.zxing.Result; import com.google.zxing.client.j2se.BufferedImageLuminanceSource; import com.google.zxing.common.HybridBinarizer; import com.google.zxing.qrcode.QRCodeReader; @Service public class QRCodeDecoder { public String getCode(BufferedImage image) { String code = null; try { // vertical bottom scan BufferedImage procImage = image.getSubimage(0, image.getHeight() / 2, image.getWidth(), image.getHeight() / 2 - 20); code = decode(procImage); } catch (RasterFormatException e) { // continue } return code; } public String getCompressedQRCode(BufferedImage image) { String code = null; try { // vertical bottom scan BufferedImage procImage = image.getSubimage(150, image.getHeight() / 2, image.getWidth() - 150, image.getHeight() / 2 - 200); code = decode(procImage); } catch (RasterFormatException e) { // continue } return code; } public String decode(BufferedImage image) { RenderingHints hints = getRenderingHints(); float[] kernelData = null; BufferedImageOp op = null; BufferedImage procImage = null; LuminanceSource source = null; BinaryBitmap bitmap = null; QRCodeReader reader = new QRCodeReader(); Result result = null; String code = null; for (int denom = 10; denom <= 50; denom += 10) { try { procImage = image; float factor = (1.0f / ((float) denom)); kernelData = getKernelData(factor); op = new ConvolveOp(new Kernel(4, 4, kernelData), ConvolveOp.EDGE_NO_OP, hints); source = new BufferedImageLuminanceSource(op.filter(procImage, null)); bitmap = new BinaryBitmap(new HybridBinarizer(source)); result = reader.decode(bitmap); code = result.getText(); break; } catch (NotFoundException e) { // continue } catch (ChecksumException e) { // continue } catch (FormatException e) { // continue } finally { hints = null; kernelData = null; op = null; source = null; bitmap = null; procImage = null; result = null; } } return code; } protected RenderingHints getRenderingHints() { Map<Key, Object> map = new HashMap<Key, Object>(); map.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); map.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); map.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); RenderingHints hints = new RenderingHints(map); return hints; } protected float[] getKernelData(float data) { return new float[] { data, data, data, data, data, data, data, data, data, data, data, data, data, data, data, data }; } }
Reading QR code within PDF file
import java.awt.image.BufferedImage; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Hashtable; import java.util.Vector; import javax.activation.DataSource; import javax.mail.util.ByteArrayDataSource; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.rendering.ImageType; import org.apache.pdfbox.rendering.PDFRenderer; import com.google.zxing.BarcodeFormat; import com.google.zxing.BinaryBitmap; import com.google.zxing.DecodeHintType; import com.google.zxing.LuminanceSource; import com.google.zxing.MultiFormatReader; import com.google.zxing.NotFoundException; import com.google.zxing.Result; import com.google.zxing.client.j2se.BufferedImageLuminanceSource; import com.google.zxing.common.HybridBinarizer; private String scanQRCode() { // Hints for scanning Vector<BarcodeFormat> decodeFormat = new Vector<BarcodeFormat>(); decodeFormat.add(BarcodeFormat.QR_CODE); Hashtable<DecodeHintType, Object> hintMap = new Hashtable<DecodeHintType, Object>(); hintMap.put(DecodeHintType.TRY_HARDER, true); hintMap.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormat); MultiFormatReader qrcodeReader = new MultiFormatReader(); qrcodeReader.setHints(hintMap); try { // Try lowest DPI first. // BufferedImage pageImage = getPageImage(pageIndex, dpiSettings[i]); BufferedImage pageImage = getPageImage(); LuminanceSource source = new BufferedImageLuminanceSource(pageImage); BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); // By using decodeWithState, we keep the Hints that we set earlier. Result result = qrcodeReader.decodeWithState(bitmap); String text = result.getText(); return text; } catch (IOException e) { e.printStackTrace(); } catch (NotFoundException e) { e.printStackTrace(); } // This should never happen, ever... return null; } private BufferedImage getPageImage() throws IOException { Path docPath = Paths.get("C:\\NS2\\test_files\\java3.pdf"); PDDocument pdfDoc = PDDocument.load(docPath.toFile()); PDFRenderer renderer = new PDFRenderer(pdfDoc); // renderImageWithDPI(page number, image size, format) BufferedImage image = renderer.renderImageWithDPI(0, 150, ImageType.BINARY); // entire page info pdfDoc.close(); return image; }
Scan QR code in PDF
import java.awt.image.BufferedImage; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.EnumMap; import java.util.EnumSet; import java.util.HashMap; import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.Vector; import javax.imageio.ImageIO; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.rendering.ImageType; import org.apache.pdfbox.rendering.PDFRenderer; import com.google.zxing.qrcode.QRCodeReader; import com.google.zxing.BarcodeFormat; import com.google.zxing.BinaryBitmap; import com.google.zxing.DecodeHintType; import com.google.zxing.EncodeHintType; import com.google.zxing.LuminanceSource; import com.google.zxing.MultiFormatReader; import com.google.zxing.MultiFormatWriter; import com.google.zxing.NotFoundException; import com.google.zxing.Result; import com.google.zxing.WriterException; import com.google.zxing.client.j2se.BufferedImageLuminanceSource; import com.google.zxing.client.j2se.MatrixToImageWriter; import com.google.zxing.common.BitMatrix; import com.google.zxing.common.HybridBinarizer; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import com.ns.support.QrPdf; public class My20190205QrCodeTest { private static String path = "C:\\NS2\\test_files\\520044839973-ARV.pdf";// public static void main(String[] args) { My20190205QrCodeTest a = new My20190205QrCodeTest(); try { a.testPdf(); } catch (Exception e) { e.printStackTrace(); } System.out.println("---------------- END ------------------"); } private void testPdf() { try { String line = scanQRCode(1); System.out.println("---------------- test7 result:::" + line); } catch (Exception e) { e.printStackTrace(); } } private String scanQRCode(int pageIndex) { // Hints for scanning Vector<BarcodeFormat> decodeFormat = new Vector<BarcodeFormat>(); decodeFormat.add(BarcodeFormat.QR_CODE); Hashtable<DecodeHintType, Object> hintMap = new Hashtable<DecodeHintType, Object>(); hintMap.put(DecodeHintType.TRY_HARDER, true); hintMap.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormat); MultiFormatReader qrcodeReader = new MultiFormatReader(); qrcodeReader.setHints(hintMap); try { // Try lowest DPI first. BufferedImage pageImage = getPageImage(); LuminanceSource source = new BufferedImageLuminanceSource(pageImage); BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); // By using decodeWithState, we keep the Hints that we set earlier. Result result = qrcodeReader.decodeWithState(bitmap); String text = result.getText(); // System.out.println(" -- text:::" + text); return text; } catch (IOException e) { e.printStackTrace(); } catch (NotFoundException e) { e.printStackTrace(); } // This should never happen, ever... return null; } private BufferedImage getPageImage() throws IOException { Path docPath = Paths.get(path); PDDocument pdfDoc = PDDocument.load(docPath.toFile()); PDFRenderer renderer = new PDFRenderer(pdfDoc); // renderImageWithDPI(page number, image size, format) BufferedImage image = renderer.renderImageWithDPI(0, 150, ImageType.BINARY); // entire page info // BufferedImage image = renderer.renderImage(0); pdfDoc.close(); return image; } }
LISTAGG vs XMLAGG
LISTAGG gives “java.sql.SQLException: ORA-01489: result of string concatenation is too long” due to limitation for VARCHAR2.
select CONCAT(CONCAT(t2.REF_NUM_TYPE,':'), (listagg(t2.REF_NUM,',') within group (order by t2.REF_NUM asc))) as REF_NUMS_BK from ( select max(s.PIPELINE_TX_ID) as PIPELINE_TX_ID, rn.ref_num_type, rn.ref_num from reference_numbers rn, ouk_shipment_activity_cmpny s where 1=1 and rn.pipeline_tx_id = s.pipeline_tx_id and s.PIPELINE_TX_ID = '123132123123' group by rn.ref_num_type, rn.ref_num order by rn.ref_num_type, rn.ref_num ) t2 where 1=1 group by t2.ref_num_type
Therefore, XMLELEMENT can be workaround.
select CONCAT(CONCAT(t2.REF_NUM_TYPE,':'),(RTRIM(XMLAGG(XMLELEMENT(e,t2.REF_NUM,',').EXTRACT('//text()')).GetClobVal(),','))) AS REF_NUMS from ( select max(s.PIPELINE_TX_ID) as PIPELINE_TX_ID, rn.ref_num_type, rn.ref_num from reference_numbers rn, ouk_shipment_activity_cmpny s where 1=1 and rn.pipeline_tx_id = s.pipeline_tx_id and s.PIPELINE_TX_ID = '123132123123' group by rn.ref_num_type, rn.ref_num order by rn.ref_num_type, rn.ref_num ) t2 where 1=1 group by t2.ref_num_type
It can be trim as well.
select CONCAT( CONCAT(t2.REF_NUM_TYPE,':'), SUBSTR( (RTRIM(XMLAGG(XMLELEMENT(e,t2.REF_NUM,',').EXTRACT('//text()')).GetClobVal(),',') ),1,1000 ) ) AS REF_NUMS from ( select max(s.PIPELINE_TX_ID) as PIPELINE_TX_ID, rn.ref_num_type, rn.ref_num from reference_numbers rn, ouk_shipment_activity_cmpny s where 1=1 and rn.pipeline_tx_id = s.pipeline_tx_id and s.PIPELINE_TX_ID = '30277174594' -- 202501494 202498201 30277174594(too long) group by rn.ref_num_type, rn.ref_num order by rn.ref_num_type, rn.ref_num ) t2 where 1=1 group by t2.ref_num_type
Example for XMLAGG with order by
with ref_base as ( select max(a.PIPELINE_TX_ID) as ppl ,a.REF_NUM_TYPE ,a.REF_NUM from REFERENCE_NUMBERS a where 1=1 and a.PIPELINE_TX_ID = '30277174594' group by a.REF_NUM_TYPE, a.REF_NUM order by a.REF_NUM_TYPE, a.REF_NUM ) select ( select RTRIM((XMLAGG(XMLELEMENT(e, b.REF_NUM,',') order by b.REF_NUM).EXTRACT('//text()')).GetClobVal(),',') AS REF_NUMS from ref_base b where b.REF_NUM_TYPE = 'ED1' group by b.REF_NUM_TYPE ) as REF_NUMS_ED1 from dual
Example for LISTAGG with limited elements
select LISTAGG( case when rownum <= 300 then ( case when rownum = 300 then rn.ref_num || ' MORE....' else rn.ref_num end ) else null end, ',' ) within group (order by rn.ref_num) as ref_nums from reference_numbers rn where rn.pipeline_tx_id = '123456'
Import Git project to eclipse
Copy the repository URL
File -> Import -> Git -> Projects from Git
Clone URL, the Next….
Paste the URL, then go ahead next, and next ….
How To Work on GitHub
This used to be my personal memo to work on GitHub (basic operation), but I also thought it’s good to share to others who might have the same (or similar) problem.
Summary:
- Creating Repository
- How to clone the repository
- How to upload your resource
- GitHub website to add a SSH key
- How to generating a SSH key
- How to delete repository
Optimizing SQL
While you are sleeping, there are lots of programs are running based on it’s scheduling. They are often called “Batch Jobs“. And one of batch jobs is to get rid of old transactions.
In Biz apps, we often need to do performance tuning. According to my experience, the SQL is usually the biggest reason to cause a performance issue.
I have a memory that I have a performance issue for this SQL.
This is to get the target records for Data Purge (Oracle):
SELECT * FROM TABLE_TO_BE_PURGED A WHERE EXISTS ( SELECT '*' FROM PURGE_TARGET_TABLE TGT WHERE 1=1 AND TGT.INV_NUM = A.REF_TXT_01 ) OR EXISTS ( SELECT '*' FROM INTEREFACE_TABLE ITFC, PURGE_TARGET_TABLE TGT WHERE ITFC.REF_NUM = B.REF_NUM AND ITFC.REF_SUB_NUM = B.REF_SUB_NUM AND ITFC.INV_NUM = TGT.INV_NUM )
And came up with this after struggling hours…
SELECT * FROM TABLE_TO_BE_PURGED A1 WHERE EXISTS ( SELECT '*' FROM ( SELECT B1.PURGED_PK FROM TABLE_TO_BE_PURGED B1 , PURGE_TARGET_TABLE TGT WHERE 1=1 AND TGT.INV_NUM = B1.REF_TXT_01 UNION SELECT B2.PURGED_PK FROM TABLE_TO_BE_PURGED B2 , INTEREFACE_TABLE ITFC , PURGE_TARGET_TABLE TGT WHERE ITFC.REF_NUM = B2.REF_NUM AND ITFC.REF_SUB_NUM = B2.REF_SUB_NUM AND ITFC.INV_NUM = TGT.INV_NUM ) T1 WHERE T1.PURGED_PK = A1.PURGED_PK )
The performance improved dramatically, but the interesting thing was that the execution plan (cost) was pretty much the same. The one above get slower when having more records. And the one below was fast enough although having many records.