1 Commits

2 changed files with 163 additions and 21 deletions

5
.gitignore vendored
View File

@@ -45,4 +45,7 @@ dependency-reduced-pom.xml
.idea
## This is for our app, cause it likes to store stuff ##
network_cameras.json
network_cameras.json
## exec launch4j config ##
execfg.xml

View File

@@ -1,30 +1,106 @@
package io.swtc.proccessing;
import io.swtc.proccessing.ui.ShowError;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
/**
* Enhanced CameraPanel with support for custom image processors
*/
public class CameraPanel extends JPanel {
private volatile BufferedImage sourceImage;
private volatile BufferedImage processedImage;
private Function<BufferedImage, BufferedImage> imageProcessor;
private final AtomicBoolean repaintScheduled = new AtomicBoolean(false);
private double zoomLevel = 1.0;
private double xOffset = 0;
private double yOffset = 0;
private Point dragStartPoint;
private static final double MIN_ZOOM = 1.0;
private static final double MAX_ZOOM = 10.0; // ten is enough if ur using 640x480
private static final double ZOOM_MULTIPLIER = 1.1;
public CameraPanel() {
setBackground(Color.BLACK);
setPreferredSize(new Dimension(640, 480));
initInteractionListeners();
}
private void initInteractionListeners() {
MouseAdapter mouseHandler = new MouseAdapter() {
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
handleZoom(e);
}
@Override
public void mousePressed(MouseEvent e) {
dragStartPoint = e.getPoint();
setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
}
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2)
resetView();
}
@Override
public void mouseReleased(MouseEvent e) { setCursor(Cursor.getDefaultCursor()); }
@Override
public void mouseDragged(MouseEvent e) {
handlePan(e);
}
@Override
public void mouseExited(MouseEvent e) { setCursor(Cursor.getDefaultCursor()); }
};
addMouseWheelListener(mouseHandler);
addMouseListener(mouseHandler);
addMouseMotionListener(mouseHandler);
}
public void setImage(BufferedImage img) {
sourceImage = img;
updateProcessedImage();
scheduleRepaint();
}
public void setImageProcessor(Function<BufferedImage, BufferedImage> processor) {
this.imageProcessor = processor;
if (sourceImage != null) {
updateProcessedImage();
scheduleRepaint();
}
}
private void updateProcessedImage() {
if (sourceImage == null) return;
if (imageProcessor != null) {
try {
processedImage = imageProcessor.apply(sourceImage);
} catch (Exception e) {
ShowError.error(null,"Fucked up in rendering \n" + Arrays.toString(e.getStackTrace()),"Problem");
processedImage = sourceImage; // Fallback
}
} else {
processedImage = sourceImage;
}
}
private void scheduleRepaint() {
if (repaintScheduled.compareAndSet(false, true)) {
SwingUtilities.invokeLater(() -> {
repaintScheduled.set(false);
@@ -33,37 +109,100 @@ public class CameraPanel extends JPanel {
}
}
public void setImageProcessor(Function<BufferedImage, BufferedImage> processor) {
this.imageProcessor = processor;
private void handleZoom(MouseWheelEvent e) {
if (processedImage == null) return;
double oldZoom = zoomLevel;
if (e.getWheelRotation() < 0) {
zoomLevel *= ZOOM_MULTIPLIER; // Zoom In
} else {
zoomLevel /= ZOOM_MULTIPLIER; // Zoom Out
}
// clamp shit
zoomLevel = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, zoomLevel));
if (oldZoom != zoomLevel) {
double xRel = e.getX() - xOffset;
double yRel = e.getY() - yOffset;
double zoomFactor = zoomLevel / oldZoom;
xOffset = e.getX() - (xRel * zoomFactor);
yOffset = e.getY() - (yRel * zoomFactor);
checkBounds();
repaint();
}
}
private void handlePan(MouseEvent e) {
if (processedImage == null || dragStartPoint == null) return;
// Calculate delta
int dx = e.getX() - dragStartPoint.x;
int dy = e.getY() - dragStartPoint.y;
xOffset += dx;
yOffset += dy;
dragStartPoint = e.getPoint();
checkBounds();
repaint();
}
private void checkBounds() {
double viewedWidth = getWidth() * zoomLevel;
double viewedHeight = getHeight() * zoomLevel;
if (xOffset > 0) xOffset = 0;
if (yOffset > 0) yOffset = 0;
if (xOffset + viewedWidth < getWidth()) {
xOffset = getWidth() - viewedWidth;
}
if (yOffset + viewedHeight < getHeight()) {
yOffset = getHeight() - viewedHeight;
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
BufferedImage src = sourceImage;
if (src == null) return;
BufferedImage img = src;
if (imageProcessor != null) {
// we only apply the proccessor if it is present
// that is due too CPU Usage ; This project was built for a DUAL Core CPU, not a quad or even 6 Core CPU
img = imageProcessor.apply(src);
}
processedImage = img;
if (processedImage == null) return;
Graphics2D g2d = (Graphics2D) g;
AffineTransform originalTransform = g2d.getTransform();
g2d.setRenderingHint(
RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR
);
g2d.drawImage(img, 0, 0, getWidth(), getHeight(), null);
g2d.translate(xOffset, yOffset);
double scaleX = (double) getWidth() / processedImage.getWidth();
double scaleY = (double) getHeight() / processedImage.getHeight();
g2d.scale(scaleX * zoomLevel, scaleY * zoomLevel);
g2d.drawImage(processedImage, 0, 0, null);
g2d.setTransform(originalTransform);
}
public BufferedImage getCurrentProcessedImage() {
return processedImage;
}
}
public void resetView() {
zoomLevel = 1.0;
xOffset = 0;
yOffset = 0;
repaint();
}
}