package org.openpnp.vision.pipeline.ui; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.Point; import java.awt.image.BufferedImage; import javax.swing.JComponent; import org.opencv.core.Mat; import org.openpnp.util.OpenCvUtils; public class MatView extends JComponent { private BufferedImage image; public MatView() { setBackground(Color.black); } public void setMat(Mat mat) { if (mat == null || mat.empty()) { image = null; } else { image = OpenCvUtils.toBufferedImage(mat); } repaint(); } public Point scalePoint(Point p) { if (image == null) { return new Point(0, 0); } Insets ins = getInsets(); double sourceWidth = image.getWidth(); double sourceHeight = image.getHeight(); double destWidth = getWidth() - ins.left - ins.right; double destHeight = getHeight() - ins.top - ins.bottom; double widthRatio = sourceWidth / destWidth; double heightRatio = sourceHeight / destHeight; double scaledHeight, scaledWidth; if (heightRatio > widthRatio) { double aspectRatio = sourceWidth / sourceHeight; scaledHeight = destHeight; scaledWidth = (scaledHeight * aspectRatio); } else { double aspectRatio = sourceHeight / sourceWidth; scaledWidth = destWidth; scaledHeight = (scaledWidth * aspectRatio); } int imageX = (int) (ins.left + (destWidth / 2) - (scaledWidth / 2)); int imageY = (int) (ins.top + (destHeight / 2) - (scaledHeight / 2)); int x = (int) ((p.x - imageX) * (sourceWidth / scaledWidth)); int y = (int) ((p.y - imageY) * (sourceHeight / scaledHeight)); x = Math.max(x, 0); x = Math.min(x, image.getWidth()); y = Math.max(y, 0); y = Math.min(y, image.getHeight()); return new Point(x, y); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); if (image == null) { return; } Insets ins = getInsets(); double sourceWidth = image.getWidth(); double sourceHeight = image.getHeight(); double destWidth = getWidth() - ins.left - ins.right; double destHeight = getHeight() - ins.top - ins.bottom; /** * We want to fit both axes in the given destWidth and destHeight while maintaining the * aspect ratio. If the frame is smaller in either or both axes than the original will need * to be scaled to fill the space as completely as possible while still maintaining the * aspect ratio. 1. Determine the source size of the image: sourceWidth, sourceHeight. 2. * Determine the max size each axis can be: destWidth, destHeight. 3. Calculate how much * each axis needs to be scaled to fit. 4. Use the larger of the two and scale the opposite * axis by the aspect ratio + the scaling ratio. */ double widthRatio = sourceWidth / destWidth; double heightRatio = sourceHeight / destHeight; double scaledHeight, scaledWidth; if (heightRatio > widthRatio) { double aspectRatio = sourceWidth / sourceHeight; scaledHeight = destHeight; scaledWidth = (scaledHeight * aspectRatio); } else { double aspectRatio = sourceHeight / sourceWidth; scaledWidth = destWidth; scaledHeight = (scaledWidth * aspectRatio); } int imageX = (int) (ins.left + (destWidth / 2) - (scaledWidth / 2)); int imageY = (int) (ins.top + (destHeight / 2) - (scaledHeight / 2)); Graphics2D g2d = (Graphics2D) g; g2d.drawImage(image, imageX, imageY, (int) scaledWidth, (int) scaledHeight, null); } }