org.jpedal.jbig2.examples.viewer.JBIG2Viewer Maven / Gradle / Ivy
Show all versions of OpenViewerFX Show documentation
/**
* ===========================================
* Java Pdf Extraction Decoding Access Library
* ===========================================
*
* Project Info: http://www.jpedal.org
* (C) Copyright 1997-2008, IDRsolutions and Contributors.
* Main Developer: Simon Barnett
*
* This file is part of JPedal
*
* Copyright (c) 2008, IDRsolutions
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the IDRsolutions nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY IDRsolutions ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL IDRsolutions BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Other JBIG2 image decoding implementations include
* jbig2dec (http://jbig2dec.sourceforge.net/)
* xpdf (http://www.foolabs.com/xpdf/)
*
* The final draft JBIG2 specification can be found at http://www.jpeg.org/public/fcd14492.pdf
*
* All three of the above resources were used in the writing of this software, with methodologies,
* processes and inspiration taken from all three.
*
* ---------------
* JBIG2Viewer.java
* ---------------
*/
package org.jpedal.jbig2.examples.viewer;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.Transparency;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.PixelGrabber;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JToolBar;
import javax.swing.ScrollPaneConstants;
import javax.swing.UIManager;
import org.jpedal.jbig2.JBIG2Decoder;
import org.jpedal.jbig2.JBIG2Exception;
import org.jpedal.jbig2.image.JBIG2Bitmap;
public class JBIG2Viewer extends JFrame {
private JFrame mainFrame = this;
private JScrollPane jsp;
private BufferedImage image;
private JLabel imageLabel = new JLabel();
private JComboBox scalingBox;
private String scalingItem = "";
private double scaling;
private JComboBox rotationBox;
private String rotationItem = "";
private int rotation;
private NavigationToolbar navToolbar;
private JBIG2Decoder decoder;
private int currentPage;
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
new JBIG2Viewer();
} catch (Exception e) {
e.printStackTrace();
}
}
public JBIG2Viewer() {
setSize(500, 500);
getContentPane().setLayout(new BorderLayout());
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(new BorderLayout());
setUpToolbar();
imageLabel.setHorizontalAlignment(JLabel.CENTER);
imageLabel.setVerticalAlignment(JLabel.TOP);
jsp = new JScrollPane(imageLabel);
getContentPane().add(jsp, BorderLayout.CENTER);
navToolbar = new NavigationToolbar(this);
navToolbar.setFloatable(false);
getContentPane().add(navToolbar, BorderLayout.SOUTH);
setTitle("JPedal JBIG2 Image Decoder");
setVisible(true);
}
private void setUpToolbar() {
// Create a horizontal toolbar
JToolBar toolbar = new JToolBar();
toolbar.setFloatable(false);
toolbar.setBorder(BorderFactory.createEtchedBorder());
JButton openButton = new JButton(new AbstractAction("Open", new ImageIcon(getClass().getResource("/org/jpedal/jbig2/examples/viewer/res/open.png"))) {
public void actionPerformed(ActionEvent evt) {
openFile();
}
});
openButton.setText(null);
openButton.setToolTipText("Open New File");
toolbar.add(openButton);
toolbar.add(Box.createRigidArea(new Dimension(7, 0)));
JButton saveButton = new JButton(new AbstractAction("Save", new ImageIcon(getClass().getResource("/org/jpedal/jbig2/examples/viewer/res/save.png"))) {
public void actionPerformed(ActionEvent evt) {
if (image == null) {
JOptionPane.showMessageDialog(mainFrame, "No image is open");
} else {
saveFile();
}
}
});
saveButton.setText(null);
saveButton.setToolTipText("Save File As");
toolbar.add(saveButton);
toolbar.add(Box.createRigidArea(new Dimension(7, 0)));
JButton propertiesButton = new JButton(new AbstractAction("Properties", new ImageIcon(getClass().getResource("/org/jpedal/jbig2/examples/viewer/res/properties.png"))) {
public void actionPerformed(ActionEvent evt) {
// Perform action
}
});
propertiesButton.setText(null);
propertiesButton.setToolTipText("File Properties");
// toolbar.add(propertiesButton);
toolbar.add(Box.createRigidArea(new Dimension(7, 0)));
toolbar.add(new JLabel("Zoom:"));
toolbar.add(Box.createRigidArea(new Dimension(3, 0)));
ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
setScalingAndRotation();
}
};
scalingBox = new JComboBox(new String[]{"Window", "Height", "Width", "25", "50", "75", "100", "125", "150", "200", "250", "500", "750", "1000"});
scalingBox.setEditable(true);
scalingBox.setPreferredSize(new Dimension(scalingBox.getPreferredSize().width, toolbar.getHeight()));
scalingBox.setPrototypeDisplayValue("XXXXXXXX"); // Set a desired
// width
scalingBox.setMaximumSize(new Dimension(100, 100));
toolbar.add(scalingBox);
toolbar.add(Box.createRigidArea(new Dimension(7, 0)));
toolbar.add(new JLabel("Rotation:"));
toolbar.add(Box.createRigidArea(new Dimension(3, 0)));
rotationBox = new JComboBox(new String[]{"0", "90", "180", "270"});
rotationBox.setEditable(true);
rotationBox.setPreferredSize(new Dimension(rotationBox.getPreferredSize().width, toolbar.getHeight()));
rotationBox.setMaximumSize(new Dimension(100, 100));
toolbar.add(rotationBox);
getContentPane().add(toolbar, BorderLayout.NORTH);
rotationBox.addActionListener(actionListener);
scalingBox.addActionListener(actionListener);
}
private void saveFile() {
JFileChooser chooser = new JFileChooser();
chooser.addChoosableFileFilter(new FileFilterer(new String[]{"png"}, "PNG (*.png)"));
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
int approved = chooser.showSaveDialog(null);
if (approved == JFileChooser.APPROVE_OPTION) {
File file = chooser.getSelectedFile();
String fileToSave = file.getAbsolutePath();
if (!fileToSave.toLowerCase().endsWith(".png")) {
file = new File(fileToSave + ".png");
}
try {
ImageIO.write(image, "png", file);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void openFile() {
JFileChooser open = new JFileChooser(".");
open.setFileSelectionMode(JFileChooser.FILES_ONLY);
String[] png = new String[]{"jb2", "jbig2"};
open.addChoosableFileFilter(new FileFilterer(png, "JBIG2 (jb2, jbig2)"));
int resultOfFileSelect = open.showOpenDialog(mainFrame);
if (resultOfFileSelect == JFileChooser.APPROVE_OPTION) {
/** reset rotation */
rotation = 0;
rotationItem = "0";
rotationBox.setSelectedItem(rotationItem);
/** reset scaling */
scaling = 1;
scalingItem = "Window";
scalingBox.setSelectedItem(scalingItem);
decoder = new JBIG2Decoder();
try {
decoder.decodeJBIG2(open.getSelectedFile());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JBIG2Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// navToolbar.open();
navToolbar.setCurrentPage(1);
navToolbar.setTotalNoOfPages(decoder.getNumberOfPages());
currentPage = 1;
image = decoder.getPageAsBufferedImage(currentPage - 1);
setScalingAndRotation();
}
}
private void setScalingAndRotation() {
if (image == null)
return;
String selectedScaling = (String) scalingBox.getSelectedItem();
if (selectedScaling.equals("Window")) {
int windowWidth = jsp.getWidth();
int windowHeight = jsp.getHeight();
int imageWidth = image.getWidth();
int imageHeight = image.getHeight();
if (windowWidth / (double) imageWidth < windowHeight / (double) imageHeight) { // scale by width
scaleToWidth();
} else { // scale by height
scaleToHeight();
}
jsp.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
jsp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
} else {
jsp.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
jsp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
if (selectedScaling.equals("Height")) {
scaleToHeight();
} else if (selectedScaling.equals("Width")) {
scaleToWidth();
} else { // this might be an int
try {
int scale = Integer.parseInt(selectedScaling);
this.scaling = scale / (double) 100;
} catch (NumberFormatException e) { // not a number
e.printStackTrace();
scalingBox.setSelectedItem(scalingItem);
return;
}
}
}
String selectedRotation = (String) rotationBox.getSelectedItem();
try {
this.rotation = Integer.parseInt(selectedRotation);
} catch (NumberFormatException e) { // not a number
e.printStackTrace();
rotationBox.setSelectedItem(rotationItem);
return;
}
Image scaledImage = image.getScaledInstance((int) (image.getWidth() * scaling), -1, Image.SCALE_DEFAULT);
BufferedImage rotatedImage = rotate(toBufferedImage(scaledImage), rotation * Math.PI / 180);
imageLabel.setIcon(new ImageIcon(rotatedImage));
scalingItem = (String) scalingBox.getSelectedItem();
}
private void setRotation() {
String selectedRotation = (String) rotationBox.getSelectedItem();
try {
this.rotation = Integer.parseInt(selectedRotation);
} catch (NumberFormatException e) { // not a number
e.printStackTrace();
rotationBox.setSelectedItem(rotationItem);
return;
}
Image rotatedImage = rotate(image, rotation * Math.PI / 180);
imageLabel.setIcon(new ImageIcon(rotatedImage));
rotationItem = (String) rotationBox.getSelectedItem();
}
private void scaleToWidth() {
if (image == null)
return;
scaling = (jsp.getWidth()) / (double) image.getWidth();
}
private void scaleToHeight() {
if (image == null)
return;
scaling = (jsp.getHeight()) / (double) image.getHeight();
}
private static BufferedImage rotate(BufferedImage src, double angle) {
if (src == null)
return null;
int w = src.getWidth();
int h = src.getHeight();
int newW = (int) (Math.round(h * Math.abs(Math.sin(angle)) + w * Math.abs(Math.cos(angle))));
int newH = (int) (Math.round(h * Math.abs(Math.cos(angle)) + w * Math.abs(Math.sin(angle))));
AffineTransform at = AffineTransform.getTranslateInstance((newW - w) / 2, (newH - h) / 2);
at.rotate(angle, w / 2, h / 2);
BufferedImage dst = new BufferedImage(newW, newH, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = dst.createGraphics();
g.drawRenderedImage(src, at);
g.dispose();
return dst;
}
private static boolean hasAlpha(Image image) {
// If buffered image, the color model is readily available
if (image instanceof BufferedImage) {
BufferedImage bimage = (BufferedImage) image;
return bimage.getColorModel().hasAlpha();
}
// Use a pixel grabber to retrieve the image's color model;
// grabbing a single pixel is usually sufficient
PixelGrabber pg = new PixelGrabber(image, 0, 0, 1, 1, false);
try {
pg.grabPixels();
} catch (InterruptedException e) {
e.printStackTrace();
}
// Get the image's color model
ColorModel cm = pg.getColorModel();
return cm.hasAlpha();
}
private BufferedImage toBufferedImage(Image image) {
if (image instanceof BufferedImage) {
return (BufferedImage) image;
}
// This code ensures that all the pixels in the image are loaded
image = new ImageIcon(image).getImage();
// Determine if the image has transparent pixels; for this method's
// implementation, see e661 Determining If an Image Has Transparent
// Pixels
boolean hasAlpha = hasAlpha(image);
// Create a buffered image with a format that's compatible with the
// screen
BufferedImage bimage = null;
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
try {
// Determine the type of transparency of the new buffered image
int transparency = Transparency.OPAQUE;
if (hasAlpha) {
transparency = Transparency.BITMASK;
}
// Create the buffered image
GraphicsDevice gs = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gs.getDefaultConfiguration();
bimage = gc.createCompatibleImage(image.getWidth(null), image.getHeight(null), transparency);
} catch (HeadlessException e) {
// The system does not have a screen
}
if (bimage == null) {
// Create a buffered image using the default color model
int type = BufferedImage.TYPE_INT_RGB;
if (hasAlpha) {
type = BufferedImage.TYPE_INT_ARGB;
}
bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
}
// Copy image to buffered image
Graphics g = bimage.createGraphics();
// Paint the image onto the buffered image
g.drawImage(image, 0, 0, null);
g.dispose();
return bimage;
}
public static void displayJBIG2AsImage(JBIG2Bitmap bitmap) {
byte[] bytes = bitmap.getData(true);
if (bytes == null)
return;
// make a a DEEP copy so we cant alter
int len = bytes.length;
byte[] copy = new byte[len];
System.arraycopy(bytes, 0, copy, 0, len);
int width = bitmap.getWidth();
int height = bitmap.getHeight();
/** create an image from the raw data */
DataBuffer db = new DataBufferByte(copy, copy.length);
WritableRaster raster = Raster.createPackedRaster(db, width, height, 1, null);
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY);
image.setData(raster);
Image scaledImage = image.getScaledInstance(500, -1, Image.SCALE_AREA_AVERAGING);
BufferedImage result = new BufferedImage(scaledImage.getWidth(null), scaledImage.getHeight(null), BufferedImage.TYPE_INT_BGR);
Graphics2D g = result.createGraphics();
g.drawImage(scaledImage, 0, 0, null);
g.dispose();
JLabel label = new JLabel(new ImageIcon(result));
JOptionPane.showConfirmDialog(null, label, "JBIG2 Display", JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE);
}
public JBIG2Decoder getDecoder() {
return decoder;
}
public void displayPage(int page) {
if (image != null && page > 0 && page <= decoder.getNumberOfPages()) {
image = decoder.getPageAsBufferedImage(page - 1);
currentPage = page;
setScalingAndRotation();
navToolbar.setCurrentPage(currentPage);
}
}
public int getCurrentPage() {
return currentPage;
}
}