/********************************************************************************* * TotalCross Software Development Kit * * Copyright (C) 2000-2012 SuperWaba Ltda. * * All Rights Reserved * * * * This library and virtual machine is distributed in the hope that it will * * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * * * This file is covered by the GNU LESSER GENERAL PUBLIC LICENSE VERSION 3.0 * * A copy of this license is located in file license.txt at the root of this * * SDK or can be downloaded here: * * http://www.gnu.org/licenses/lgpl-3.0.txt * * * *********************************************************************************/ package totalcross.unit; import totalcross.util.zip.*; import totalcross.ui.gfx.*; import totalcross.ui.image.*; import totalcross.io.*; import totalcross.sys.*; import totalcross.ui.*; /** This class is a helper to test if two images are equal, ie, * their width and height are the satest and their pixel values * are the satest. * There's first a learning stage where the images are generated * and the compressed strings are created. * Then the test should run again to do the effective comparision * at a pda. * <p>Here's a sample: <pre> * public class GraphicsTest extends TestCase * { * private Graphics g; * private boolean learning = false; // change this to true to generate the strings * * // generated string during learning stage * private String drawLine = "58C3AD94510EC2300CC5DEFD0FEA73C0186C0335892791DF7956DB240F6485CCB571027CCAC80C6E2E32822F1599C0DD4406F02D223DF8F190163C34A4034F0B69C08B84D4E0D5414AF04BD17C4ACDA5BA16D5997EFFA778FF4C5C9613B4E0B21A5DDA2EFCC527CFD7DE17F77EDCED87ECAF9C17397FF33C73633FE4BEC9FD957920F345E695CC3F99A7329F0DB683AA1EE9F8D157"; * * private ImageTester testDrawLine() * { * int w = 40, h = 40; * ImageTester it = new ImageTester(w,h); * Graphics g = it.g; * g.backColor = Color.WHITE; * g.fillRect(0,0,w,h); * g.drawLine(0,0,w,h); * g.drawLine(0,0,w,0); * g.drawLine(0,0,0,h); * g.drawLine(w-1,0,w-1,h); * g.drawLine(0,h-1,w,h-1); * g.drawLine(w,0,0,h); * g.drawLine(5,10,5,10); // a single pixel * g.drawLine(5,15,6,16); // two pixels * return it; * } * * public void testRun() * { * g = MainWindow.getMainWindow().getGraphics(); * * test(testDrawLine(), drawLine, "drawLine"); * } * * private void test(ImageTester it, String compressedResults, String title) * { * if (learning) * { * g.drawImage(it,0,0); * Vm.debug("private String "+title+" = \""+it.toString()+"\";"); * } * else * assertEquals(it, compressedResults); * } * } * </pre> * */ public class ImageTester extends Image // guich@565_7 { public Graphics g; public String title; public String name; private byte []bytes; private static int []rgbs; private static StringBuffer sbuf = new StringBuffer(10000); private static ByteArrayStream normal = new ByteArrayStream(65000); private static byte[] normalBytes = normal.getBuffer(); private static ByteArrayStream compressed = new ByteArrayStream(65000); private static byte[] compressedBytes = compressed.getBuffer(); public ImageTester(int width, int height) throws ImageException { super(width, height); create(); } public ImageTester(String name) throws ImageException, IOException { super(name); this.name = name; create(); } private void create() { bytes = new byte[getNrBytes()]; g = getGraphics(); } private int getNrBytes() { int bpp = Settings.screenBPP; int div = 32 / bpp; return ((width+div-1) / div)*div; } /** This testthod is the reason for the creation of this class. * It compares two images byte per byte. */ public boolean equals(Object originalObj) { if (originalObj instanceof ImageTester) { ImageTester original = (ImageTester)originalObj; if (this.width != original.getWidth() || this.height != original.getHeight()) return false; byte[] testb = bytes; byte[] originalb = original.bytes; if (testb.length != originalb.length) return false; int n = testb.length; int h = height; for (int j = 0; j < h; j++) { super.getPixelRow(testb, j); original.getPixelRow(originalb, j); for (int i = 0; i < n; i++) if (testb[i] != originalb[i]) return false; } return true; } if (originalObj instanceof String) // created with the toString below? { normal.reset(); hex2bytes((String)originalObj, compressed); int whoriginal = 0; try { whoriginal = ZLib.inflate(compressed, normal); } catch (IOException e) { e.printStackTrace(); // not the best, better let the user handle it! return false; } int whtest = bytes.length * height; if (whoriginal != whtest) return false; byte[] testbytes = bytes; byte[] originalbytes = normalBytes; int[] palme = rgbs; int n = testbytes.length; int ofs = 0; int h = height; int test=0,orig=0,i=0,j; int w = width; int skip = n - width; for (j = 0; j < h; j++) { super.getPixelRow(testbytes, j); for (i = 0; i < w; i++) { orig = palme[originalbytes[ofs++] & 0xFF]; test = palme[testbytes[i] & 0xFF]; if (test != orig) { new CompareBox(title, rgbs, orig, test, i, j, n, originalbytes, this).popup(); TestCase.output(title+" failed"); MainWindow.getMainWindow().repaintNow(); return false; } } ofs += skip; } return true; } return super.equals(originalObj); } public static void hex2bytes(String str, ByteArrayStream bas) { byte []in = str.getBytes(); int size = in.length >> 1; byte []out = bas.getBuffer(); int ofs = 0; for (int i = 0; i < size; i++) out[i] = (byte)(Convert.digitOf((char)in[ofs++], 16) << 4 | Convert.digitOf((char)in[ofs++], 16)); bas.reset(); bas.skipBytes(size); bas.mark(); } /** Converts this image to String, as a string of hexadecimal numbers. */ public String toString() { StringBuffer sb = sbuf; sb.setLength(0); byte[] b = bytes; int n = b.length; compressed.reset(); normal.reset(); int h = height; for (int j = 0; j < h; j++) { super.getPixelRow(b, j); normal.writeBytes(b, 0, n); } normal.mark(); int len = 0; try { len = ZLib.deflate(normal, compressed, 9); } catch (IOException e) { e.printStackTrace(); // not the best, better let the user handle it! return sb.toString(); } byte []out = compressedBytes; for (int i = 0; i < len; i++) sb.append(Convert.unsigned2hex(out[i],2)); return sb.toString(); } }