Package jexifviewer

Source Code of jexifviewer.JImgView

/*
*  JImgView.java
*
*  Created on 17. April 2006, 11:36
*
*  Copyright (C) 17. April 2006  <Reiner>

*  This program is free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software
*  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
*/


package jexifviewer;

import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.JViewport;
import javax.swing.KeyStroke;
import javax.swing.RepaintManager;
import javax.swing.SwingUtilities;

import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.Rectangle2D;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.Rectangle;
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.io.RandomAccessFile;
import java.io.File;

import javax.imageio.ImageIO;


import java.util.ArrayList;
import java.util.Iterator;
import javax.imageio.IIOImage;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import javax.imageio.stream.FileImageOutputStream;
import shared.cvshelper.Cvs;


/**
*
* @author reiner
*/

@Cvs
(
    header = "$Header: /home/reiner/cvs/Java/JExifViewer/src/jexifviewer/JImgView.java,v 1.8 2010/04/02 12:12:13 reiner Exp $"
)
public final class JImgView extends JComponent implements Printable
{
    protected BufferedImage m_img;
    private JIfdData m_ifd;
    private int m_orientation = 0;
    private float m_zoom = 0.0f;
    private boolean m_bZoomDirty = false;
   
    private JImageCache m_imgCache;
   
    private Point m_moveStartPoint;
    private boolean m_bMove = false;
    private boolean m_bMoveOutSide = false;
   
    private Point m_viewPos;
   
    private boolean m_bPreloadDirty = false;
  
  
    /** Creates a new instance of JImgView */
    public JImgView(int cacheSize)
    {
        m_imgCache = new JImageCache(cacheSize, Main.m_settings.getCallGcAfterCacheOp());

        // Keyboard action on the image viewer

        // full / normal view
        getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "esc");
        getActionMap().put("esc", new AbstractAction()
        {
            public void actionPerformed(ActionEvent event)
            {
                Main.m_mainFrame.toggleView();
            }
        })

        // Zoom in / out
        getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ADD, InputEvent.CTRL_DOWN_MASK), "ctrl_+");
        getActionMap().put("ctrl_+", new AbstractAction()
        {
            public void actionPerformed(ActionEvent event)
            {
                setZoomUp();
            }
        });
        getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_SUBTRACT, InputEvent.CTRL_DOWN_MASK), "ctrl_-");
        getActionMap().put("ctrl_-", new AbstractAction()
        {
            public void actionPerformed(ActionEvent event)
            {
                setZoomDown();
            }
        })
        // fit
        getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.CTRL_DOWN_MASK), "ctrl_enter");
        getActionMap().put("ctrl_enter", new AbstractAction()
        {
            public void actionPerformed(ActionEvent event)
            {
                resetZoom();
            }
        });

        // 100%
        getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_MULTIPLY, InputEvent.CTRL_DOWN_MASK), "ctrl_100%");
        getActionMap().put("ctrl_100%", new AbstractAction()
        {
            public void actionPerformed(ActionEvent event)
            {
                setZoom(1.0f);
            }
        });

        // 50%
        getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_DIVIDE, InputEvent.CTRL_DOWN_MASK), "ctrl_50%");
        getActionMap().put("ctrl_50%", new AbstractAction()
        {
            public void actionPerformed(ActionEvent event)
            {
                setZoom(.5f);
            }
        });

        // Scrolling
        getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_NUMPAD2, 0), "ctrl_scrolldown");
        getActionMap().put("ctrl_scrolldown", new AbstractAction()
        {
            public void actionPerformed(ActionEvent event)
            {
                if (m_zoom != 0.0f)
                    scrollImg(0, Main.m_settings.getImgScrollDelta());
            }
        });

        getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_NUMPAD8, 0), "ctrl_scrollup");
        getActionMap().put("ctrl_scrollup", new AbstractAction()
        {
            public void actionPerformed(ActionEvent event)
            {
                if (m_zoom != 0.0f)
                    scrollImg(0, -Main.m_settings.getImgScrollDelta());
            }
        });

        getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_NUMPAD4, 0), "ctrl_scrollleft");
        getActionMap().put("ctrl_scrollleft", new AbstractAction()
        {
            public void actionPerformed(ActionEvent event)
            {
                if (m_zoom != 0.0f)
                    scrollImg(-Main.m_settings.getImgScrollDelta(), 0);
            }
        });

        getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_NUMPAD6, 0), "ctrl_scrollright");
        getActionMap().put("ctrl_scrollright", new AbstractAction()
        {
            public void actionPerformed(ActionEvent event)
            {
                if (m_zoom != 0.0f)
                    scrollImg(Main.m_settings.getImgScrollDelta(), 0);
            }
        });

        // diagonal
        getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_NUMPAD7, 0), "ctrl_scrollupleft");
        getActionMap().put("ctrl_scrollupleft", new AbstractAction()
        {
            public void actionPerformed(ActionEvent event)
            {
                if (m_zoom != 0.0f)
                    scrollImg(-Main.m_settings.getImgScrollDelta(), -Main.m_settings.getImgScrollDelta());
            }
        });

        getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_NUMPAD9, 0), "ctrl_scrollupright");
        getActionMap().put("ctrl_scrollupright", new AbstractAction()
        {
            public void actionPerformed(ActionEvent event)
            {
                if (m_zoom != 0.0f)
                    scrollImg(Main.m_settings.getImgScrollDelta(), -Main.m_settings.getImgScrollDelta());
            }
        });

        getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_NUMPAD1, 0), "ctrl_scrolldownleft");
        getActionMap().put("ctrl_scrolldownleft", new AbstractAction()
        {
            public void actionPerformed(ActionEvent event)
            {
                if (m_zoom != 0.0f)
                    scrollImg(-Main.m_settings.getImgScrollDelta(), Main.m_settings.getImgScrollDelta());
            }
        });

        getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_NUMPAD3, 0), "ctrl_scrolldownright");
        getActionMap().put("ctrl_scrolldownright", new AbstractAction()
        {
            public void actionPerformed(ActionEvent event)
            {
                if (m_zoom != 0.0f)
                    scrollImg(Main.m_settings.getImgScrollDelta(), Main.m_settings.getImgScrollDelta());
            }
        });

        // special
        getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_NUMPAD5, 0), "ctrl_scrollcenter");
        getActionMap().put("ctrl_scrollcenter", new AbstractAction()
        {
            public void actionPerformed(ActionEvent event)
            {
                if (m_zoom != 0.0f)
                {
                    Dimension size = getSize();
                    JViewport viewPort = (JViewport)getParent();
                    assert viewPort != null;
                    Dimension dimView = viewPort.getExtentSize();
                    setViewPosition(new Point((int)(size.width/2 - dimView.width/2), (int)(size.height/2 - dimView.height)));
                }
            }
        });

        getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_NUMPAD0, 0), "ctrl_scrollhome");
        getActionMap().put("ctrl_scrollhome", new AbstractAction()
        {
            public void actionPerformed(ActionEvent event)
            {
                if (m_zoom != 0.0f)
                    setViewPosition(new Point(0, 0));
            }
        });

        getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_DECIMAL, 0), "ctrl_scrollend");
        getActionMap().put("ctrl_scrollend", new AbstractAction()
        {
            public void actionPerformed(ActionEvent event)
            {
                if (m_zoom != 0.0f)
                {
                    Dimension size = getSize();
                    setViewPosition(new Point((int)size.width, (int)size.height));
                }
            }
        });

        // Mouse
        addMouseListener(new MouseAdapter()
        {
            public void mousePressed(MouseEvent ev)
            {
                if (getZoom() != 0.0f)
                {
                    m_moveStartPoint = ev.getPoint();
                    setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
                    m_bMoveOutSide = false;
                    m_bMove = true;
                }
            }

            public void mouseReleased(MouseEvent ev)
            {
                if (m_bMove)
                {
                    setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                    m_bMove = false;
                }
            }

            public void mouseExited(MouseEvent ev)
            {
                if (m_bMove)
                {
                    setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                    m_bMoveOutSide = true;
                }
            }

            public void mouseEntered(MouseEvent ev)
            {
                if (m_bMove)
                {
                    if (m_bMoveOutSide)
                    {
                        setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
                        m_bMoveOutSide = false;
                    }
                }
            }
        });
        addMouseMotionListener(new MouseMotionAdapter()
        {
            public void mouseDragged(MouseEvent ev)
            {
                if (m_bMove && !m_bMoveOutSide)
                {
                    JViewport viewPort = (JViewport)getParent();
                    assert viewPort != null;
                    Rectangle rect = viewPort.getViewRect();
                    if (rect.contains(ev.getPoint()))
                    {
                        Point pt = new Point(viewPort.getViewPosition());
                        pt.translate(m_moveStartPoint.x - ev.getPoint().x, m_moveStartPoint.y - ev.getPoint().y);
                        setViewPosition(pt);
                    }
                }
            }
        });
    }
   
    private void scrollImg(int dx, int dy)
    {
        JViewport viewPort = (JViewport)getParent();
        assert viewPort != null;
        Point pt = new Point(viewPort.getViewPosition());
        pt.translate(dx, dy);
        setViewPosition(pt);
    }
   
    private boolean doSetViewPosition(Point _pt, boolean bForceSet)
    {
        boolean flag = true;
        JViewport viewPort = (JViewport)getParent();
        assert viewPort != null;
        Point pt = new Point(_pt);
        if (pt.x < 0) pt.x = 0;
        if (pt.y < 0 ) pt.y = 0;

        Dimension dimCtrl = getSize();
        Dimension dimView = viewPort.getExtentSize();
        if (pt.x > dimCtrl.width - dimView.width)
        {
            pt.x = dimCtrl.width - dimView.width;
            flag = false;
        }
        if (pt.y > dimCtrl.height - dimView.height)
        {
            pt.y = dimCtrl.height - dimView.height;
            flag = false;
        }
        if (flag || bForceSet)
            viewPort.setViewPosition(pt);
        return flag;
    }

    private void setViewPosition(Point pt)
    {
      doSetViewPosition(pt, true);
    }

    private boolean setViewPosition(Point pt, boolean bForce)
    {
        return doSetViewPosition(pt, bForce);
    }
 
    public void setZoomDown()
    {
      setZoom(getRealZoom() - Main.m_settings.getZoomDelta());
    }

    public void setZoomUp()
    {
        setZoom(getRealZoom() + Main.m_settings.getZoomDelta());
    }
   
    /**
     * must be called after the zoom is done !
     */
    private void adjustViewPosByZoom(float oldZoom)
    {
        float zoom = getRealZoom();
        float zoomDelta = zoom - oldZoom;
        final JViewport viewPort = (JViewport)getParent();
        assert viewPort != null;
        Dimension dimView = viewPort.getExtentSize();
        m_viewPos = viewPort.getViewPosition();
        m_viewPos.translate(Math.round((m_viewPos.x + (float)dimView.width/2.0f)*zoomDelta/oldZoom), Math.round((m_viewPos.y + (float)dimView.height/2.0f)*zoomDelta/oldZoom));
        if (!setViewPosition(m_viewPos, false))
        {
            SwingUtilities.invokeLater(new Runnable()
            {
                public void run()
                {
                    setViewPosition(m_viewPos);
                }
            });
        }
    }
   
    public void resetZoom()
    {
        m_zoom = 0.0f;
        m_bZoomDirty = true;
        internalSetZoom();
        repaint();
        if (Main.m_settings.isDebug())
            System.err.println("Reset zoom");
    }
   
    public void setZoom(float zoom)
    {
        if (zoom > 0.01 && zoom <= 8.0f)
        {
            final float oldZoom = getRealZoom();
            m_zoom = zoom;
            m_bZoomDirty = true;
            internalSetZoom();
            repaint();
            if (Main.m_settings.isDebug())
                System.err.println("Zoom: " + m_zoom);
            adjustViewPosByZoom(oldZoom);
        }
    }
   
    public float getZoom()
    {
      return m_zoom;
    }

    public float getRealZoom()
    {
        float zoom = m_zoom;
        if (m_zoom == 0.0f)
        {
            if (m_img != null)
            {
                Dimension dim = getSize();
                int w = m_img.getWidth();
                int h = m_img.getHeight();
                double dx, dy;
                switch(getOrientation())
                {
                    case 1: // 0�
                        dx = (double)dim.width / (double)w;
                        dy = (double)dim.height / (double)h;
                        zoom = (float)Math.min(dx, dy);
                        break;
                    case 2: // <->
                        dx = (double)dim.width / (double)w;
                        dy = (double)dim.height / (double)h;
                        zoom = (float)Math.min(dx, dy);
                        break;
                    case 3: // 180�
                        dx = (double)dim.width / (double)w;
                        dy = (double)dim.height / (double)h;
                        zoom = (float)Math.min(dx, dy);
                       break;
                    case 4: // 180� + <->
                        dx = (double)dim.width / (double)w;
                        dy = (double)dim.height / (double)h;
                        zoom = (float)Math.min(dx, dy);
                       break;
                    case 5: // -90� + <->
                        dx = (double)dim.width / (double)h;
                        dy = (double)dim.height / (double)w;
                        zoom = (float)Math.min(dx, dy);
                        break;
                    case 6: // -90�
                        dx = (double)dim.width / (double)h;
                        dy = (double)dim.height / (double)w;
                        zoom = (float)Math.min(dx, dy);
                        break;
                    case 7: // 90� + <->
                        dx = (double)dim.width / (double)h;
                        dy = (double)dim.height / (double)w;
                        zoom = (float)Math.min(dx, dy);
                        break;
                    case 8: // 90�
                        dx = (double)dim.width / (double)h;
                        dy = (double)dim.height / (double)w;
                        zoom = (float)Math.min(dx, dy);
                        break;
                }
            }
        }
        return zoom;
    }

    private void internalSetZoom()
    {
        if (m_img != null)
        {
            int w = m_img.getWidth();
            int h = m_img.getHeight();
            if (w >= 0 && h>= 0)
            {
                Dimension dim;
                if (m_zoom == 0.0f)
                    setPreferredSize(dim = new Dimension(1, 1));
                else setPreferredSize(dim = new Dimension((int)(w*m_zoom), (int)(h*m_zoom)));
                m_bZoomDirty = false;
                revalidate();

                // getSize will not say the actual size if we call it now
                SwingUtilities.invokeLater(new Runnable()
                {
                    public void run()
                    {
                    Main.m_mainFrame.updateTitle(m_ifd);
                    }
                });
            }
        }
    }
   
    static public int getNextOrientation(int orientation, boolean bUp)
    {
        switch(orientation)
        {
            case 1:
                orientation = bUp ? 6 : 8;
                break;
            case 2:
                orientation = bUp ? 7 : 5;
                break;
            case 3:
                orientation = bUp ? 8 : 6;
                break;
            case 4:
                orientation = bUp ? 5 : 7;
                break;
            case 5:
                orientation = bUp ? 2 : 4;
                break;
            case 6:
                orientation = bUp ? 3 : 1;
                break;
            case 7:
                orientation = bUp ? 4 : 2;
                break;
            case 8:
                orientation = bUp ? 1 : 3;
                break;
        }
        return orientation;
    }
   
    static public int getNextFlipOrientation(int orientation)
    {
        switch(orientation)
        {
            case 1:
                orientation = 2;
                break;
            case 2:
                orientation = 1;
                break;
            case 3:
                orientation = 4;
                break;
            case 4:
                orientation = 3;
                break;
            case 5:
                orientation = 6;
                break;
            case 6:
                orientation = 5;
                break;
            case 7:
                orientation = 8;
                break;
            case 8:
                orientation = 7;
                break;
        }
        return orientation;
    }

    public boolean isImage()
    {
        return m_img != null;
    }
   
    public JIfdData getIfdData()
    {
        return m_ifd;
    }
   
    protected int getOrientation(JIfdData ifd)
    {
        if (ifd != null)
        {
            int orientation = ifd.getOrientation();
            if (orientation <= 0 || orientation > 8) orientation = 1;
            return orientation;
        }
        return 0;
    }

    public int getOrientation()
    {
        return  (m_orientation == 0 ? getOrientation(m_ifd) : m_orientation);
    }

    public int getCustomOrientation()
    {
      return m_orientation;
    }

    public void setOrientation(int orientation)
    {
        m_orientation = orientation;
        repaint();
    }
   
    public void clearCache()
    {
      m_imgCache.clear();
    }

    public void removeFromCache(String file)
    {
        m_imgCache.remove(file);
    }
   
    public void preloadImg(final JIfdData ifd)
    {
        if (ifd != null)
        {
            if (m_imgCache.get(ifd.getFilePath()) == null)
            {
                Thread th = new Thread()
                {
                    public void run()
                    {
                        try
                        {
                            final BufferedImage img = ImageIO.read(new File(ifd.getFilePath()));
                            SwingUtilities.invokeLater(new Runnable()
                            {
                                public void run()
                                {
                                    m_imgCache.add(new JImageData(ifd.getFilePath(), img));
                                    Main.m_mainFrame.doPreload();
                                }
                            });
                        }
                        catch (Exception ex)
                        {
                        }
                    }
                };
                if (Main.m_settings.isDebug())
                    System.err.println("Preload: " + ifd.getFilePath());
                th.start();
            }
        }
    }
   
    public void setJpg(JIfdData ifd)
    {
        if (Main.m_settings.getSaveImage() != 0 && m_orientation != 0 && m_ifd != null && m_ifd.getOrientation() != m_orientation)
        {
            if (Main.m_settings.getSaveImage() == 1 || (Main.m_settings.getSaveImage() == 2 && JOptionPane.showConfirmDialog(Main.m_mainFrame, String.format(Main.getString("img_saveorientation_ask"), m_ifd.getFilePath()), Main.getMessageBoxCaption(), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION))
            {
                saveOrientation(false);
            }
        }
        if (ifd  == null)
        {
            m_ifd = null;
            m_img = null;
            m_orientation = 0;
            m_bPreloadDirty = false;
        }
        else if (m_ifd == null || !ifd.getFilePath().equals(m_ifd.getFilePath()))
        {
            m_bZoomDirty = true;
            m_ifd = ifd;

            JImageData data = m_imgCache.get(m_ifd.getFilePath());
            if (data != null)
                m_img = data.getImage();
            else
            {
                try
                {
                    m_img = ImageIO.read(new File(ifd.getFilePath()));
                    m_imgCache.add(new JImageData(m_ifd.getFilePath(), m_img));
                }
                catch(IOException ex)
                {}
            }
            m_img.setAccelerationPriority(0.85f);
            m_orientation = 0;
            m_bPreloadDirty = true;
        }
        repaint();
        if (Main.m_settings.getCallGcInSetJpg())
            System.gc();
        if (Main.m_settings.isDebug())
            System.err.println("Memory: (total, free, max): " + Runtime.getRuntime().totalMemory() + ", " + Runtime.getRuntime().freeMemory() + ", " + Runtime.getRuntime().maxMemory());
    }

    public int print(Graphics pg, PageFormat pageFormat, int pageIndex)
    {
        if (pageIndex == 0)
        {
            pg.translate((int)pageFormat.getImageableX(), (int)pageFormat.getImageableY());
            RepaintManager currentManager = RepaintManager.currentManager(this);
            currentManager.setDoubleBufferingEnabled(false);
            Graphics2D g2d = (Graphics2D)pg;
            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
            doPaint(pg, new Dimension((int)pageFormat.getImageableWidth(), (int)pageFormat.getImageableHeight()), true);
            currentManager.setDoubleBufferingEnabled(true);
            System.gc();
            return PAGE_EXISTS;
        }
        else return NO_SUCH_PAGE;
    }
   
    public void paintComponent(Graphics g)
    {
        Graphics gd = g.create();
        if (m_bZoomDirty) internalSetZoom();
        if (doPaint(gd, m_zoom == 0.0f ? getSize() : getPreferredSize(), false))
        {
            if (m_bPreloadDirty)
            {
                m_bPreloadDirty = false;
                Main.m_mainFrame.doPreload();
            }
        }
    }

    protected void doScaleRotate(BufferedImage img, JIfdData ifd, Graphics g, Dimension dim)
    {
        Graphics2D g2d = (Graphics2D)g;
        double dx=0, dy=0, d = 0;
        int xOffset = 0;
        int yOffset = 0;
        int w = img.getWidth(null);
        int h = img.getHeight(null);

        switch(ifd != null ? getOrientation(ifd) : getOrientation())
        {
            case 1: // 0�
                dx = (double)dim.width / (double)w;
                dy = (double)dim.height / (double)h;
                d = Math.min(dx, dy);
                g2d.scale(d, d);
                if ((int)(w*d + .5) < dim.width)
                    xOffset = (int)((dim.width - w*d)/(2.0*d) + 0.5);
                if ((int)(h*d + .5) < dim.height)
                    yOffset = (int)((dim.height - h*d)/(2.0*d) + 0.5);
                g2d.translate(xOffset, yOffset);
                break;
            case 2: // <->
                dx = (double)dim.width / (double)w;
                dy = (double)dim.height / (double)h;
                d = Math.min(dx, dy);
                g2d.translate(w*d, 0);
                g2d.scale(-d, d);
                if ((int)(w*d + .5) < dim.width)
                    xOffset = (int)((dim.width - w*d)/(2.0*d) + 0.5);
                if ((int)(h*d + .5) < dim.height)
                    yOffset = (int)((dim.height - h*d)/(2.0*d) + 0.5);
                g2d.translate(-xOffset, yOffset);
                break;
            case 3: // 180�
                dx = (double)dim.width / (double)w;
                dy = (double)dim.height / (double)h;
                d = Math.min(dx, dy);
                g2d.rotate(Math.PI);
                g2d.translate(-w*d, -h*d);
                g2d.scale(d, d);
                if ((int)(w*d + .5) < dim.width)
                    xOffset = (int)((dim.width - w*d)/(2.0*d) + 0.5);
                if ((int)(h*d + .5) < dim.height)
                    yOffset = (int)((dim.height - h*d)/(2.0*d) + 0.5);
                g2d.translate(-xOffset, -yOffset);
               break;
            case 4: // 180� + <->
                dx = (double)dim.width / (double)w;
                dy = (double)dim.height / (double)h;
                d = Math.min(dx, dy);
                g2d.rotate(Math.PI);
                g2d.translate(0, -h*d);
                g2d.scale(-d, d);
                if ((int)(w*d + .5) < dim.width)
                    xOffset = (int)((dim.width - w*d)/(2.0*d) + 0.5);
                if ((int)(h*d + .5) < dim.height)
                    yOffset = (int)((dim.height - h*d)/(2.0*d) + 0.5);
                g2d.translate(xOffset, -yOffset);
               break;
            case 5: // -90� + <->
                dx = (double)dim.width / (double)h;
                dy = (double)dim.height / (double)w;
                d = Math.min(dx, dy);
                g2d.rotate(Math.PI/2);
                g2d.scale(d, -d);
                if ((int)(h*d + .5) < dim.width)
                    xOffset = (int)((dim.width - h*d)/(2.0*d) + 0.5);
                if ((int)(w*d + .5) < dim.height)
                    yOffset = (int)((dim.height - w*d)/(2.0*d) + 0.5);
                g2d.translate(yOffset, xOffset);
                break;
            case 6: // -90�
                dx = (double)dim.width / (double)h;
                dy = (double)dim.height / (double)w;
                d = Math.min(dx, dy);
                g2d.rotate(Math.PI/2);
                g2d.translate(0, -h*d);
                g2d.scale(d, d);
                if ((int)(h*d + .5) < dim.width)
                    xOffset = (int)((dim.width - h*d)/(2.0*d) + 0.5);
                if ((int)(w*d + .5) < dim.height)
                    yOffset = (int)((dim.height - w*d)/(2.0*d) + 0.5);
                g2d.translate(yOffset, -xOffset);
                break;
            case 7: // 90� + <->
                dx = (double)dim.width / (double)h;
                dy = (double)dim.height / (double)w;
                d = Math.min(dx, dy);
                g2d.rotate(-Math.PI/2);
                g2d.translate(-w*d, h*d);
                g2d.scale(d, -d);
                if ((int)(h*d + .5) < dim.width)
                    xOffset = (int)((dim.width - h*d)/(2.0*d) + 0.5);
                if ((int)(w*d + .5) < dim.height)
                    yOffset = (int)((dim.height - w*d)/(2.0*d) + 0.5);
                g2d.translate(-yOffset, -xOffset);
                break;
            case 8: // 90�
                dx = (double)dim.width / (double)h;
                dy = (double)dim.height / (double)w;
                d = Math.min(dx, dy);
                g2d.rotate(-Math.PI/2);
                g2d.translate(-w*d, 0);
                g2d.scale(d, d);
                if ((int)(h*d + .5) < dim.width)
                    xOffset = (int)((dim.width - h*d)/(2.0*d) + 0.5);
                if ((int)(w*d + .5) < dim.height)
                    yOffset = (int)((dim.height - w*d)/(2.0*d) + 0.5);
                g2d.translate(yOffset, xOffset);
                break;
        }
    }
   
    public boolean doPaint(Graphics g, Dimension dim, boolean bPrint)
    {
        if (m_ifd != null && m_img != null)
        {
            double dx=0, dy=0, d = 0;
            Graphics2D g2d = (Graphics2D)g;
            int w = m_img.getWidth();
            int h = m_img.getHeight();
            if (dim == null) dim = new Dimension(w, h);

            if (h > 0 && w > 0)
            {
                doScaleRotate(m_img, null, g, dim);
                g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, Main.m_settings.getInterpolation());
                Rectangle rect = g2d.getClipBounds();
                if (rect == null)
                    rect = new Rectangle(0, 0, dim.width, dim.height);
                if (!bPrint)
                {
                    g2d.setColor(Main.m_settings.getImgViewBackColor());
                    g2d.fillRect((int)rect.getX(), (int)rect.getY(), (int)rect.getWidth(), (int)rect.getHeight());
                }
                g2d.drawImage(m_img, rect.x, rect.y, rect.x + rect.width, rect.y + rect.height, rect.x, rect.y, rect.x + rect.width, rect.y + rect.height, this);
                return true;
            }
            else
            {
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                JViewport viewPort = (JViewport)getParent();
                assert (viewPort != null);

                Point pt = viewPort.getViewPosition();
                dim = viewPort.getExtentSize();
                String str = Main.getString("img_wait");
                Rectangle2D rect = g2d.getFontMetrics().getStringBounds(str, g2d);
                g2d.drawString(str, (int)pt.getX() + (int)((dim.getWidth() - rect.getWidth())/2), (int)pt.getY() + (int)((dim.getHeight() + rect.getHeight())/2));
                if (Main.m_settings.isDebug())
                    System.err.println("no image !");
                repaint(250);
            }
        }
        return false;
    }
   
    public boolean saveOrientation(boolean bReload)
    {
        boolean flag = false;
        if (m_ifd != null && m_orientation != 0)
        {
            RandomAccessFile file = null;
            try
            {
                file = new RandomAccessFile(m_ifd.getFilePath(), "rw");
                flag = m_ifd.updateTag(file, JExifTag.EXIFTAG_TAG_ORIENTATION, m_orientation);
            }
            catch(IOException ex)
            {}
            finally
            {
                try
                {
                    if (file != null) file.close();
                }
                catch (IOException ex)
                {}
            }
        }
        if (flag)
        {
            if (bReload)
            {
                if (m_ifd.readFromFile(m_ifd.getFilePath()))
                {
                    m_orientation = 0;
                    setJpg(m_ifd);
                }
            }
            Main.m_mainFrame.updateTableItem(m_ifd);
        }
        else JOptionPane.showMessageDialog(Main.m_mainFrame, String.format(Main.getString("img_saveorientation_failed"), m_ifd.getFilePath()), Main.getMessageBoxCaption(), JOptionPane.ERROR_MESSAGE);
        return flag;
    }

    public boolean export()
    {
        boolean flag = false;
        if (m_img != null)
        {
            JExportDialog dia = new JExportDialog(Main.m_mainFrame, this);
            dia.m_quality = Main.m_settings.getExportQuality();
            dia.m_scaleFactor = Main.m_settings.getExportScaleFactor();
            dia.m_bOptimizedHuf = Main.m_settings.isExportJpegOptimizedHufTable();
            dia.m_mimeType = Main.m_settings.getExportMimeType();
            dia.m_file = new File(m_ifd.getFilePath());
            if (dia.doModal())
            {
                Main.m_mainFrame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

                Main.m_settings.setExportQuality((float)dia.m_quality);
                Main.m_settings.setExportScalefactor((float)dia.m_scaleFactor);
                Main.m_settings.setExportJpegOptimizedHufTable(dia.m_bOptimizedHuf);
                Main.m_settings.setExportMimeType(dia.m_mimeType);

                if (dia.m_mimeType.equals("image/png"))
                    flag = savePNG(dia.m_file, m_img, null, dia.m_scaleFactor);
                else if (dia.m_mimeType.equals("image/jpeg"))
                    flag = saveJPG(dia.m_file, m_img, null, dia.m_scaleFactor, dia.m_quality, dia.m_bOptimizedHuf);
                else if (dia.m_mimeType.equals("image/bmp"))
                    flag = saveBMP(dia.m_file, m_img, null, dia.m_scaleFactor);

                Main.m_mainFrame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
            }
        }
        return flag;
    }

    protected boolean saveJPG(File file, BufferedImage img, JIfdData ifd, double scaleFactor, double quality, boolean bOptimizedHuffman)
    {
        boolean flag = false;
        if (img != null)
        {
            FileImageOutputStream fios = null;
            try
            {
                if (file.exists())
                    file.delete();
                BufferedImage bi = getBufferedImage(img, ifd, scaleFactor);
                Iterator iter = ImageIO.getImageWritersByMIMEType("image/jpeg");
                if (iter.hasNext())
                {
                    ImageWriter writer = (ImageWriter)iter.next();
                    if (Main.m_settings.isDebug())
                        System.err.println(writer.getClass().getName());
                    ImageWriteParam iwp = writer.getDefaultWriteParam();
                    iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
                    iwp.setCompressionQuality((float)quality);
                    if (bOptimizedHuffman && iwp instanceof JPEGImageWriteParam)
                    {
                        JPEGImageWriteParam iwpjpeg = (JPEGImageWriteParam)iwp;
                        // this can reduce size, but can also break badly written decoders
                        iwpjpeg.setOptimizeHuffmanTables(true);
                    }
                    writer.setOutput(fios = new FileImageOutputStream(file));
                    writer.write(null, new IIOImage(bi, null, null), iwp);
                    writer.dispose();
                    flag = true;
                }
            }
            catch(IOException ex)
            {
                if (Main.m_settings.isDebug())
                    System.err.println(ex.toString());
            }
            if (fios != null)
            {
                try
                {
                    fios.close();
                }
                catch(IOException ex)
                {}
            }
        }
        return flag;
    }

    protected boolean saveBMP(File file, BufferedImage img, JIfdData ifd, double scaleFactor)
    {
        boolean flag = false;
        if (img != null)
        {
            FileImageOutputStream fios = null;
            try
            {
                if (file.exists())
                    file.delete();
                BufferedImage bi = getBufferedImage(img, ifd, scaleFactor);
                Iterator iter = ImageIO.getImageWritersByMIMEType("image/bmp");
                if (iter.hasNext())
                {
                    ImageWriter writer = (ImageWriter)iter.next();
                    if (Main.m_settings.isDebug())
                        System.err.println(writer.getClass().getName());
                    writer.setOutput(fios = new FileImageOutputStream(file));
                    writer.write(new IIOImage(bi, null, null));
                    writer.dispose();
                    flag = true;
                }
            }
            catch(IOException ex)
            {
                if (Main.m_settings.isDebug())
                    System.err.println(ex.toString());
            }
            if (fios != null)
            {
                try
                {
                    fios.close();
                }
                catch(IOException ex)
                {}
            }
        }
        return flag;
    }

    protected boolean savePNG(File file, BufferedImage img, JIfdData ifd, double scaleFactor)
    {
        boolean flag = false;
        if (img != null)
        {
            FileImageOutputStream fios = null;
            try
            {
                if (file.exists())
                    file.delete();
                BufferedImage bi = getBufferedImage(img, ifd, scaleFactor);
                PngEncoderB pngEnc = new PngEncoderB(bi);
                pngEnc.setCompressionLevel(9);
                fios = new FileImageOutputStream(file);
                byte [] data = pngEnc.pngEncode(false);
                if (data != null)
                    fios.write(data);
                 flag = true;
            }
            catch(IOException ex)
            {
                if (Main.m_settings.isDebug())
                    System.err.println(ex.toString());
            }
            if (fios != null)
            {
                try
                {
                    fios.close();
                }
                catch(IOException ex)
                {}
            }
        }
        return flag;
    }

    public Dimension getImageSize(BufferedImage img, JIfdData ifd, double scaleFactor)
    {
        int w = img.getWidth(null), h = img.getHeight(null);
        int d;
        switch(ifd == null ? getOrientation() : getOrientation(ifd))
        {
            case 5: // -90° + <->
            case 6: // -90°
            case 7: // 90° + <->
            case 8: // 90°
                d = w;
                w = h;
                h = d;
                break;
        }
        h = (int)(scaleFactor * (double)h + .5);
        w = (int)(scaleFactor * (double)w + .5);

        return new Dimension(w, h);
    }

    public BufferedImage getBufferedImage(BufferedImage img, JIfdData ifd, double scaleFactor)
    {
        Dimension dim = getImageSize(img, ifd, scaleFactor);

        BufferedImage bi = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().createCompatibleImage(dim.width, dim.height);
        Graphics g = bi.createGraphics();
        doScaleRotate(img, ifd, g, dim);
        Graphics2D g2d = (Graphics2D)g;
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, Main.m_settings.getInterpolation());
        g.drawImage(img, 0, 0, null);
        g.dispose();
        return bi;
    }
}

final class JImageData
{
    private BufferedImage m_image;
    private String m_file;
   
    public JImageData(String file, BufferedImage image)
    {
        m_image = image;
        m_file = file;
    }
   
    public String getFile()
    {
      return m_file;
    }

    public BufferedImage getImage()
    {
        return m_image;
    }
   
    public String toString()
    {
        return m_file;
    }
}

final class JImageCache
{
    private ArrayList<JImageData> m_list;
    private int m_size;
    private boolean m_bCallGc;
   
    private void trace()
    {
        if (Main.m_settings.isDebug())
        {
            System.err.println("Cache:");
            for (JImageData data : m_list)
                System.err.println("\t" + data);
        }
    }
   
    public JImageCache(int size, boolean bCallGc)
    {
        m_size = size;
        m_bCallGc = bCallGc;
        m_list = new ArrayList<JImageData>();
    }
   
    protected JImageData find(String file)
    {
        if (m_list != null && m_list.size() > 0)
        {
            for (int i=m_list.size()-1; i>=0; i--)
            {
                if (m_list.get(i).getFile().equals(file))
                    return m_list.get(i);
            }
            /*
            for (JImageData data : m_list)
            {
            if (data.getFile().equals(file))
                return data;
            }
             */
        }
        return null;
    }
   
    public void remove(String file)
    {
        if (m_list != null && m_list.size() > 0)
        {
            boolean flag = false;
            for (int i=m_list.size()-1; i>=0; i--)
            {
                if (m_list.get(i).getFile().equals(file))
                {
                    m_list.remove(i);
                    flag = true;
                    break;
                }
            }
            if (flag && m_bCallGc)
                System.gc();
        }
        if (Main.m_settings.isDebug())
            trace();
    }
   
    public void add(JImageData data)
    {
        if (find(data.getFile()) == null)
        {
            m_list.add(data);
            boolean flag = false;
            while(m_list.size() > m_size)
            {
                m_list.remove(0);
                flag = true;
            }
            if (flag && m_bCallGc)
                System.gc();
        }
        if (Main.m_settings.isDebug())
            trace();
    }

    public JImageData get(String file)
    {
      return find(file);
    }

    public void clear()
    {
        m_list.clear();
        if (m_bCallGc)
            System.gc();
    }
}
TOP

Related Classes of jexifviewer.JImgView

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.