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