Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates to healing brush demo conversion to hat - ongoing #113

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 22 additions & 27 deletions hat/examples/heal/src/java/heal/Display.java
Original file line number Diff line number Diff line change
@@ -47,7 +47,9 @@
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
@@ -66,11 +68,7 @@ public class Display extends JPanel implements MouseListener, MouseMotionListene
protected float xOffset = 0; // 0 is centered -1 is to the left;
protected float yOffset = 0; // 0 is centered -1 is to the top;


int mDownX;
int mDownY;
float mDownXOffset;
float mDownYOffset;
Point mDown;
Point2D mImageDown = new Point2D.Float();
Point2D mImageMove = new Point2D.Float();

@@ -98,10 +96,7 @@ public void mouseMoved(MouseEvent e) {
@Override
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
mDownX = e.getX();
mDownY = e.getY();
mDownXOffset = xOffset;
mDownYOffset = yOffset;
mDown = e.getPoint();
try {
transform.inverseTransform(e.getPoint(), mImageDown);
} catch (NoninvertibleTransformException e1) {
@@ -119,18 +114,17 @@ public void mouseWheelMoved(MouseWheelEvent e) {
@Override
public void mouseDragged(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
int dx = e.getX() - mDownX;
int dy = e.getY() - mDownY;
Point rightButonPoint = e.getPoint();
Dimension dragDelta = new Dimension(rightButonPoint.x - mDown.x, rightButonPoint.y - mDown.y);
try {
transform.inverseTransform(e.getPoint(), mImageMove);
int sw = getWidth();
int sh = getHeight();
int iw = image.getWidth();
int ih = image.getHeight();
float scale = zoom * Math.min(sw / (float) iw, sh / (float) ih);
xOffset = mDownXOffset + 2 * (dx / (sw - scale * iw));
yOffset = mDownYOffset + 2 * (dy / (sh - scale * ih));

Dimension displaySize = getSize();
Dimension imageSize = new Dimension( image.getWidth(),image.getHeight());
float scale = zoom *
Math.min(displaySize.width / (float) imageSize.width,
displaySize.height / (float) imageSize.height);
xOffset = 2 * (dragDelta.width / (displaySize.width - scale * imageSize.width));
yOffset = 2 * (dragDelta.height / (displaySize.height - scale * imageSize.height));
xOffset = Math.max(Math.min(xOffset, 1), -1);
yOffset = Math.max(Math.min(yOffset, 1), -1);
repaint();
@@ -158,18 +152,19 @@ public void paint(Graphics g) {
}

public void paintImage(Graphics2D g) {
int sw = getWidth();
int sh = getHeight();
int iw = image.getWidth();
int ih = image.getHeight();

Dimension displaySize = getSize();
Dimension imageSize = new Dimension( image.getWidth(),image.getHeight());
AffineTransform tx = g.getTransform();
transform.setToIdentity();
double scale = zoom * Math.min(sw / (double) iw, sh / (double) ih);
transform.translate((1 + xOffset) * (sw - iw * scale) / 2,
(1 + yOffset) * (sh - ih * scale) / 2);
double scale = zoom *
Math.min(displaySize.width / (double) imageSize.width,
displaySize.height / (double) imageSize.height);
transform.translate((1 + xOffset) * (displaySize.width - imageSize.width * scale) / 2,
(1 + yOffset) * (displaySize.height - imageSize.height * scale) / 2);
transform.scale(scale, scale);
g.transform(transform);
g.drawImage(image, 0, 0, iw, ih, null);
g.drawImage(image, 0, 0, imageSize.width, imageSize.height, null);
paintInScale(g);
g.setTransform(tx);
}
127 changes: 66 additions & 61 deletions hat/examples/heal/src/java/heal/HealingBrush.java
Original file line number Diff line number Diff line change
@@ -53,14 +53,11 @@
import java.awt.image.DataBufferInt;
import java.util.Arrays;


public class HealingBrush {

public static int[] getMask(Path path, int width, int height) {
Polygon polygon = new Polygon();
for (int i = 0; i < path.length(); i++) {

XYList.XY xy= (XYList.XY)path.xy(i);
XYList.XY xy = (XYList.XY) path.xy(i);
polygon.addPoint(xy.x() - path.x1 + 1, xy.y() - path.y1 + 1);
}
BufferedImage maskImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
@@ -72,44 +69,43 @@ public static int[] getMask(Path path, int width, int height) {
return mask;
}

public static void heal(Selection selection,
int fromDeltaX,
int fromDeltaY) {
public static void heal(Selection selection, int fromDeltaX, int fromDeltaY) {
int reg_width = 2 + selection.width;
int reg_height = 2 + selection.height;
int[] mask = getMask(selection.path, reg_width, reg_height);
int[] dest = new int[mask.length];
int[] src = new int[mask.length];
long start = System.currentTimeMillis();
long start = System.currentTimeMillis();
for (int i = 0; i < mask.length; i++) { //parallel
int x = i % reg_width;
int y = i / reg_width;
src[i] = selection.imageData.data[(selection.path.y1 + y - 1 + fromDeltaY) * selection.imageData.width + selection.path.x1 + x + fromDeltaX];
if (mask[i] != 0) {
dest[i] = src[i];
} else {
dest[i] = selection.imageData.data[(selection.path.y1 + y - 1) * selection.imageData.width + selection.path.x1 + x];
}
src[i] = selection.imageData.data[
(selection.path.y1 + y - 1 + fromDeltaY) * selection.imageData.width + selection.path.x1 + x + fromDeltaX
];
dest[i] =(mask[i] != 0)?src[i]:selection.imageData.data[(selection.path.y1 + y - 1) * selection.imageData.width + selection.path.x1 + x];
}
System.out.println("heal " +(System.currentTimeMillis()-start)+"ms");
System.out.println("heal " + (System.currentTimeMillis() - start) + "ms");

RGBList srclap = laplacian(src, reg_width, reg_height);
displayLapacian(srclap, dest, mask);

displayLapacian(srclap, dest, mask);


solve(dest, mask, srclap, reg_width, reg_height);

start=System.currentTimeMillis();

start = System.currentTimeMillis();
for (int i = 0; i < mask.length; i++) { //parallel
int x = i % reg_width;
int y = i / reg_width;
selection.imageData.data[(selection.path.y1 + y - 1) * selection.imageData.width + selection.path.x1 + x] = dest[i];
}
System.out.println("heal2 " +(System.currentTimeMillis()-start)+"ms");
System.out.println("heal2 " + (System.currentTimeMillis() - start) + "ms");
}

static void solve(int[] dest, int[] mask, RGBList lap_rgb, int width, int height) {
int r, g, b, v;
int[] tmp = new int[dest.length];
System.arraycopy(dest, 0, tmp, 0, tmp.length);
int[] tmp = Arrays.copyOf(dest,dest.length);
long start = System.currentTimeMillis();
for (int i = 0; i < 200; i++) {
for (int p = 0; p < width * height; p++) { // parallel
@@ -120,39 +116,53 @@ static void solve(int[] dest, int[] mask, RGBList lap_rgb, int width, int height
r = ((v >> 16) & 0xff);
g = ((v >> 8) & 0xff);
b = ((v >> 0) & 0xff);

v = dest[p + 1];
r += ((v >> 16) & 0xff);
g += ((v >> 8) & 0xff);
b += ((v >> 0) & 0xff);

v = dest[p - width];
r += ((v >> 16) & 0xff);
g += ((v >> 8) & 0xff);
b += ((v >> 0) & 0xff);

v = dest[p + width];
r += ((v >> 16) & 0xff);
g += ((v >> 8) & 0xff);
b += ((v >> 0) & 0xff);
r += (lap_rgb.rgb[p * 3 + 0]);
g += (lap_rgb.rgb[p * 3 + 1]);
b += (lap_rgb.rgb[p * 3 + 2]);

r += (lap_rgb.rgb[p * RGBList.STRIDE + RGBList.Ridx]);
g += (lap_rgb.rgb[p * RGBList.STRIDE + RGBList.Gidx]);
b += (lap_rgb.rgb[p * RGBList.STRIDE + RGBList.Bidx]);

r = (r + 2) / 4;
g = (g + 2) / 4;
b = (b + 2) / 4;

// r=(dest[x+1,y].r + dest[x-1,y].r +dest[x,y-1].r +dest[x,y+1].r + lap_rgb[x,y].r+2)/4;
// g=(dest[x+1,y].g + dest[x-1,y].g +dest[x,y-1].g +dest[x,y+1].g + lap_ggb[x,y].g+2)/4;
// b=(dest[x+1,y].b + dest[x-1,y].b +dest[x,y-1].b +dest[x,y+1].b + lap_bgb[x,y].b+2)/4;

tmp[p] = (((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (b & 0xFF));
}
}
int[] swap = tmp;
tmp = dest;
dest = swap;
}
System.out.println("solve " +(System.currentTimeMillis()-start)+"ms");
System.out.println("solve " + (System.currentTimeMillis() - start) + "ms");
}


static void displayLapacian(RGBList lap_rgb, int[] dst, int[] mask) {
for (RGBList.RGB rgb : lap_rgb) {
for (int i =0; i< lap_rgb.length(); i++) {
var rgb = lap_rgb.rgb(i);
if (mask[rgb.idx] != 0) {
dst[rgb.idx] = (((Math.abs(rgb.r) & 0xFF) << 16) | ((Math.abs(rgb.g) & 0xFF) << 8) | (Math.abs(rgb.b) & 0xFF));
dst[rgb.idx] =
(((Math.abs(rgb.r()) & 0xFF) << 16)
| ((Math.abs(rgb.g()) & 0xFF) << 8)
| (Math.abs(rgb.b()) & 0xFF));
}
}
}
@@ -188,12 +198,16 @@ static RGBList laplacian(int[] src, int width, int height) {
r -= ((v >> 16) & 0xff);
g -= ((v >> 8) & 0xff);
b -= ((v >> 0) & 0xff);

// r = r/4 + src[x-1,y-].r + src[x+1,y].r + src[x-0,y+1].r + src[x,y-1].r
// g = g/4 + src[x-1,y-].g + src[x+1,y].g + src[x-0,y+1].g + src[x,y-1].g
// b = b/4 + src[x-1,y-].b + src[x+1,y].b + src[x-0,y+1].b + src[x,y-1].b
rgbList.add(r, g, b);
} else {
rgbList.add(0, 0, 0);
}
}
System.out.println("laplacian " +(System.currentTimeMillis()-start)+"ms");
System.out.println("laplacian " + (System.currentTimeMillis() - start) + "ms");
return rgbList;
}

@@ -206,12 +220,16 @@ public static Point getBestMatch(Selection selection) {
int xmax = Math.min(selection.imageData.width, selection.path.x2 + selection.width * 3);
int ymax = Math.min(selection.imageData.height, selection.path.y2 + selection.height * 3);

RGBList orig_rgb = extractCurve(selection);
RGBList rgbList = new RGBList();
for (int i = 0; i < selection.path.length(); i++) {
XYList.XY xy = (XYList.XY) selection.path.xy(i);
rgbList.addRGB(selection.imageData.data[xy.y() * selection.imageData.width + xy.x()]);
}

RGBList comp = new RGBList(orig_rgb);
RGBList comp = new RGBList(rgbList);

float min = Float.MAX_VALUE;
int bestdx = -11111, bestdy = 0;
Point best = new Point(-11111, 0);
long start = System.currentTimeMillis();

for (int y = ymin; y < ymax - selection.height; y++) {
@@ -220,50 +238,37 @@ public static Point getBestMatch(Selection selection) {
int sdx = x - selection.path.x1;
int sdy = y - selection.path.y1;

for (int i=0;i<selection.path.length();i++){
XYList.XY xy= (XYList.XY)selection.path.xy(i);
comp.setRGB(xy.idx(), selection.imageData.data[sdy * selection.imageData.width + sdx + xy.y() * selection.imageData.width + xy.x()]);
for (int i = 0; i < selection.path.length(); i++) {
XYList.XY xy = (XYList.XY) selection.path.xy(i);
comp.setRGB(xy.idx(),
selection.imageData.data[
sdy * selection.imageData.width + sdx + xy.y()
* selection.imageData.width + xy.x()
]
);
}

float sum = 0;
for (RGBList.RGB rgb : orig_rgb) {
int dx = comp.rgb[rgb.idx * 3 + 0] - rgb.r;
int dy = comp.rgb[rgb.idx * 3 + 1] - rgb.g;
int dz = comp.rgb[rgb.idx * 3 + 2] - rgb.b;
sum += dx * dx + dy * dy + dz * dz;
for (int i =0; i< rgbList.length(); i++) {
var rgb = rgbList.rgb(i);
var compRgb = comp.rgb(i);
int dr = compRgb.r() - rgb.r();
int dg = compRgb.g() - rgb.g();
int db = compRgb.b() - rgb.b();
sum += dr * dr + dg * dg + db * db;
}

if (sum < min) {
min = sum;
bestdx = x - selection.path.x1;
bestdy = y - selection.path.y1;
best.setLocation(x - selection.path.x1,y - selection.path.y1);
}
}
}
}
System.out.println("search " +(System.currentTimeMillis()-start)+"ms");
offset = new Point(bestdx, bestdy);
System.out.println("search " + (System.currentTimeMillis() - start) + "ms");
offset = best;
}
return offset;

}
static RGBList extractCurve(Selection selection) {
RGBList rgbList = new RGBList();
for (int i=0;i<selection.path.length();i++){
XYList.XY xy= (XYList.XY)selection.path.xy(i);
rgbList.addRGB(selection.imageData.data[xy.y() * selection.imageData.width + xy.x()]);
}
return rgbList;
}

static void extractCurve(RGBList rgbList, Selection selection,
int dx,
int dy) {
for (int i=0;i<selection.path.length();i++){
XYList.XY xy= (XYList.XY)selection.path.xy(i);
rgbList.setRGB(xy.idx(), selection.imageData.data[dy * selection.imageData.width + dx + xy.y() * selection.imageData.width + xy.x()]);
}

}


Loading