// Code supplied by the instructor for COM 1204 assignment 6, // spring 2003. Incomplete! See //FIXME comments. package picture; public abstract class Pic { // Operations available to clients of this ADT. // The basic constructors. public static Pic emptyPic () { return new PicEmpty(); } public static Pic pixelPic (Color c) { return new PicPixel (c); } public static Pic beside (Pic p1, Pic p2) { return new PicBeside (p1, p2); } public static Pic flip (Pic p) { return new Pipicture/cFlip (p); } public static Pic rotate (Pic p) { return new PicRotate (p); } public static Pic lefthalf (Pic p) { return new PicLefthalf (p); } // The selectors. public static int height (Pic p) { return p.height(); } public static int width (Pic p) { return p.width(); } public static Color colorAt (Pic p, int i, int j) { return p.colorAt (i, j); } // The mutator. public static void setColorAt (Pic p, int i, int j, Color c) { //FIXME } // The visitor pattern. public static void forEachColor (Pic p, ColorVisitor f) { //FIXME } public static void forEachPixel (Pic p, PixelVisitor f) { //FIXME } public static Pic mapOverPixels (Pic p, PixelVisitor f) { //FIXME } // Private stuff. abstract int height (); abstract int width (); abstract Color colorAt (int i, int j); private static Color error () { throw new IllegalArgumentException(); } // Each of the basic constructors returns a new instance // of the corresponding subclass below. private static class PicEmpty extends Pic { PicEmpty () { } int height () { return 0; } int width () { return 0; } Color colorAt (int i, int j) { return error(); } } private static class PicPixel extends Pic { private Color c; // the Color of this Pic's one pixel PicPixel (Color c) { this.c = c; } int height () { return 1; } int width () { return 1; } Color colorAt (int i, int j) { if (i == 0 && j == 0) return c; else return error(); } } private static class PicBeside extends Pic { private Pic p1; // the left sub-Pic private Pic p2; // the right sub-Pic PicBeside (Pic p1, Pic p2) { this.p1 = p1; this.p2 = p2; } int height () { return Math.max (height (p1), height (p2)); } int width () { return width (p1) + width (p2); } Color colorAt (int i, int j) { int w = width (p1); if (i < w) return colorAt (p1, i, j); else return colorAt (p2, i - w, j); } } private static class PicFlip extends Pic { private Pic p; // the unflipped Pic PicFlip (Pic p) { this.p = p; } int height () { return height (p); } int width () { return width (p); } Color colorAt (int i, int j) { // this is flipped top-to-bottom, i.e. vertically return colorAt (p, i, height (p) - j - 1); } } private static class PicRotate extends Pic { private Pic p; // the unrotated Pic PicRotate (Pic p) { this.p = p; } int height () { return width (p); } int width () { return height (p); } Color colorAt (int i, int j) { // this is a clockwise rotation by 90 degrees return colorAt (p, width (p) - j - 1, i); } } private static class PicLefthalf extends Pic { private Pic p; // the original Pic, with both halves PicLefthalf (Pic p) { this.p = p; } int height () { return height (p); } int width () { return width (p) / 2; } Color colorAt (int i, int j) { if (i < width (this)) return colorAt (p, i, j); else return error(); } } // Client code to implement additional operations. public static boolean isEqual (Color c1, Color c2) { return Color.red (c1) == Color.red (c2) && Color.green (c1) == Color.green (c2) && Color.blue (c1) == Color.blue (c2); } public static boolean isEqual (Pic p1, Pic p2) { int w = Pic.width (p1); int h = Pic.height (p1); if (w != Pic.width (p2) || h != Pic.height (p2)) return false; for (int i = 0; i < w; i = i + 1) for (int j = 0; j < h; j = j + 1) if (! isEqual (Pic.colorAt (p1, i, j), Pic.colorAt (p2, i, j))) return false; return true; } public static Pic above (Pic p1, Pic p2) { return below (p2, p1); } public static Pic below (Pic p1, Pic p2) { return rotate270 (Pic.beside (Pic.rotate (p1), Pic.rotate (p2))); } public static Pic rotate180 (Pic p) { return Pic.rotate (Pic.rotate (p)); } public static Pic rotate270 (Pic p) { return Pic.rotate (rotate180 (p)); } public static Pic flipHorizontal (Pic p) { return rotate270 (Pic.flip (Pic.rotate (p))); } public static Pic righthalf (Pic p) { return rotate180 (Pic.lefthalf (rotate180 (p))); } public static Pic repeatHorizontal (Pic p, int n) { if (n == 0) return Pic.emptyPic(); else if (n == 1) return p; else if (n % 2 > 0) return Pic.beside (repeatHorizontal (p, n - 1), p); else { Pic p2 = repeatHorizontal (p, n / 2); return Pic.beside (p2, p2); } } public static Pic repeatVertical (Pic p, int n) { if (n == 0) return Pic.emptyPic(); else if (n == 1) return p; else if (n % 2 > 0) return above (repeatVertical (p, n - 1), p); else { Pic p2 = repeatVertical (p, n / 2); return above (p2, p2); } } public static Pic repeat (Pic p, int m, int n) { return repeatVertical (repeatHorizontal (p, m), n); } public static Pic solid (Color c, int w, int h) { return repeat (Pic.pixelPic (c), w, h); } public static Pic checkerboard (Pic p1, Pic p2, int m, int n) { if (m == 0 || n == 0) return Pic.emptyPic(); else if (n == 1) return Pic.beside (p1, checkerboard (p2, p1, m - 1, 1)); else return above (checkerboard (p1, p2, m, 1), checkerboard (p2, p1, m, n - 1)); } }