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