package com.akjava.gwt.inpaint.client;
import com.akjava.gwt.html5.client.file.Uint8Array;
import com.akjava.gwt.lib.client.LogUtils;
import com.akjava.lib.common.utils.ColorUtils;
import com.google.gwt.canvas.dom.client.ImageData;
import com.google.gwt.core.client.JavaScriptObject;
public class InPaint extends JavaScriptObject{
protected InPaint(){}
public static native final boolean exists()/*-{
if($wnd.InpaintTelea){
return true;
}else{
return false;
}
}-*/;
public static final int DEFAULT_RADIUS=5;
public static void createImageDataFromMask(ImageData data,Uint8Array mask,int r,int g,int b,int a,boolean doClear){
for(int y=0;y<data.getHeight();y++){
for(int x=0;x<data.getWidth();x++){
if(mask.get(y*data.getWidth()+x)==1){
data.setAlphaAt(a, x, y);
data.setRedAt(r, x, y);
data.setGreenAt(g, x, y);
data.setBlueAt(b, x, y);
}else{
if(doClear){
data.setAlphaAt(0, x, y);
data.setRedAt(0, x, y);
data.setGreenAt(0, x, y);
data.setBlueAt(0, x, y);
}
}
}
}
}
public static void createImageDataFromMaskAsGray(ImageData data,Uint8Array mask){
for(int y=0;y<data.getHeight();y++){
for(int x=0;x<data.getWidth();x++){
int v=mask.get(y*data.getWidth()+x);
data.setAlphaAt(255, x, y);
data.setRedAt(v, x, y);
data.setGreenAt(v, x, y);
data.setBlueAt(v, x, y);
}
}
}
public static Uint8Array createMaskByColor(ImageData data,int r,int g,int b){
return createMaskByColor(data, r, g, b,true);
}
public static Uint8Array createMaskBySimilarColor(ImageData data,int r,int g,int b,int allowLength){
Uint8Array bytes=Uint8Array.createUint8(data.getWidth()*data.getHeight());
for(int y=0;y<data.getHeight();y++){
for(int x=0;x<data.getWidth();x++){
int imgR=data.getRedAt(x, y);
int imgG=data.getGreenAt(x, y);
int imgB=data.getBlueAt(x, y);
double length=ColorUtils.getColorLength(r, g, b, imgR, imgG, imgB);
if(length<allowLength){
bytes.set(y*data.getWidth()+x, 1);
}
}
}
return bytes;
}
public static Uint8Array createMaskByColor(ImageData data,int r,int g,int b,boolean setSameColorCase){
Uint8Array bytes=Uint8Array.createUint8(data.getWidth()*data.getHeight());
for(int y=0;y<data.getHeight();y++){
for(int x=0;x<data.getWidth();x++){
int imgR=data.getRedAt(x, y);
int imgG=data.getGreenAt(x, y);
int imgB=data.getBlueAt(x, y);
if(r==imgR && g==imgG&&b==imgB){
if(setSameColorCase){
bytes.set(y*data.getWidth()+x, 1);
}
}else{
if(!setSameColorCase){
bytes.set(y*data.getWidth()+x, 1);
}
}
}
}
return bytes;
}
public final static native void inpaint(ImageData blah,Uint8Array mask_u8,int radius)/*-{
var width = blah.width;
var height = blah.height;
for(var channel = 0; channel < 3; channel++){
var img_u8 = new Uint8Array(width * height)
for(var n = 0; n < blah.data.length; n+=4){
img_u8[n / 4] = blah.data[n + channel]
}
$wnd.InpaintTelea(width, height, img_u8, mask_u8,radius)
for(var i = 0; i < img_u8.length; i++){
blah.data[4 * i + channel] = img_u8[i]
}
}
// render result back to canvas
for(var i = 0; i < img_u8.length; i++){
blah.data[4 * i + 3] = 255;
}
}-*/;
public final native void inpaintTelea(int width,int height,Uint8Array imageChannel,Uint8Array mask,int radius)/*-{
$wnd.InpaintTelea(width,height,imageChannel,mask,radius);
}-*/;
public static Uint8Array expandMaskByte(Uint8Array bytes,int width,int rad){
int height=bytes.length()/width;
Uint8Array copied=Uint8Array.createUint8(width*height);
for(int y=0;y<height;y++){
for(int x=0;x<width;x++){
int value=bytes.get(y*width+x);
if(value==1){
for(int dx = -rad; dx <= rad; dx++){
for(int dy = -rad; dy <= rad; dy++){
if(dx * dx + dy * dy <= rad * rad){
int sx=x+dx;
int sy=y+dy;
if(sx>=0 && sx<width && sy>=0 &&sy<height){//valid in
int at=(y+dy)*width+x+dx;
copied.set(at,1);
}
}
}
}
}
}
}
return copied;
}
public static Uint8Array createMaskByAlpha(ImageData data) {
Uint8Array bytes=Uint8Array.createUint8(data.getWidth()*data.getHeight());
for(int y=0;y<data.getHeight();y++){
for(int x=0;x<data.getWidth();x++){
int alpha=data.getAlphaAt(x, y);
//if(alpha==0){//this means only 0
//bytes.set((y)*data.getWidth()+x,1);
//}
if(alpha!=255){//need option
bytes.set((y)*data.getWidth()+x,1);
}
}
}
return bytes;
}
//TODO change,not so good
//return 0-255 value
public static Uint8Array expandMaskByteAsGray(Uint8Array bytes,int width,int rad) {
int height=bytes.length()/width;
double perv=255.0/rad;
int powrad=rad*rad;
Uint8Array copied=Uint8Array.createUint8(width*height);
for(int y=0;y<height;y++){
for(int x=0;x<width;x++){
int value=bytes.get(y*width+x);
if(value==1){
for(int dx = -rad; dx <= rad; dx++){
for(int dy = -rad; dy <= rad; dy++){
int powx=dx*dx;
int powy=dy*dy;
if(powx + powy <= powrad){
double length=Math.sqrt(powx+powy);
int v=255-((int) Math.min(255,(int)(perv*length)))+(int)(perv/2);
if(v<0){
v=0;
}
if(v>255){
v=255;
}
int sx=x+dx;
int sy=y+dy;
if(x==310 && y==189){
// LogUtils.log(dx+","+dy+","+v+",length="+length+",perv="+perv);
}
if(sx>=0 && sx<width && sy>=0 &&sy<height){//valid in
int at=(sy)*width+sx;
if(copied.get(at)<v){
copied.set(at, v);
}
}
}
}
}
}
}
}
Uint8Array averaged=Uint8Array.createUint8(width*height);
for(int y=0;y<height;y++){
for(int x=0;x<width;x++){
//int value=bytes.get(y*width+x);
//if(value!=1){
int count=0;
double total=0;
for(int dx = -rad; dx <= rad; dx++){
for(int dy = -rad; dy <= rad; dy++){
int powx=dx*dx;
int powy=dy*dy;
if(powx + powy <= powrad){
int sx=x+dx;
int sy=y+dy;
if(sx>=0 && sx<width && sy>=0 &&sy<height){//valid in
int at=(sy)*width+sx;
total+=copied.get(at);
count++;
}
}
}
}
int avg=(int)(total/count);
averaged.set(y*width+x, avg);
//}else{
//averaged.set(y*width+x, 255);
//}
}
}
return averaged;
//return copied;
}
}