sclass HashedBWImage is IBWImage, MakesBWImage { BWImage image; // don't change this afterwards... long hash; bool hashComputed; *(BufferedImage image) { this(bwImage(image)); } *(BWImage *image) { assertNotNull(image); } long hash() { while (!hashComputed) { synchronized { if (!hashComputed) { hash = hashBWImage(image); set hashComputed; } } } ret hash; } equals HashedBWImage o { if (hash() != o.hash()) false; if (!bwImagesIdentical(image, o.image)) { reportHashCollision(this, o); false; } true; } public int hashCode() { ret (int) hash(); } public BWImage get aka getBWImage() { ret image; } public int getWidth() { ret image.getWidth(); } public int getHeight() { ret image.getHeight(); } public BufferedImage getBufferedImage() { ret image.getBufferedImage(); } // check that BWImage wasn't modified void verify { if (hash != 0) assertEquals(hash, hashBWImage(image)); } S classNameForPrinting() { ret cnfp(this, selfType.class, "HashedBWImage"; } toString { ret formatFunctionCall(classNameForPrinting(), w() + "*" + h() + "px", "hash " + longToHex(hash())); } // implement IBWImage public float getFloatPixel(int x, int y) { ret image.getFloatPixel(x, y); } public int getInt(int x, int y) { ret image.getInt(x, y); } }