/*
* Copyright (C) 2015 Patryk Strach
*
* This file is part of Virtual Slide Viewer.
*
* Virtual Slide Viewer 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 3 of the License, or (at your option) any later version.
*
* Virtual Slide Viewer 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 Virtual Slide Viewer.
* If not, see <http://www.gnu.org/licenses/>.
*/
package virtualslideviewer.ui.imagelist.view;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;
import virtualslideviewer.core.ImageIndex;
import virtualslideviewer.core.VirtualSlideImage;
import virtualslideviewer.util.ImageUtil;
import virtualslideviewer.util.ParameterValidator;
/**
* A JTable cell renderer which renders a thumbnail of virtual slide's image along with its name.
*
* The renderer automatically sets cell size to fit the entire thumbnail and its name.
*/
public class ThumbnailTableCellRenderer extends DefaultTableCellRenderer
{
private static final long serialVersionUID = -6305574378144421759L;
private static final int THUMBNAIL_NAME_HEIGHT = 25;
private static final long MAX_THUMBNAIL_RESOLUTION_SIZE = 512 * 512 * 3;
private final Dimension mMaxThumbnailSize;
/**
* @param thumbnailSize Maximum size for single thumbnail.
* The images will be scaled to fit specified area while preserving its aspect ratio.
*/
public ThumbnailTableCellRenderer(Dimension thumbnailSize)
{
ParameterValidator.throwIfNull(thumbnailSize, "thumbnailSize");
mMaxThumbnailSize = thumbnailSize;
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
JLabel label = (JLabel)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
label.setOpaque(false);
label.setHorizontalAlignment(SwingConstants.CENTER);
label.setHorizontalTextPosition(SwingConstants.CENTER);
label.setVerticalTextPosition(SwingConstants.BOTTOM);
VirtualSlideImage imageToRender = (VirtualSlideImage)value;
label.setIcon(new ImageIcon(getThumbnail(imageToRender)));
label.setText(imageToRender.getName());
setCellSizeToFitThumbnail(table, row, column, new Dimension(label.getIcon().getIconWidth(), label.getIcon().getIconHeight()));
return label;
}
private Image getThumbnail(VirtualSlideImage image)
{
BufferedImage thumbnailImage = loadImageFromThumbnailResolution(image);
return ImageUtil.scaleToFitPreservingAspectRatio(thumbnailImage, mMaxThumbnailSize);
}
private BufferedImage loadImageFromThumbnailResolution(VirtualSlideImage image)
{
int thumbnailResIndex = ImageUtil.getResolutionIndexWithSizeNotBiggerThan(image, MAX_THUMBNAIL_RESOLUTION_SIZE);
Dimension imageSize = image.getImageSize(thumbnailResIndex);
BufferedImage lowestResolution = new BufferedImage(imageSize.width, imageSize.height,
image.isRGB() ? BufferedImage.TYPE_3BYTE_BGR : BufferedImage.TYPE_BYTE_GRAY);
ImageUtil.loadDataIntoBufferedImage(lowestResolution, (dst) ->
{
image.getPixels(dst, new Rectangle(new Point(0, 0), imageSize), new ImageIndex(thumbnailResIndex));
});
return lowestResolution;
}
private void setCellSizeToFitThumbnail(JTable table, int rowIndex, int columnIndex, Dimension realThumbnailSize)
{
int preferredRowHeight = realThumbnailSize.height + THUMBNAIL_NAME_HEIGHT + table.getRowMargin();
if(table.getRowHeight(rowIndex) != preferredRowHeight)
{
table.setRowHeight(rowIndex, preferredRowHeight);
}
TableColumn column = table.getColumnModel().getColumn(columnIndex);
if(column.getWidth() < realThumbnailSize.width)
{
column.setPreferredWidth(realThumbnailSize.width);
}
}
}