package com.akjava.gwt.lib.client.experimental; import com.akjava.gwt.lib.client.LogUtils; import com.google.gwt.canvas.dom.client.ImageData; import com.google.gwt.typedarrays.client.Uint8ArrayNative; public class ResizeUtils { private ResizeUtils(){} //from http://tech-algorithm.com/articles/bilinear-image-scaling/ public static Uint8ArrayNative resizeBilinear(Uint8ArrayNative array, int w, int h, int w2, int h2) { Uint8ArrayNative result = Uint8ArrayNative.create(w2*h2*4) ; int a, b, c, d, x, y, index ; float x_ratio = ((float)(w-1))/w2 ; float y_ratio = ((float)(h-1))/h2 ; float x_diff, y_diff, value ; int offset = 0 ; for (int i=0;i<h2;i++) { for (int j=0;j<w2;j++) { x = (int)(x_ratio * j) ; y = (int)(y_ratio * i) ; x_diff = (x_ratio * j) - x ; y_diff = (y_ratio * i) - y ; index = (y*w+x) ; for(int k=0;k<4;k++){ a = array.get((index)*4+k) ; b =array.get((index+1)*4+k) ; c = array.get((index+w)*4+k) ; d = array.get((index+w+1)*4+k) ; value = (a&0xff)*(1-x_diff)*(1-y_diff) + (b&0xff)*(x_diff)*(1-y_diff) + (c&0xff)*(y_diff)*(1-x_diff) + (d&0xff)*(x_diff*y_diff); result.set(offset*4+k,(int) value); } offset++; } } return result; } /* * to create data url private String toDataUrl(Uint8ArrayNative array,int w,int h){ Canvas resizedCanvas=CanvasUtils.createCanvas(w, h); ImageData data=ImageDataUtils.copySizeOnly(resizedCanvas);//they must have rgba ResizeUtils.setUint8Array(data, array); CanvasUtils.copyTo(data, resizedCanvas); return resizedCanvas.toDataUrl(); } */ public static Uint8ArrayNative resizeBilinear(ImageData imageData,int ax,int ay, int w, int h, int w2, int h2) { Uint8ArrayNative array=ImageDataUtils.getUint8(imageData); Uint8ArrayNative result = Uint8ArrayNative.create(w2*h2*4) ; int a, b, c, d, x, y, index ; float x_ratio = ((float)(w-1))/w2 ; float y_ratio = ((float)(h-1))/h2 ; float x_diff, y_diff, value ; int offset = 0 ; int iw=imageData.getWidth(); for (int i=0;i<h2;i++) { for (int j=0;j<w2;j++) { x = (int)(x_ratio * j) ; y = (int)(y_ratio * i) ; x_diff = (x_ratio * j) - x ; y_diff = (y_ratio * i) - y ; //index = (y*w+x) ; index = ((ay+y)*iw+x+ax) ; for(int k=0;k<4;k++){ a = array.get((index)*4+k) ; b =array.get((index+1)*4+k) ; c = array.get((index+iw)*4+k) ; d = array.get((index+iw+1)*4+k) ; value = (a&0xff)*(1-x_diff)*(1-y_diff) + (b&0xff)*(x_diff)*(1-y_diff) + (c&0xff)*(y_diff)*(1-x_diff) + (d&0xff)*(x_diff*y_diff); result.set(offset*4+k,(int) value); } offset++; } } return result; } public static Uint8ArrayNative resizeBilinearRedOnly(Uint8ArrayNative array, int w, int h, int w2, int h2) { Uint8ArrayNative result = Uint8ArrayNative.create(w2*h2*4) ; int a, b, c, d, x, y, index ; float x_ratio = ((float)(w-1))/w2 ; float y_ratio = ((float)(h-1))/h2 ; float x_diff, y_diff, value ; int offset = 0 ; for (int i=0;i<h2;i++) { for (int j=0;j<w2;j++) { x = (int)(x_ratio * j) ; y = (int)(y_ratio * i) ; x_diff = (x_ratio * j) - x ; y_diff = (y_ratio * i) - y ; index = (y*w+x) ; a = array.get((index)*4) ; b =array.get((index+1)*4) ; c = array.get((index+w)*4) ; d = array.get((index+w+1)*4) ; value = (a&0xff)*(1-x_diff)*(1-y_diff) + (b&0xff)*(x_diff)*(1-y_diff) + (c&0xff)*(y_diff)*(1-x_diff) + (d&0xff)*(x_diff*y_diff); result.set(offset*4,(int) value); offset++; } } return result; } public static Uint8ArrayNative resizeBilinearRedOnly(ImageData imageData,int ax,int ay, int w, int h, int w2, int h2) { Uint8ArrayNative array=ImageDataUtils.getUint8(imageData); Uint8ArrayNative result = Uint8ArrayNative.create(w2*h2) ; int a, b, c, d, x, y, index ; float x_ratio = ((float)(w-1))/w2 ; float y_ratio = ((float)(h-1))/h2 ; float x_diff, y_diff, value ; int offset = 0 ; int iw=imageData.getWidth(); for (int i=0;i<h2;i++) { for (int j=0;j<w2;j++) { x = (int)(x_ratio * j) ; y = (int)(y_ratio * i) ; x_diff = (x_ratio * j) - x ; y_diff = (y_ratio * i) - y ; index = ((ay+y)*iw+x+ax) ; a = array.get((index)*4) ; b =array.get((index+1)*4) ; c = array.get((index+iw)*4) ; d = array.get((index+iw+1)*4) ; value = (a&0xff)*(1-x_diff)*(1-y_diff) + (b&0xff)*(x_diff)*(1-y_diff) + (c&0xff)*(y_diff)*(1-x_diff) + (d&0xff)*(x_diff*y_diff); result.set(offset,(int) value); offset++; } } return result; } /** * * @param array must be packed * @param w * @param h * @param w2 * @param h2 * @return */ public static Uint8ArrayNative resizeBilinearRedOnlyPacked(Uint8ArrayNative array, int w, int h, int w2, int h2) { Uint8ArrayNative result = Uint8ArrayNative.create(w2*h2) ; int a, b, c, d, x, y, index ; float x_ratio = ((float)(w-1))/w2 ; float y_ratio = ((float)(h-1))/h2 ; float x_diff, y_diff, value ; int offset = 0 ; for (int i=0;i<h2;i++) { for (int j=0;j<w2;j++) { x = (int)(x_ratio * j) ; y = (int)(y_ratio * i) ; x_diff = (x_ratio * j) - x ; y_diff = (y_ratio * i) - y ; index = (y*w+x) ; a = array.get((index)) ; b =array.get((index+1)) ; c = array.get((index+w)) ; d = array.get((index+w+1)) ; value = (a&0xff)*(1-x_diff)*(1-y_diff) + (b&0xff)*(x_diff)*(1-y_diff) + (c&0xff)*(y_diff)*(1-x_diff) + (d&0xff)*(x_diff*y_diff); result.set(offset,(int) value); offset++; } } return result; } //http://tech-algorithm.com/articles/nearest-neighbor-image-scaling/ public static Uint8ArrayNative resizePixels(Uint8ArrayNative array,int w1,int h1,int w2,int h2) { int[] temp = new int[w2*h2*4] ;//rgba // EDIT: added +1 to account for an early rounding problem int x_ratio = (int)((w1<<16)/w2) +1; int y_ratio = (int)((h1<<16)/h2) +1; //int x_ratio = (int)((w1<<16)/w2) ; //int y_ratio = (int)((h1<<16)/h2) ; int x2, y2 ; for (int i=0;i<h2;i++) { for (int j=0;j<w2;j++) { x2 = ((j*x_ratio)>>16) ; y2 = ((i*y_ratio)>>16) ; int tempOff=((i*w2)+j)*4; int arrayOff=((y2*w1)+x2)*4; for(int k=0;k<4;k++){ temp[tempOff+k] = array.get(arrayOff+k) ; } } } return Uint8ArrayNative.create(temp); } public final static native Uint8ArrayNative getUint8Array(ImageData data) /*-{ return data.data; }-*/; public final static void setUint8Array(ImageData data,int[] array){ int w=data.getWidth(); LogUtils.log(array.length+",data="+data.getWidth()+"x"+data.getHeight()); for(int i=0;i<array.length;i+=4){ int x=i%(w*4); int y=i/(w*4); data.setRedAt(array[i], x, y); data.setGreenAt(array[i+1], x, y); data.setBlueAt(array[i+2], x, y); data.setAlphaAt(array[i+3], x, y); //LogUtils.log(x+"x"+y+","+array[i]+"/"+array[i+3]); } } public final static native void setUint8Array(ImageData data,Uint8ArrayNative array) /*-{ data.data.set(array); }-*/; }