1*b1cdbd2cSJim Jagielski /************************************************************** 2*b1cdbd2cSJim Jagielski * 3*b1cdbd2cSJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one 4*b1cdbd2cSJim Jagielski * or more contributor license agreements. See the NOTICE file 5*b1cdbd2cSJim Jagielski * distributed with this work for additional information 6*b1cdbd2cSJim Jagielski * regarding copyright ownership. The ASF licenses this file 7*b1cdbd2cSJim Jagielski * to you under the Apache License, Version 2.0 (the 8*b1cdbd2cSJim Jagielski * "License"); you may not use this file except in compliance 9*b1cdbd2cSJim Jagielski * with the License. You may obtain a copy of the License at 10*b1cdbd2cSJim Jagielski * 11*b1cdbd2cSJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0 12*b1cdbd2cSJim Jagielski * 13*b1cdbd2cSJim Jagielski * Unless required by applicable law or agreed to in writing, 14*b1cdbd2cSJim Jagielski * software distributed under the License is distributed on an 15*b1cdbd2cSJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*b1cdbd2cSJim Jagielski * KIND, either express or implied. See the License for the 17*b1cdbd2cSJim Jagielski * specific language governing permissions and limitations 18*b1cdbd2cSJim Jagielski * under the License. 19*b1cdbd2cSJim Jagielski * 20*b1cdbd2cSJim Jagielski *************************************************************/ 21*b1cdbd2cSJim Jagielski 22*b1cdbd2cSJim Jagielski 23*b1cdbd2cSJim Jagielski 24*b1cdbd2cSJim Jagielski package convwatch; 25*b1cdbd2cSJim Jagielski 26*b1cdbd2cSJim Jagielski import convwatch.ImageHelper; 27*b1cdbd2cSJim Jagielski import java.io.File; 28*b1cdbd2cSJim Jagielski import java.awt.image.RenderedImage; 29*b1cdbd2cSJim Jagielski import java.awt.image.BufferedImage; 30*b1cdbd2cSJim Jagielski import java.lang.reflect.Method; 31*b1cdbd2cSJim Jagielski 32*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------- 33*b1cdbd2cSJim Jagielski class Rect 34*b1cdbd2cSJim Jagielski { 35*b1cdbd2cSJim Jagielski int x; 36*b1cdbd2cSJim Jagielski int y; 37*b1cdbd2cSJim Jagielski int w; 38*b1cdbd2cSJim Jagielski int h; 39*b1cdbd2cSJim Jagielski Rect(int _x, int _y, int _w, int _h)40*b1cdbd2cSJim Jagielski public Rect(int _x, int _y, int _w, int _h) 41*b1cdbd2cSJim Jagielski { 42*b1cdbd2cSJim Jagielski x = _x; 43*b1cdbd2cSJim Jagielski y = _y; 44*b1cdbd2cSJim Jagielski w = _w; 45*b1cdbd2cSJim Jagielski h = _h; 46*b1cdbd2cSJim Jagielski } getX()47*b1cdbd2cSJim Jagielski public int getX() {return x;} getY()48*b1cdbd2cSJim Jagielski public int getY() {return y;} getWidth()49*b1cdbd2cSJim Jagielski public int getWidth() {return w;} getHeight()50*b1cdbd2cSJim Jagielski public int getHeight() {return h;} 51*b1cdbd2cSJim Jagielski } 52*b1cdbd2cSJim Jagielski 53*b1cdbd2cSJim Jagielski class BorderRemover 54*b1cdbd2cSJim Jagielski { 55*b1cdbd2cSJim Jagielski ImageHelper m_aImage; 56*b1cdbd2cSJim Jagielski 57*b1cdbd2cSJim Jagielski // Helper values, filled after find Border 58*b1cdbd2cSJim Jagielski 59*b1cdbd2cSJim Jagielski // --------------------------------- test mode --------------------------------- 60*b1cdbd2cSJim Jagielski 61*b1cdbd2cSJim Jagielski // void pixelValue(int pixel) 62*b1cdbd2cSJim Jagielski // { 63*b1cdbd2cSJim Jagielski // int alpha = (pixel >> 24) & 0xff; 64*b1cdbd2cSJim Jagielski // int red = (pixel >> 16) & 0xff; 65*b1cdbd2cSJim Jagielski // int green = (pixel >> 8) & 0xff; 66*b1cdbd2cSJim Jagielski // int blue = (pixel ) & 0xff; 67*b1cdbd2cSJim Jagielski // int dummy = 0; 68*b1cdbd2cSJim Jagielski // } 69*b1cdbd2cSJim Jagielski 70*b1cdbd2cSJim Jagielski /* 71*b1cdbd2cSJim Jagielski * compares 2 colors with a given tolerance. So it's possible to check differences approximate. 72*b1cdbd2cSJim Jagielski * @param _nColor1 73*b1cdbd2cSJim Jagielski * @param _nColor2 74*b1cdbd2cSJim Jagielski * @param _nTolerance is a percentage value how strong the colors could be differ 75*b1cdbd2cSJim Jagielski 76*b1cdbd2cSJim Jagielski */ compareColorWithTolerance(int _nColor1, int _nColor2, int _nTolerance)77*b1cdbd2cSJim Jagielski boolean compareColorWithTolerance(int _nColor1, int _nColor2, int _nTolerance) 78*b1cdbd2cSJim Jagielski { 79*b1cdbd2cSJim Jagielski // int alpha1 = (_nColor1 >> 24) & 0xff; 80*b1cdbd2cSJim Jagielski int red1 = (_nColor1 >> 16) & 0xff; 81*b1cdbd2cSJim Jagielski int green1 = (_nColor1 >> 8) & 0xff; 82*b1cdbd2cSJim Jagielski int blue1 = (_nColor1 ) & 0xff; 83*b1cdbd2cSJim Jagielski 84*b1cdbd2cSJim Jagielski // int alpha2 = (_nColor2 >> 24) & 0xff; 85*b1cdbd2cSJim Jagielski int red2 = (_nColor2 >> 16) & 0xff; 86*b1cdbd2cSJim Jagielski int green2 = (_nColor2 >> 8) & 0xff; 87*b1cdbd2cSJim Jagielski int blue2 = (_nColor2 ) & 0xff; 88*b1cdbd2cSJim Jagielski 89*b1cdbd2cSJim Jagielski if (_nTolerance > 100) 90*b1cdbd2cSJim Jagielski { 91*b1cdbd2cSJim Jagielski _nTolerance = 100; 92*b1cdbd2cSJim Jagielski } 93*b1cdbd2cSJim Jagielski 94*b1cdbd2cSJim Jagielski // calculate tolerance halve 95*b1cdbd2cSJim Jagielski double nTolerable = (_nTolerance * 256 / 100); 96*b1cdbd2cSJim Jagielski if (nTolerable < 0) 97*b1cdbd2cSJim Jagielski { 98*b1cdbd2cSJim Jagielski nTolerable = 0; 99*b1cdbd2cSJim Jagielski } 100*b1cdbd2cSJim Jagielski 101*b1cdbd2cSJim Jagielski // X - th < Y < X + th 102*b1cdbd2cSJim Jagielski // if ((red1 - nTolerable) < red2 && red2 < (red1 + nTolerable)) 103*b1cdbd2cSJim Jagielski // is the same 104*b1cdbd2cSJim Jagielski // abs (X - Y) < th 105*b1cdbd2cSJim Jagielski if (Math.abs(red1 - red2) < nTolerable) 106*b1cdbd2cSJim Jagielski { 107*b1cdbd2cSJim Jagielski if (Math.abs(green1 - green2) < nTolerable) 108*b1cdbd2cSJim Jagielski { 109*b1cdbd2cSJim Jagielski if (Math.abs(blue1 - blue2) < nTolerable) 110*b1cdbd2cSJim Jagielski { 111*b1cdbd2cSJim Jagielski return true; 112*b1cdbd2cSJim Jagielski } 113*b1cdbd2cSJim Jagielski else 114*b1cdbd2cSJim Jagielski { 115*b1cdbd2cSJim Jagielski // blue differ 116*b1cdbd2cSJim Jagielski } 117*b1cdbd2cSJim Jagielski } 118*b1cdbd2cSJim Jagielski else 119*b1cdbd2cSJim Jagielski { 120*b1cdbd2cSJim Jagielski // green differ 121*b1cdbd2cSJim Jagielski } 122*b1cdbd2cSJim Jagielski } 123*b1cdbd2cSJim Jagielski else 124*b1cdbd2cSJim Jagielski { 125*b1cdbd2cSJim Jagielski // red differ 126*b1cdbd2cSJim Jagielski } 127*b1cdbd2cSJim Jagielski 128*b1cdbd2cSJim Jagielski return false; 129*b1cdbd2cSJim Jagielski } 130*b1cdbd2cSJim Jagielski 131*b1cdbd2cSJim Jagielski /** 132*b1cdbd2cSJim Jagielski * create a new image from an exist one without it's borders 133*b1cdbd2cSJim Jagielski * open the file (_sFilenameFrom) as an image, check if it contains any borders and remove 134*b1cdbd2cSJim Jagielski * the borders. 135*b1cdbd2cSJim Jagielski */ createNewImageWithoutBorder(String _sFilenameFrom, String _sFilenameTo)136*b1cdbd2cSJim Jagielski public boolean createNewImageWithoutBorder(String _sFilenameFrom, String _sFilenameTo) 137*b1cdbd2cSJim Jagielski throws java.io.IOException 138*b1cdbd2cSJim Jagielski { 139*b1cdbd2cSJim Jagielski // System.out.println("load image: " + fileName); 140*b1cdbd2cSJim Jagielski m_aImage = ImageHelper.createImageHelper(_sFilenameFrom); 141*b1cdbd2cSJim Jagielski 142*b1cdbd2cSJim Jagielski // System.out.println("image width:" + String.valueOf(m_aImage.getWidth())); 143*b1cdbd2cSJim Jagielski // System.out.println("image height:" + String.valueOf(m_aImage.getHeight())); 144*b1cdbd2cSJim Jagielski 145*b1cdbd2cSJim Jagielski // int nw = graphics_stuff.countNotWhitePixel(m_aImage); 146*b1cdbd2cSJim Jagielski // System.out.println("not white pixels:" + String.valueOf(nw)); 147*b1cdbd2cSJim Jagielski 148*b1cdbd2cSJim Jagielski // int nb = graphics_stuff.countNotBlackPixel(m_aImage); 149*b1cdbd2cSJim Jagielski // System.out.println("not black pixels:" + String.valueOf(nb)); 150*b1cdbd2cSJim Jagielski 151*b1cdbd2cSJim Jagielski int nBorderColor = m_aImage.getPixel(0,0); 152*b1cdbd2cSJim Jagielski Rect aInnerRect = findBorder(m_aImage, nBorderColor); 153*b1cdbd2cSJim Jagielski 154*b1cdbd2cSJim Jagielski RenderedImage aImage = createImage(m_aImage, aInnerRect); 155*b1cdbd2cSJim Jagielski 156*b1cdbd2cSJim Jagielski File aWriteFile = new File(_sFilenameTo); 157*b1cdbd2cSJim Jagielski // GlobalLogWriter.get().println("Hello World: File to: " + _sFilenameTo); 158*b1cdbd2cSJim Jagielski 159*b1cdbd2cSJim Jagielski Exception ex = null; 160*b1cdbd2cSJim Jagielski try 161*b1cdbd2cSJim Jagielski { 162*b1cdbd2cSJim Jagielski Class imageIOClass = Class.forName("javax.imageio.ImageIO"); 163*b1cdbd2cSJim Jagielski // GlobalLogWriter.get().println("Hello World: get Class"); 164*b1cdbd2cSJim Jagielski 165*b1cdbd2cSJim Jagielski Method getWriterMIMETypesMethod = imageIOClass.getDeclaredMethod("getWriterMIMETypes", new Class[]{ }); 166*b1cdbd2cSJim Jagielski // GlobalLogWriter.get().println("Hello World: get Methode"); 167*b1cdbd2cSJim Jagielski 168*b1cdbd2cSJim Jagielski Object aObj = getWriterMIMETypesMethod.invoke(imageIOClass, new Object[]{ }); 169*b1cdbd2cSJim Jagielski String[] types = (String[])aObj; 170*b1cdbd2cSJim Jagielski // GlobalLogWriter.get().println("Hello World: types: " + Arrays.asList(types) ); 171*b1cdbd2cSJim Jagielski 172*b1cdbd2cSJim Jagielski Method writeMethod = imageIOClass.getDeclaredMethod("write", new Class[]{ java.awt.image.RenderedImage.class, 173*b1cdbd2cSJim Jagielski java.lang.String.class, 174*b1cdbd2cSJim Jagielski java.io.File.class}); 175*b1cdbd2cSJim Jagielski // GlobalLogWriter.get().println("Hello World: get Methode"); 176*b1cdbd2cSJim Jagielski writeMethod.invoke(imageIOClass, new Object[]{aImage, "image/jpeg", aWriteFile}); 177*b1cdbd2cSJim Jagielski } 178*b1cdbd2cSJim Jagielski catch(java.lang.ClassNotFoundException e) { 179*b1cdbd2cSJim Jagielski e.printStackTrace(); 180*b1cdbd2cSJim Jagielski ex = e; 181*b1cdbd2cSJim Jagielski } 182*b1cdbd2cSJim Jagielski catch(java.lang.NoSuchMethodException e) { 183*b1cdbd2cSJim Jagielski e.printStackTrace(); 184*b1cdbd2cSJim Jagielski ex = e; 185*b1cdbd2cSJim Jagielski } 186*b1cdbd2cSJim Jagielski catch(java.lang.IllegalAccessException e) { 187*b1cdbd2cSJim Jagielski e.printStackTrace(); 188*b1cdbd2cSJim Jagielski ex = e; 189*b1cdbd2cSJim Jagielski } 190*b1cdbd2cSJim Jagielski catch(java.lang.reflect.InvocationTargetException e) { 191*b1cdbd2cSJim Jagielski e.printStackTrace(); 192*b1cdbd2cSJim Jagielski ex = e; 193*b1cdbd2cSJim Jagielski } 194*b1cdbd2cSJim Jagielski 195*b1cdbd2cSJim Jagielski if (ex != null) { 196*b1cdbd2cSJim Jagielski // get Java version: 197*b1cdbd2cSJim Jagielski String javaVersion = System.getProperty("java.version"); 198*b1cdbd2cSJim Jagielski throw new java.io.IOException( 199*b1cdbd2cSJim Jagielski "Cannot construct object with current Java version " + 200*b1cdbd2cSJim Jagielski javaVersion + ": " + ex.getMessage()); 201*b1cdbd2cSJim Jagielski } 202*b1cdbd2cSJim Jagielski // ImageIO.write(aImage, "jpg", aWriteFile); 203*b1cdbd2cSJim Jagielski 204*b1cdbd2cSJim Jagielski return true; 205*b1cdbd2cSJim Jagielski } 206*b1cdbd2cSJim Jagielski 207*b1cdbd2cSJim Jagielski 208*b1cdbd2cSJim Jagielski /** 209*b1cdbd2cSJim Jagielski * runs through the image, pixel by pixel 210*b1cdbd2cSJim Jagielski * as long as found pixels like the color at (0,0) this is interpreted as border. 211*b1cdbd2cSJim Jagielski * as result it fills the m_nXMin, m_nXMax, m_nYMin, m_nYMax values. 212*b1cdbd2cSJim Jagielski */ 213*b1cdbd2cSJim Jagielski findBorder(ImageHelper _aImage, int _nBorderColor)214*b1cdbd2cSJim Jagielski Rect findBorder(ImageHelper _aImage, int _nBorderColor) 215*b1cdbd2cSJim Jagielski { 216*b1cdbd2cSJim Jagielski int h = _aImage.getHeight(); 217*b1cdbd2cSJim Jagielski int w = _aImage.getWidth(); 218*b1cdbd2cSJim Jagielski int nXMin = w; 219*b1cdbd2cSJim Jagielski int nXMax = 0; 220*b1cdbd2cSJim Jagielski int nYMin = h; 221*b1cdbd2cSJim Jagielski int nYMax = 0; 222*b1cdbd2cSJim Jagielski 223*b1cdbd2cSJim Jagielski for (int y = 0; y < h; y++) 224*b1cdbd2cSJim Jagielski { 225*b1cdbd2cSJim Jagielski for (int x = 0; x < nXMin; x++) 226*b1cdbd2cSJim Jagielski { 227*b1cdbd2cSJim Jagielski // handlesinglepixel(x+i, y+j, pixels[j * w + i]); 228*b1cdbd2cSJim Jagielski int nCurrentColor = _aImage.getPixel(x, y); 229*b1cdbd2cSJim Jagielski if (! compareColorWithTolerance(nCurrentColor, _nBorderColor, 10)) 230*b1cdbd2cSJim Jagielski { 231*b1cdbd2cSJim Jagielski // pixelValue(nCurrentColor); 232*b1cdbd2cSJim Jagielski // System.out.print("*"); 233*b1cdbd2cSJim Jagielski nXMin = java.lang.Math.min(nXMin, x); 234*b1cdbd2cSJim Jagielski nYMin = java.lang.Math.min(nYMin, y); 235*b1cdbd2cSJim Jagielski } 236*b1cdbd2cSJim Jagielski // else 237*b1cdbd2cSJim Jagielski // { 238*b1cdbd2cSJim Jagielski // System.out.print(" "); 239*b1cdbd2cSJim Jagielski // } 240*b1cdbd2cSJim Jagielski } 241*b1cdbd2cSJim Jagielski } 242*b1cdbd2cSJim Jagielski for (int y = 0; y < h; y++) 243*b1cdbd2cSJim Jagielski { 244*b1cdbd2cSJim Jagielski for (int nx = w - 1; nx >= nXMax; --nx) 245*b1cdbd2cSJim Jagielski { 246*b1cdbd2cSJim Jagielski int ny = h - y - 1; 247*b1cdbd2cSJim Jagielski int nCurrentColor = _aImage.getPixel(nx, ny); 248*b1cdbd2cSJim Jagielski if (! compareColorWithTolerance(nCurrentColor, _nBorderColor, 10)) 249*b1cdbd2cSJim Jagielski { 250*b1cdbd2cSJim Jagielski nXMax = java.lang.Math.max(nXMax, nx); 251*b1cdbd2cSJim Jagielski nYMax = java.lang.Math.max(nYMax, ny); 252*b1cdbd2cSJim Jagielski } 253*b1cdbd2cSJim Jagielski } 254*b1cdbd2cSJim Jagielski // System.out.println(); 255*b1cdbd2cSJim Jagielski } 256*b1cdbd2cSJim Jagielski // System.out.println("xmin: " + String.valueOf(nXMin)); 257*b1cdbd2cSJim Jagielski // System.out.println("xmax: " + String.valueOf(nXMax)); 258*b1cdbd2cSJim Jagielski // System.out.println("ymin: " + String.valueOf(nYMin)); 259*b1cdbd2cSJim Jagielski // System.out.println("ymax: " + String.valueOf(nYMax)); 260*b1cdbd2cSJim Jagielski 261*b1cdbd2cSJim Jagielski Rect aRect; 262*b1cdbd2cSJim Jagielski if (nXMin < nXMax && nYMin < nYMax) 263*b1cdbd2cSJim Jagielski { 264*b1cdbd2cSJim Jagielski int nw = nXMax - nXMin + 1; 265*b1cdbd2cSJim Jagielski int nh = nYMax - nYMin + 1; 266*b1cdbd2cSJim Jagielski 267*b1cdbd2cSJim Jagielski // this is the rectangle around the image content. 268*b1cdbd2cSJim Jagielski aRect = new Rect(nXMin, nYMin, nw, nh ); 269*b1cdbd2cSJim Jagielski } 270*b1cdbd2cSJim Jagielski else 271*b1cdbd2cSJim Jagielski { 272*b1cdbd2cSJim Jagielski // create the smalles possible image 273*b1cdbd2cSJim Jagielski aRect = new Rect(0,0,1,1); 274*b1cdbd2cSJim Jagielski } 275*b1cdbd2cSJim Jagielski 276*b1cdbd2cSJim Jagielski 277*b1cdbd2cSJim Jagielski // m_nXMin = nXMin; 278*b1cdbd2cSJim Jagielski // m_nXMax = nXMax; 279*b1cdbd2cSJim Jagielski // m_nYMin = nYMin; 280*b1cdbd2cSJim Jagielski // m_nYMax = nYMax; 281*b1cdbd2cSJim Jagielski return aRect; 282*b1cdbd2cSJim Jagielski } 283*b1cdbd2cSJim Jagielski createImage(ImageHelper _aImage, Rect _aRect)284*b1cdbd2cSJim Jagielski RenderedImage createImage(ImageHelper _aImage, Rect _aRect) throws IllegalArgumentException 285*b1cdbd2cSJim Jagielski { 286*b1cdbd2cSJim Jagielski // TODO: throw if w or h < 0 287*b1cdbd2cSJim Jagielski int w = _aRect.getWidth(); 288*b1cdbd2cSJim Jagielski int h = _aRect.getHeight(); 289*b1cdbd2cSJim Jagielski 290*b1cdbd2cSJim Jagielski if (w <= 0 || h <= 0) 291*b1cdbd2cSJim Jagielski { 292*b1cdbd2cSJim Jagielski throw new IllegalArgumentException("width or height are too small or negative."); 293*b1cdbd2cSJim Jagielski } 294*b1cdbd2cSJim Jagielski 295*b1cdbd2cSJim Jagielski BufferedImage aBI = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); 296*b1cdbd2cSJim Jagielski 297*b1cdbd2cSJim Jagielski int nXOffset = _aRect.getX(); 298*b1cdbd2cSJim Jagielski int nYOffset = _aRect.getY(); 299*b1cdbd2cSJim Jagielski 300*b1cdbd2cSJim Jagielski // Memory Block move 301*b1cdbd2cSJim Jagielski for (int y = 0; y < h; y++) 302*b1cdbd2cSJim Jagielski { 303*b1cdbd2cSJim Jagielski for (int x = 0; x < w; x++) 304*b1cdbd2cSJim Jagielski { 305*b1cdbd2cSJim Jagielski // aPixels[y * w + x] = m_aImage.getPixel(m_nXMin + x, m_nYMin + y); 306*b1cdbd2cSJim Jagielski aBI.setRGB(x, y, _aImage.getPixel(x + nXOffset, y + nYOffset)); 307*b1cdbd2cSJim Jagielski } 308*b1cdbd2cSJim Jagielski } 309*b1cdbd2cSJim Jagielski // java.awt.image.MemoryImageSource aSource = new java.awt.image.MemoryImageSource(w, h, aPixels, 0, w); 310*b1cdbd2cSJim Jagielski // return java.awt.Component.createImage(aSource); 311*b1cdbd2cSJim Jagielski // return java.awt.Toolkit.getDefaultToolkit().createImage(aSource); 312*b1cdbd2cSJim Jagielski return aBI; 313*b1cdbd2cSJim Jagielski } 314*b1cdbd2cSJim Jagielski 315*b1cdbd2cSJim Jagielski } 316