!!!pj1!!!

pj1弄了整整一周 test终于19分的时候眼泪都要出来了 心里蹦出了四个大字母f*** 这个作业动不动就是一个bug卡半天 读题读半天 十分打击自信心 不过还好最终是做出来了 非常感谢小伙伴们的帮助 先上码

import java.util.Arrays;

/* PixImage.java */

/**
 *  The PixImage class represents an image, which is a rectangular grid of
 *  color pixels.  Each pixel has red, green, and blue intensities in the range
 *  0...255.  Descriptions of the methods you must implement appear below.
 *  They include a constructor of the form
 *
 *      public PixImage(int width, int height);
 *
 *  that creates a black (zero intensity) image of the specified width and
 *  height.  Pixels are numbered in the range (0...width - 1, 0...height - 1).
 *
 *  All methods in this class must be implemented to complete Part I.
 *  See the README file accompanying this project for additional details.
 */

public class PixImage {

  /**
   *  Define any variables associated with a PixImage object here.  These
   *  variables MUST be private.
   */
    private int height;
    private int width;
    private short[][][] pixel;
 

  /**
   * PixImage() constructs an empty PixImage with a specified width and height.
   * Every pixel has red, green, and blue intensities of zero (solid black).
   *
   * @param width the width of the image.
   * @param height the height of the image.
   */
  public PixImage(int width, int height) {
      this.width=width;
      this.height=height;
      pixel=new short[width][height][3];
      for(int i=0;i<width;i++){
          for(int j=0;j<height;j++){
              setPixel(i, j, (short)0, (short)0, (short)0);
          }
      }
      } 

  /**
   * getWidth() returns the width of the image.
   *
   * @return the width of the image.
   */
  public int getWidth() {
    // Replace the following line with your solution.
    return width;
  }

  /**
   * getHeight() returns the height of the image.
   *
   * @return the height of the image.
   */
  public int getHeight() {
    // Replace the following line with your solution.
    return height;
  }

  /**
   * getRed() returns the red intensity of the pixel at coordinate (x, y).
   *
   * @param x the x-coordinate of the pixel.
   * @param y the y-coordinate of the pixel.
   * @return the red intensity of the pixel at coordinate (x, y).
   */
  public short getRed(int x, int y) {
    // Replace the following line with your solution.
      return pixel[x][y][0];
  }

  /**
   * getGreen() returns the green intensity of the pixel at coordinate (x, y).
   *
   * @param x the x-coordinate of the pixel.
   * @param y the y-coordinate of the pixel.
   * @return the green intensity of the pixel at coordinate (x, y).
   */
  public short getGreen(int x, int y) {
    // Replace the following line with your solution.
      return pixel[x][y][1];
  }

  /**
   * getBlue() returns the blue intensity of the pixel at coordinate (x, y).
   *
   * @param x the x-coordinate of the pixel.
   * @param y the y-coordinate of the pixel.
   * @return the blue intensity of the pixel at coordinate (x, y).
   */
  public short getBlue(int x, int y) {
    // Replace the following line with your solution.
      return pixel[x][y][2];
  }

  /**
   * setPixel() sets the pixel at coordinate (x, y) to specified red, green,
   * and blue intensities.
   *
   * If any of the three color intensities is NOT in the range 0...255, then
   * this method does NOT change any of the pixel intensities.
   *
   * @param x the x-coordinate of the pixel.
   * @param y the y-coordinate of the pixel.
   * @param red the new red intensity for the pixel at coordinate (x, y).
   * @param green the new green intensity for the pixel at coordinate (x, y).
   * @param blue the new blue intensity for the pixel at coordinate (x, y).
   */
  public void setPixel(int x, int y, short red, short green, short blue) {
        if(pixel[x][y][0]>255||pixel[x][y][0]<0||pixel[x][y][1]>255||
                pixel[x][y][1]<0||pixel[x][y][2]>255||pixel[x][y][2]<0){
            
        }else {
            pixel[x][y][0]=red;
            pixel[x][y][1]=green;
            pixel[x][y][2]=blue;
        }
             // Your solution here.
  }
  
  /**
   * toString() returns a String representation of this PixImage.
   *
   * This method isn't required, but it should be very useful to you when
   * you're debugging your code.  It's up to you how you represent a PixImage
   * as a String.
   *
   * @return a String representation of this PixImage.
   */
  public String toString() {
    // Replace the following line with your solution.
      String message;
      message="[";
      for(int i=0;i<getWidth();i++){
          for(int j=0;j<getHeight();j++)
    message=message+
    " {"+(getRed(i,j)+" "+getGreen(i,j)+" "+getBlue(i,j))+"} ";// Replace the following line with your solution.
      }message=message+"]";
      return message;
  }

  /**
   * boxBlur() returns a blurred version of "this" PixImage.
   *
   * If numIterations == 1, each pixel in the output PixImage is assigned
   * a value equal to the average of its neighboring pixels in "this" PixImage,
   * INCLUDING the pixel itself.
   *
   * A pixel not on the image boundary has nine neighbors--the pixel itself and
   * the eight pixels surrounding it.  A pixel on the boundary has six
   * neighbors if it is not a corner pixel; only four neighbors if it is
   * a corner pixel.  The average of the neighbors is the sum of all the
   * neighbor pixel values (including the pixel itself) divided by the number
   * of neighbors, with non-integer quotients rounded toward zero (as Java does
   * naturally when you divide two integers).
   *
   * Each color (red, green, blue) is blurred separately.  The red input should
   * have NO effect on the green or blue outputs, etc.
   *
   * The parameter numIterations specifies a number of repeated iterations of
   * box blurring to perform.  If numIterations is zero or negative, "this"
   * PixImage is returned (not a copy).  If numIterations is positive, the
   * return value is a newly constructed PixImage.
   *
   * IMPORTANT:  DO NOT CHANGE "this" PixImage!!!  All blurring/changes should
   * appear in the new, output PixImage only.
   *
   * @param numIterations the number of iterations of box blurring.
   * @return a blurred version of "this" PixImage.
   */
  public PixImage boxBlur(int numIterations) {
      if(numIterations==0) return this;
      else{
    PixImage blured=new PixImage(getWidth(),getHeight());
    for(int i=1;i<getWidth()-1;i++){
        for(int j=1;j<getHeight()-1;j++){
                blured.setPixel(i,j,(short) ((getRed(i-1,j-1)+getRed(i-1,j)+getRed(i-1,j+1)+getRed(i,j-1)+
                                getRed(i,j)+getRed(i,j+1)+getRed(i+1,j-1)+getRed(i+1,j)+getRed(i+1,j+1))/9),
                                (short) ((getGreen(i-1,j-1)+getGreen(i-1,j)+getGreen(i-1,j+1)+getGreen(i,j-1)+
                                getGreen(i,j)+getGreen(i,j+1)+getGreen(i+1,j-1)+getGreen(i+1,j)+getGreen(i+1,j+1))/9),
                                (short) ((getBlue(i-1,j-1)+getBlue(i-1,j)+getBlue(i-1,j+1)+getBlue(i,j-1)+
                                getBlue(i,j)+getBlue(i,j+1)+getBlue(i+1,j-1)+getBlue(i+1,j)+getBlue(i+1,j+1))/9));
    }
    }
        blured.setPixel(0,0,(short)((getRed(1,0)+getRed(1,1)+getRed(0,1)+getRed(0,0))/4),
                (short)((getGreen(1,0)+getGreen(1,1)+getGreen(0,1)+getGreen(0,0))/4),
                (short)((getBlue(1,0)+getBlue(1,1)+getBlue(0,1)+getBlue(0,0))/4));
        //up left coner 
        blured.setPixel(0, getHeight()-1,(short)((getRed(0,getHeight()-2)+getRed(0,getHeight()-1)+
                                          getRed(1,getHeight()-2)+getRed(1,getHeight()-1))/4),
                                        (short)((getGreen(0,getHeight()-2)+getGreen(0,getHeight()-1)+
                                          getGreen(1,getHeight()-2)+getGreen(1,getHeight()-1))/4),
                                       (short)((getBlue(0,getHeight()-2)+getBlue(0,getHeight()-1)+
                                          getBlue(1,getHeight()-2)+getBlue(1,getHeight()-1))/4));
        //bottom left coner
        blured.setPixel(getWidth()-1,0,(short)((getRed(getWidth()-2,0)+getRed(getWidth()-2,1)+
                getRed(getWidth()-1,0)+getRed(getWidth()-1,1))/4),(short)((getGreen(getWidth()-2,0)+getGreen(getWidth()-2,1)+
                        getGreen(getWidth()-1,0)+getGreen(getWidth()-1,1))/4),(short)((getBlue(getWidth()-2,0)+getBlue(getWidth()-2,1)+
                                getBlue(getWidth()-1,0)+getBlue(getWidth()-1,1))/4));
    
    // up right coner
        blured.setPixel(getWidth()-1, getHeight()-1, (short)((getRed(getWidth()-2,getHeight()-2)+getRed(getWidth()-2,getHeight()-1)+
                getRed(getWidth()-1,getHeight()-2)+getRed(getWidth()-1,getHeight()-1))/4), (short)((getGreen(getWidth()-2,getHeight()-2)+getGreen(getWidth()-2,getHeight()-1)+
                        getGreen(getWidth()-1,getHeight()-2)+getGreen(getWidth()-1,getHeight()-1))/4), (short)((getBlue(getWidth()-2,getHeight()-2)+getBlue(getWidth()-2,getHeight()-1)+
                                getBlue(getWidth()-1,getHeight()-2)+getBlue(getWidth()-1,getHeight()-1))/4));
   //bottom right coner
        for(int i=1;i<getWidth()-1;i++){
            blured.setPixel(i, 0, (short) ((getRed(i-1,0)+getRed(i-1,1)+
                                    getRed(i,0)+getRed(i,1)+getRed(i+1,0)+getRed(i+1,1))/6), 
                                  (short) ((getGreen(i-1,0)+getGreen(i-1,1)+getGreen(i,0)+
                                      getGreen(i,1)+getGreen(i+1,0)+getGreen(i+1,1))/6),       
                                   (short)((getBlue(i-1,0)+getBlue(i-1,1)+
                                      getBlue(i,0)+getBlue(i,1)+getBlue(i+1,0)+getBlue(i+1,1))/6));
            blured.setPixel(i, getHeight()-1, (short) ((getRed(i-1,getHeight()-1)+getRed(i-1,getHeight()-2)+
                    getRed(i,getHeight()-1)+getRed(i,getHeight()-2)+getRed(i+1,getHeight()-1)+getRed(i+1,getHeight()-2))/6), 
                  (short) ((getGreen(i-1, getHeight()-1)+getGreen(i-1, getHeight()-2)+getGreen(i, getHeight()-1)+
                      getGreen(i, getHeight()-2)+getGreen(i+1, getHeight()-1)+getGreen(i+1, getHeight()-2))/6),       
                   (short)((getBlue(i-1, getHeight()-1)+getBlue(i-1, getHeight()-2)+
                      getBlue(i, getHeight()-1)+getBlue(i, getHeight()-2)+getBlue(i+1, getHeight()-1)+getBlue(i+1, getHeight()-2))/6));
            }//the up and bottom boundary
        for(int j=1;j<getHeight()-1;j++){
            blured.setPixel(0,j,(short) ((getRed(0,j-1)+getRed(0,j)+
                                  getRed(0,j+1)+getRed(1,j-1)+getRed(1,j)+getRed(1,j+1))/6),
                                (short) ((getGreen(0,j-1)+getGreen(0,j)+
                                  getGreen(0,j+1)+getGreen(1,j-1)+getGreen(1,j)+getGreen(1,j+1))/6),
                                (short) ((getBlue(0,j-1)+getBlue(0,j)+
                                  getBlue(0,j+1)+getBlue(1,j-1)+getBlue(1,j)+getBlue(1,j+1))/6));
            blured.setPixel(getWidth()-1,j,
                    (short) ((getRed(getWidth()-1,j-1)+getRed(getWidth()-1,j)+
                    getRed(getWidth()-1,j+1)+getRed(getWidth()-2,j-1)+getRed(getWidth()-2,j)+getRed(getWidth()-2,j+1))/6),
                  (short) ((getGreen(getWidth()-1,j-1)+getGreen(getWidth()-1,j)+
                    getGreen(getWidth()-1,j+1)+getGreen(getWidth()-2,j-1)+getGreen(getWidth()-2,j)+getGreen(getWidth()-2,j+1))/6),
                  (short) ((getBlue(getWidth()-1,j-1)+getBlue(getWidth()-1,j)+
                    getBlue(getWidth()-1,j+1)+getBlue(getWidth()-2,j-1)+getBlue(getWidth()-2,j)+getBlue(getWidth()-2,j+1))/6));
        }// the left and right boundary
        if(numIterations==1) return blured;
        else return blured.boxBlur(numIterations-1);
  }
  }

  /**
   * mag2gray() maps an energy (squared vector magnitude) in the range
   * 0...24,969,600 to a grayscale intensity in the range 0...255.  The map
   * is logarithmic, but shifted so that values of 5,080 and below map to zero.
   *
   * DO NOT CHANGE THIS METHOD.  If you do, you will not be able to get the
   * correct images and pass the autograder.
   *
   * @param mag the energy (squared vector magnitude) of the pixel whose
   * intensity we want to compute.
   * @return the intensity of the output pixel.
   */
  private static short mag2gray(long mag) {
    short intensity = (short) (30.0 * Math.log(1.0 + (double) mag) - 256.0);

    // Make sure the returned intensity is in the range 0...255, regardless of
    // the input value.
    if (intensity < 0) {
      intensity = 0;
    } else if (intensity > 255) {
      intensity = 255;
    }
    return intensity;
  }

  /**
   * sobelEdges() applies the Sobel operator, identifying edges in "this"
   * image.  The Sobel operator computes a magnitude that represents how
   * strong the edge is.  We compute separate gradients for the red, blue, and
   * green components at each pixel, then sum the squares of the three
   * gradients at each pixel.  We convert the squared magnitude at each pixel
   * into a grayscale pixel intensity in the range 0...255 with the logarithmic
   * mapping encoded in mag2gray().  The output is a grayscale PixImage whose
   * pixel intensities reflect the strength of the edges.
   *
   * See http://en.wikipedia.org/wiki/Sobel_operator#Formulation for details.
   *
   * @return a grayscale PixImage representing the edges of the input image.
   * Whiter pixels represent stronger edges.
   */
  public PixImage sobelEdges() {
      PixImage reflected=doReflection();
        long vector[][][][] = new long[getWidth()][getHeight()][3][2];
        long energy[][] = new long[getWidth()][getHeight()];
        PixImage sobeled=new PixImage(getWidth(),getHeight());
  for(int i=0;i<getWidth();i++){
      for(int j=0;j<getHeight();j++){
          vector[i][j][0][0]=1*reflected.getRed(i,j)+0*reflected.getRed(i+1,j)+(-1)*reflected.getRed(i+2,j)+2*reflected.getRed(i,j+1)+0*reflected.getRed(i+1,j+1)
          +(-2)*reflected.getRed(i+2,j+1)+1*reflected.getRed(i,j+2)+0*reflected.getRed(i+1,j+2)+(-1)*reflected.getRed(i+2,j+2);
             vector[i][j][0][1]=1*reflected.getRed(i,j)+2*reflected.getRed(i+1,j)+1*reflected.getRed(i+2,j)+0*reflected.getRed(i,j+1)+0*reflected.getRed(i+1,j+1)
          +0*reflected.getRed(i+2,j+1)+(-1)*reflected.getRed(i,j+2)+(-2)*reflected.getRed(i+1,j+2)+(-1)*reflected.getRed(i+2,j+2);
             //Red's gx&gy
             vector[i][j][1][0]=1*reflected.getGreen(i,j)+0*reflected.getGreen(i+1,j)+(-1)*reflected.getGreen(i+2,j)+2*reflected.getGreen(i,j+1)+0*reflected.getGreen(i+1,j+1)
          +(-2)*reflected.getGreen(i+2,j+1)+1*reflected.getGreen(i,j+2)+0*reflected.getGreen(i+1,j+2)+(-1)*reflected.getGreen(i+2,j+2);
             vector[i][j][1][1]=1*reflected.getGreen(i,j)+2*reflected.getGreen(i+1,j)+1*reflected.getGreen(i+2,j)+0*reflected.getGreen(i,j+1)+0*reflected.getGreen(i+1,j+1)
          +0*reflected.getGreen(i+2,j+1)+(-1)*reflected.getGreen(i,j+2)+(-2)*reflected.getGreen(i+1,j+2)+(-1)*reflected.getGreen(i+2,j+2);
             //Green's gx&gy
             vector[i][j][2][0]=1*reflected.getBlue(i,j)+0*reflected.getBlue(i+1,j)+(-1)*reflected.getBlue(i+2,j)+2*reflected.getBlue(i,j+1)+0*reflected.getBlue(i+1,j+1)
          +(-2)*reflected.getBlue(i+2,j+1)+1*reflected.getBlue(i,j+2)+0*reflected.getBlue(i+1,j+2)+(-1)*reflected.getBlue(i+2,j+2);
             vector[i][j][2][1]=1*reflected.getBlue(i,j)+2*reflected.getBlue(i+1,j)+1*reflected.getBlue(i+2,j)+0*reflected.getBlue(i,j+1)+0*reflected.getBlue(i+1,j+1)
          +0*reflected.getBlue(i+2,j+1)+(-1)*reflected.getBlue(i,j+2)+(-2)*reflected.getBlue(i+1,j+2)+(-1)*reflected.getBlue(i+2,j+2);
             //Blue's gx&gy
             energy[i][j]=vector[i][j][0][0]*vector[i][j][0][0]+vector[i][j][0][1]*vector[i][j][0][1]+vector[i][j][1][0]*vector[i][j][1][0]
                     +vector[i][j][1][1]*vector[i][j][1][1]+vector[i][j][2][0]*vector[i][j][2][0]+vector[i][j][2][1]*vector[i][j][2][1];
          sobeled.setPixel(i,j,mag2gray(energy[i][j]),mag2gray(energy[i][j]),mag2gray(energy[i][j]));
      }
  }
  return sobeled;

  }

  private PixImage doReflection(){
        //将原数列向外围扩大一圈
        PixImage reflect=new PixImage(getWidth()+2,getHeight()+2);
        for(int j=0;j<getHeight();j++)
               reflect.setPixel(0,j+1,getRed(0,j),getGreen(0,j),getBlue(0,j));    
        //left boundary
        for(int j=0;j<getHeight();j++)
               reflect.setPixel(reflect.getWidth()-1,j+1,getRed(getWidth()-1,j),getGreen(getWidth()-1,j),getBlue(getWidth()-1,j));
       //right boundary
        for(int j=0;j<getWidth();j++)
               reflect.setPixel(j+1,0,getRed(j,0),getGreen(j,0),getBlue(j,0));
        //up boundary
        for(int j=0;j<getWidth();j++)
               reflect.setPixel(j+1,reflect.getHeight()-1,getRed(j,getHeight()-1),getGreen(j,getHeight()-1),getBlue(j,getHeight()-1));
        //bottom boundary
        reflect.setPixel(0, 0, getRed(0,0), getGreen(0,0), getBlue(0,0));
        reflect.setPixel(reflect.getWidth()-1, 0, getRed(getWidth()-1,0), getGreen(getWidth()-1,0), getBlue(getWidth()-1,0));
        reflect.setPixel(0, reflect.getHeight()-1, getRed(0,getHeight()-1), getGreen(0,getHeight()-1), getBlue(0,getHeight()-1));
        reflect.setPixel(reflect.getWidth()-1,reflect.getHeight()-1,getRed(getWidth()-1,getHeight()-1), getGreen(getWidth()-1,getHeight()-1), getBlue(getWidth()-1,getHeight()-1));
        //4个特殊点
        for(int i=1;i<reflect.getWidth()-1;i++){
              for(int j=1;j<reflect.getHeight()-1;j++){
                  reflect.setPixel(i, j, getRed(i-1,j-1), getGreen(i-1,j-1), getBlue(i-1,j-1));
              }
          } //复制中央位置
        return reflect;
    }

  /**
   * TEST CODE:  YOU DO NOT NEED TO FILL IN ANY METHODS BELOW THIS POINT.
   * You are welcome to add tests, though.  Methods below this point will not
   * be tested.  This is not the autograder, which will be provided separately.
   */


  /**
   * doTest() checks whether the condition is true and prints the given error
   * message if it is not.
   *
   * @param b the condition to check.
   * @param msg the error message to print if the condition is false.
   */
  private static void doTest(boolean b, String msg) {
    if (b) {
      System.out.println("Good.");
    } else {
      System.err.println(msg);
    }
  }

  /**
   * array2PixImage() converts a 2D array of grayscale intensities to
   * a grayscale PixImage.
   *
   * @param pixels a 2D array of grayscale intensities in the range 0...255.
   * @return a new PixImage whose red, green, and blue values are equal to
   * the input grayscale intensities.
   */
  private static PixImage array2PixImage(int[][] pixels) {
    int width = pixels.length;
    int height = pixels[0].length;
    PixImage image = new PixImage(width, height);

    for (int x = 0; x < width; x++) {
      for (int y = 0; y < height; y++) {
        image.setPixel(x, y, (short) pixels[x][y], (short) pixels[x][y],
                       (short) pixels[x][y]);
      }
    }

    return image;
  }

  /**
   * equals() checks whether two images are the same, i.e. have the same
   * dimensions and pixels.
   *
   * @param image a PixImage to compare with "this" PixImage.
   * @return true if the specified PixImage is identical to "this" PixImage.
   */
  public boolean equals(PixImage image) {
    int width = getWidth();
    int height = getHeight();

    if (image == null ||
        width != image.getWidth() || height != image.getHeight()) {
      return false;
    }

    for (int x = 0; x < width; x++) {
      for (int y = 0; y < height; y++) {
        if (! (getRed(x, y) == image.getRed(x, y) &&
               getGreen(x, y) == image.getGreen(x, y) &&
               getBlue(x, y) == image.getBlue(x, y))) {
          return false;
        }
      }
    }
    return true;
  }

  /**
   * main() runs a series of tests to ensure that the convolutions (box blur
   * and Sobel) are correct.
   */
  public static void main(String[] args) {
    // Be forwarned that when you write arrays directly in Java as below,
    // each "row" of text is a column of your image--the numbers get
    // transposed.
    PixImage image1 = array2PixImage(new int[][] { { 0, 10, 240 },
                                                   { 30, 120, 250 },
                                                   { 80, 250, 255 } });

    System.out.println("Testing getWidth/getHeight on a 3x3 image.  " +
                       "Input image:");
    System.out.print(image1);
    System.out.println(image1.getWidth());
    doTest(image1.getWidth() == 3 && image1.getHeight() == 3,
           "Incorrect image width and height.");

    System.out.println("Testing blurring on a 3x3 image.");
    doTest(image1.boxBlur(1).equals(
           array2PixImage(new int[][] { { 40, 108, 155 },
                                        { 81, 137, 187 },
                                        { 120, 164, 218 } })),
           "Incorrect box blur (1 rep):
" + image1.boxBlur(1));
    doTest(image1.boxBlur(2).equals(
           array2PixImage(new int[][] { { 91, 118, 146 },
                                        { 108, 134, 161 },
                                        { 125, 151, 176 } })),
           "Incorrect box blur (2 rep):
" + image1.boxBlur(2));
    doTest(image1.boxBlur(2).equals(image1.boxBlur(1).boxBlur(1)),
           "Incorrect box blur (1 rep + 1 rep):
" +
           image1.boxBlur(2) + image1.boxBlur(1).boxBlur(1));

    System.out.println("Testing edge detection on a 3x3 image.");
    doTest(image1.sobelEdges().equals(
           array2PixImage(new int[][] { { 104, 189, 180 },
                                        { 160, 193, 157 },
                                        { 166, 178, 96 } })),
           "Incorrect Sobel:
" + image1.sobelEdges());


    PixImage image2 = array2PixImage(new int[][] { { 0, 100, 100 },
                                                   { 0, 0, 100 } });
    System.out.println("Testing getWidth/getHeight on a 2x3 image.  " +
                       "Input image:");
    System.out.println(image2);
    System.out.println(image2.doReflection());
    doTest(image2.getWidth() == 2 && image2.getHeight() == 3,
           "Incorrect image width and height.");

    System.out.println("Testing blurring on a 2x3 image.");
    doTest(image2.boxBlur(1).equals(
           array2PixImage(new int[][] { { 25, 50, 75 },
                                        { 25, 50, 75 } })),
           "Incorrect box blur (1 rep):
" + image2.boxBlur(1));

    System.out.println("Testing edge detection on a 2x3 image.");
    doTest(image2.sobelEdges().equals(
           array2PixImage(new int[][] { { 122, 143, 74 },
                                        { 74, 143, 122 } })),
           "Incorrect Sobel:
" + image2.sobelEdges());
  }
}
PixImage
/* RunLengthEncoding.java */

/**
 *  The RunLengthEncoding class defines an object that run-length encodes
 *  a PixImage object.  Descriptions of the methods you must implement appear
 *  below.  They include constructors of the form
 *
 *      public RunLengthEncoding(int width, int height);
 *      public RunLengthEncoding(int width, int height, int[] red, int[] green,
 *                               int[] blue, int[] runLengths) {
 *      public RunLengthEncoding(PixImage image) {
 *
 *  that create a run-length encoding of a PixImage having the specified width
 *  and height.
 *
 *  The first constructor creates a run-length encoding of a PixImage in which
 *  every pixel is black.  The second constructor creates a run-length encoding
 *  for which the runs are provided as parameters.  The third constructor
 *  converts a PixImage object into a run-length encoding of that image.
 *
 *  See the README file accompanying this project for additional details.
 */

import java.util.Iterator;

public class RunLengthEncoding implements Iterable {

  /**
   *  Define any variables associated with a RunLengthEncoding object here.
   *  These variables MUST be private.
   */
private DListNode1 head;
private DListNode1 tail;
private int size;
private int width;
private int height;
private int k;

  /**
   *  The following methods are required for Part II.
   */

  /**
   *  RunLengthEncoding() (with two parameters) constructs a run-length
   *  encoding of a black PixImage of the specified width and height, in which
   *  every pixel has red, green, and blue intensities of zero.
   *
   *  @param width the width of the image.
   *  @param height the height of the image.
   */

  public RunLengthEncoding(int width, int height) {
    this.width=width;
    this.height=height;
    head=new DListNode1(0,width*height);
    tail=head;
    tail.prev=null;
    head.next=null;
    size=1;// Your solution here.
  }

  /**
   *  RunLengthEncoding() (with six parameters) constructs a run-length
   *  encoding of a PixImage of the specified width and height.  The runs of
   *  the run-length encoding are taken from four input arrays of equal length.
   *  Run i has length runLengths[i] and RGB intensities red[i], green[i], and
   *  blue[i].
   *
   *  @param width the width of the image.
   *  @param height the height of the image.
   *  @param red is an array that specifies the red intensity of each run.
   *  @param green is an array that specifies the green intensity of each run.
   *  @param blue is an array that specifies the blue intensity of each run.
   *  @param runLengths is an array that specifies the length of each run.
   *
   *  NOTE:  All four input arrays should have the same length (not zero).
   *  All pixel intensities in the first three arrays should be in the range
   *  0...255.  The sum of all the elements of the runLengths array should be
   *  width * height.  (Feel free to quit with an error message if any of these
   *  conditions are not met--though we won't be testing that.)
   */

  public RunLengthEncoding(int width, int height, int[] red, int[] green,
                           int[] blue, int[] runLengths) {
          this.width=width;
          this.height=height;
          head=new DListNode1(red[0],green[0],blue[0],runLengths[0]);
          tail=head;
          tail.prev=null;
          head.next=null;
          size=1;
          int k=runLengths.length;
      for(int i=1;i<k;i++){
          DListNode1 theNext = new DListNode1(red[i],green[i],blue[i],runLengths[i]);
          tail.next=theNext;
          theNext.prev=tail;
          tail=theNext;
          size++;}
    // Your solution here.
  }
 
  /**
   *  getWidth() returns the width of the image that this run-length encoding
   *  represents.
   *
   *  @return the width of the image that this run-length encoding represents.
   */

  public int getWidth() {
    // Replace the following line with your solution.
    return width;
  }

  /**
   *  getHeight() returns the height of the image that this run-length encoding
   *  represents.
   *
   *  @return the height of the image that this run-length encoding represents.
   */
  public int getHeight() {
    // Replace the following line with your solution.
    return height;
  }

  /**
   *  iterator() returns a newly created RunIterator that can iterate through
   *  the runs of this RunLengthEncoding.
   *
   *  @return a newly created RunIterator object set to the first run of this
   *  RunLengthEncoding.
   */
  public RunIterator iterator() {
    RunIterator run=new RunIterator(head);
    return run;
   
    // Replace the following line with your solution.
    // You'll want to construct a new RunIterator, but first you'll need to
    // write a constructor in the RunIterator class.
  }
 
  /**
   *  toPixImage() converts a run-length encoding of an image into a PixImage
   *  object.
   *
   *  @return the PixImage that this RunLengthEncoding encodes.
   */
  public PixImage toPixImage() {
    PixImage converted=new PixImage(width,height);
    RunIterator k=iterator();
    int n0,m0,n1,m1,sumOfruns;
    int[] next; 
    sumOfruns=0; 
    m0=0;
    n0=0;
    while(k.hasNext()){
    next=k.next();
    sumOfruns=sumOfruns+next[0];
    m1=sumOfruns%width;
    n1=sumOfruns/width;
    if (m1==0){m1=width;
    n1=n1-1; }
    if(n1>n0){
        for(int i=m0;i<width;i++){
              converted.setPixel(i,n0,(short)next[1],(short)next[2],(short)next[3]);
              }
        for(int j=n0+1;j<n1;j++){
            for(int i=0;i<width;i++){
              converted.setPixel(i,j,(short)next[1],(short)next[2],(short)next[3]);
          }
        }
        for(int i=0;i<m1;i++){
            converted.setPixel(i,n1,(short)next[1],(short)next[2],(short)next[3]);
        }
          }
          else{
                for(int i=m0;i<m1;i++){
                      converted.setPixel(i,n1,(short)next[1],(short)next[2],(short)next[3]);
                      }    
          }
        m0=m1;
        n0=n1;
        
    }
        
  // Replace the following line with your solution.
    return converted;
  }

  /**
   *  toString() returns a String representation of this RunLengthEncoding.
   *
   *  This method isn't required, but it should be very useful to you when
   *  you're debugging your code.  It's up to you how you represent
   *  a RunLengthEncoding as a String.
   *
   *  @return a String representation of this RunLengthEncoding.
   */
  public String toString() {
    String h=new String();
    DListNode1 current=head;
    h="[";
    while (current != null){
        h=h+"{"+current.red+current.green+current.blue+"|"+current.num+"}";
        current=current.next;
    }
        h=h+"]";// Replace the following line with your solution.
    return h;
  }


  /**
   *  The following methods are required for Part III.
   */

  /**
   *  RunLengthEncoding() (with one parameter) is a constructor that creates
   *  a run-length encoding of a specified PixImage.
   * 
   *  Note that you must encode the image in row-major format, i.e., the second
   *  pixel should be (1, 0) and not (0, 1).
   *
   *  @param image is the PixImage to run-length encode.
   */
  public RunLengthEncoding(PixImage image) {
    int[] red=new int[image.getWidth()*image.getHeight()];
    int[] green=new int[image.getWidth()*image.getHeight()];
    int[] blue=new int[image.getWidth()*image.getHeight()];
    int[] num=new int[image.getWidth()*image.getHeight()];
    k=0;
    red[0]=image.getRed(0,0);
    green[0]=image.getGreen(0,0);
    blue[0]=image.getBlue(0,0);
    num[0]=1;
    for(int j=0;j<image.getHeight();j++){
        for(int i=0;i<image.getWidth();i++){
            if(i==image.getWidth()-1&&j==image.getHeight()-1){
                break;}    
            else if(i==image.getWidth()-1&&j!=image.getHeight()-1){
                if(image.getRed(i,j)==image.getRed(0,j+1)&&image.getGreen(i,j)==image.getGreen(0,j+1)
                        &&image.getBlue(i,j)==image.getBlue(0,j+1)){
                   num[k]++;}
                else{
                    k=k+1;
                    num[k]=1;
                    red[k]=image.getRed(0,j+1);
                    green[k]=image.getGreen(0,j+1);
                    blue[k]=image.getBlue(0,j+1);
                    }    
                }else if(image.getRed(i,j)==image.getRed(i+1,j)
                        &&image.getGreen(i,j)==image.getGreen(i+1,j)&&image.getBlue(i,j)==image.getBlue(i+1,j)){
                    num[k]++;}
                    else {
                        k=k+1;
                        num[k]=1;
                        red[k]=image.getRed(i+1,j);
                        green[k]=image.getGreen(i+1,j);
                        blue[k]=image.getBlue(i+1,j);
                        }
                    }    
    }
    // Your solution here, but you should probably leave the following line
    // at the end.
      this.width=image.getWidth();
      this.height=image.getHeight();
   for(int i=0;i<=k;i++){
   DListNode1 theNext = new DListNode1(red[i],green[i],blue[i],num[i]);
   if(i==0) {head=theNext;
             tail=head;
                tail.prev=null;
             head.next=null;
             size++;}
   else {tail.next=theNext;
         theNext.prev=tail;
         theNext.next=null;
         tail=theNext;
         size++;
       
   }
   }

  check();
     
  }

  /**
   *  check() walks through the run-length encoding and prints an error message
   *  if two consecutive runs have the same RGB intensities, or if the sum of
   *  all run lengths does not equal the number of pixels in the image.
   */
  public void check() {
     int sumLength=0;
     DListNode1 current; 
     current=head;
          while(current.next!=null){
          int r0=current.red;
          int g0=current.green;
          int b0=current.blue;
          int r1=current.next.red;
          int g1=current.next.green;
          int b1=current.next.blue;
         if(r0==r1&&g0==g1&&b0==b1){
             System.out.println("ERROR:consecutive same runs");    
    }    if(current.num<1||tail.num<1){
             System.out.println("ERROR:runlength less than 1"); 
    }
         sumLength=sumLength+current.num;
         current=current.next;
         }
          sumLength=sumLength+tail.num;
        
    if(sumLength!=width*height){
        System.out.println("ERROR:unequal sum with pixels ");    
    }     
    }
   
  


  /**
   *  The following method is required for Part IV.
   */

  /**
   *  setPixel() modifies this run-length encoding so that the specified color
   *  is stored at the given (x, y) coordinates.  The old pixel value at that
   *  coordinate should be overwritten and all others should remain the same.
   *  The updated run-length encoding should be compressed as much as possible;
   *  there should not be two consecutive runs with exactly the same RGB color.
   *
   *  @param x the x-coordinate of the pixel to modify.
   *  @param y the y-coordinate of the pixel to modify.
   *  @param red the new red intensity to store at coordinate (x, y).
   *  @param green the new green intensity to store at coordinate (x, y).
   *  @param blue the new blue intensity to store at coordinate (x, y).
   */
  public void setPixel(int x, int y, short red, short green, short blue) {
       int location,totalLength,nth;
       location=x+y*width+1;
       DListNode1 current;
       current=head;
       totalLength=current.num;
       if(totalLength>=location){
           nth=location;
       }
       else{
           while(totalLength<location){
       current=current.next;
       totalLength=totalLength+current.num;}
       nth=current.num-(totalLength-location);}


if(current.red==red&&current.green==green&&current.blue==blue){
    }
 else{
     if(current.num==1){
           current.red=red;
           current.green=green;
           current.blue=blue;
           if(current!=head&&current!=tail){
           if(red==current.prev.red&&green==current.prev.green
                   &&blue==current.prev.blue&&red==current.next.red&&green==current.next.green
                   &&blue==current.next.blue){
               current.prev.num=current.prev.num+1+current.next.num;
               if(current.next==tail){
               current.prev.next=null;
               current.prev=tail;
                }
               else{
                  current.prev.next=current.next.next;
                  current.next.next.prev=current.prev;
               }
           }
           else if(red==current.next.red&&green==current.next.green
                   &&blue==current.next.blue){
               current.next.num=current.next.num+1;;
               current.prev.next=current.next;
               current.next.prev=current.prev;
           }
           else if(red==current.prev.red&&green==current.prev.green
                   &&blue==current.prev.blue){
               current.prev.num=current.prev.num+1;
               current.prev.next=current.next;
               current.next.prev=current.prev;
           }
           }
           if(current==head){
               if(red==current.next.red&&green==current.next.green
                       &&blue==current.next.blue){
                   current.next.num=current.next.num+current.num;
                   current.next.prev=null;
                   head=current.next;
               }
               
           }
           if(current==tail){
               if(current.red==current.prev.red&&current.green==current.prev.green
                       &&current.blue==current.prev.blue){
                   current.prev.num=current.prev.num+current.num;
                   current.prev.next=null;
                   tail=current.prev;
               }
           }
       }
    if(current.num>1){
           if(current!=head&&current!=tail){
               if(nth==1){
                   if(current.prev.red==red&&current.prev.green==green&&current.prev.blue==blue){
                       current.prev.num++;
                       current.num--;
                   }else {
                       DListNode1 changed=new DListNode1(red,green,blue,1);
                       insertBefore(current,changed);

                   }
               }
               if(nth==current.num){
                   if(current.next.red==red&&current.next.green==green&&current.next.blue==blue){
                       current.next.num++;
                       current.num--;
               }else{
                   DListNode1 changed=new DListNode1(red,green,blue,1);
                   insertAfter(current,changed);

               }
               
           } 
            if (nth>1&&nth<current.num){
                DListNode1 theFront=new DListNode1(current.red,current.green,current.blue,nth-1);
                insertBefore(current,theFront);
                DListNode1 changed=new DListNode1(red,green,blue,1);
                insertBefore(current,changed);
                current.num=current.num-nth+2;
            }
       }
        if(current==head){
            if(nth==1){
                 DListNode1 changed=new DListNode1(red,green,blue,1);
                 insertAsHead(current,changed);
            }
            else if(nth==current.num){ 
                if(current.next.red==red&&current.next.green==green&&current.next.blue==blue){
                   current.next.num++;
                   current.num--;
           }else{
               DListNode1 changed=new DListNode1(red,green,blue,1);
               insertAfter(current,changed);
        }
       }else if(nth>1&&nth<current.num){
            DListNode1 theAfter=new DListNode1(current.red,current.green,current.blue,current.num-nth);
            insertAfter(current,theAfter);
            DListNode1 changed=new DListNode1(red,green,blue,1);
            insertAfter(current,changed);
            current.num=nth-1;
           
       }
    }
        if(current==tail){
            if(nth==current.num){
                 DListNode1 changed=new DListNode1(red,green,blue,1);
                insertAsTail(current,changed);
            }
            else if(nth==1){ 
                if(current.prev.red==red&&current.prev.green==green&&current.prev.blue==blue){
                   current.prev.num++;
                   current.num--;
           }else{
               DListNode1 changed=new DListNode1(red,green,blue,1);
               insertBefore(current,changed);
        }
       }else if(nth>1&&nth<current.num){
            DListNode1 theFront=new DListNode1(current.red,current.green,current.blue,nth-1);
            insertBefore(current,theFront);
            DListNode1 changed=new DListNode1(red,green,blue,1);
            insertBefore(current,changed);
            current.num=current.num-nth+2;
           
       }
        }
        }
 }
      // Your solution here, but you should probably leave the following line
    //   at the end.
    check();
  }
  private void insertAsHead(DListNode1 cur,DListNode1 inserted){
      inserted.next=cur;
      inserted.prev=null;
      cur.prev=inserted;
      head=inserted;
      cur.num--;
  }
  private void insertAsTail(DListNode1 cur,DListNode1 inserted){
      inserted.prev=cur;
      inserted.next=null;
      cur.next=inserted;
      tail=inserted;
      cur.num--;
  }
  private void insertBefore(DListNode1 cur,DListNode1 inserted){
       cur.prev.next=inserted;
       inserted.prev=cur.prev;
       inserted.next=cur;
       cur.prev=inserted;
       cur.num--;
  }
  private void insertAfter(DListNode1 cur,DListNode1 inserted){
       cur.next.prev=inserted;
       inserted.prev=cur;
       inserted.next=cur.next;
       cur.next=inserted;
       cur.num--;
  }

  /**
   * TEST CODE:  YOU DO NOT NEED TO FILL IN ANY METHODS BELOW THIS POINT.
   * You are welcome to add tests, though.  Methods below this point will not
   * be tested.  This is not the autograder, which will be provided separately.
   */


  /**
   * doTest() checks whether the condition is true and prints the given error
   * message if it is not.
   *
   * @param b the condition to check.
   * @param msg the error message to print if the condition is false.
   */
  private static void doTest(boolean b, String msg) {
    if (b) {
      System.out.println("Good.");
    } else {
      System.err.println(msg);
    }
  }

  /**
   * array2PixImage() converts a 2D array of grayscale intensities to
   * a grayscale PixImage.
   *
   * @param pixels a 2D array of grayscale intensities in the range 0...255.
   * @return a new PixImage whose red, green, and blue values are equal to
   * the input grayscale intensities.
   */
  private static PixImage array2PixImage(int[][] pixels) {
    int width = pixels.length;
    int height = pixels[0].length;
    PixImage image = new PixImage(width, height);

    for (int x = 0; x < width; x++) {
      for (int y = 0; y < height; y++) {
        image.setPixel(x, y, (short) pixels[x][y], (short) pixels[x][y],
                       (short) pixels[x][y]);
      }
    }

    return image;
  }

  /**
   * setAndCheckRLE() sets the given coordinate in the given run-length
   * encoding to the given value and then checks whether the resulting
   * run-length encoding is correct.
   *
   * @param rle the run-length encoding to modify.
   * @param x the x-coordinate to set.
   * @param y the y-coordinate to set.
   * @param intensity the grayscale intensity to assign to pixel (x, y).
   */
  private static void setAndCheckRLE(RunLengthEncoding rle,
                                     int x, int y, int intensity) {
    rle.setPixel(x, y,
                 (short) intensity, (short) intensity, (short) intensity);
    rle.check();
  }

  /**
   * main() runs a series of tests of the run-length encoding code.
   */
  public static void main(String[] args) {
    // Be forwarned that when you write arrays directly in Java as below,
    // each "row" of text is a column of your image--the numbers get
    // transposed.
    PixImage image1 = array2PixImage(new int[][] { { 0, 3, 6 },
                                                   { 1, 4, 7 },
                                                   { 2, 5, 8 } });

    System.out.println("Testing one-parameter RunLengthEncoding constuctor " +
                       "on a 3x3 image.  Input image:");
    System.out.print(image1);
    
    RunLengthEncoding rle1 = new RunLengthEncoding(image1);
    rle1.check();
    System.out.println("Testing getWidth/getHeight on a 3x3 encoding.");
    doTest(rle1.getWidth() == 3 && rle1.getHeight() == 3,
           "RLE1 has wrong dimensions");

    System.out.println("Testing toPixImage() on a 3x3 encoding.");
    doTest(image1.equals(rle1.toPixImage()),
           "image1 -> RLE1 -> image does not reconstruct the original image");
    System.out.println(rle1.toPixImage());
    System.out.println("Testing setPixel() on a 3x3 encoding.");
    setAndCheckRLE(rle1, 0, 0, 42);
    image1.setPixel(0, 0, (short) 42, (short) 42, (short) 42);
    doTest(rle1.toPixImage().equals(image1),
           /*
                       array2PixImage(new int[][] { { 42, 3, 6 },
                                                    { 1, 4, 7 },
                                                    { 2, 5, 8 } })),
           */
           "Setting RLE1[0][0] = 42 fails.");

    System.out.println("Testing setPixel() on a 3x3 encoding.");
    setAndCheckRLE(rle1, 1, 0, 42);
    image1.setPixel(1, 0, (short) 42, (short) 42, (short) 42);
    doTest(rle1.toPixImage().equals(image1),
           "Setting RLE1[1][0] = 42 fails.");

    System.out.println("Testing setPixel() on a 3x3 encoding.");
    setAndCheckRLE(rle1, 0, 1, 2);
    image1.setPixel(0, 1, (short) 2, (short) 2, (short) 2);
    doTest(rle1.toPixImage().equals(image1),
           "Setting RLE1[0][1] = 2 fails.");

    System.out.println("Testing setPixel() on a 3x3 encoding.");
    setAndCheckRLE(rle1, 0, 0, 0);
    image1.setPixel(0, 0, (short) 0, (short) 0, (short) 0);
    doTest(rle1.toPixImage().equals(image1),
           "Setting RLE1[0][0] = 0 fails.");

    System.out.println("Testing setPixel() on a 3x3 encoding.");
    setAndCheckRLE(rle1, 2, 2, 7);
    image1.setPixel(2, 2, (short) 7, (short) 7, (short) 7);
    doTest(rle1.toPixImage().equals(image1),
           "Setting RLE1[2][2] = 7 fails.");

    System.out.println("Testing setPixel() on a 3x3 encoding.");
    setAndCheckRLE(rle1, 2, 2, 42);
    image1.setPixel(2, 2, (short) 42, (short) 42, (short) 42);
    doTest(rle1.toPixImage().equals(image1),
           "Setting RLE1[2][2] = 42 fails.");

    System.out.println("Testing setPixel() on a 3x3 encoding.");
    setAndCheckRLE(rle1, 1, 2, 42);
    image1.setPixel(1, 2, (short) 42, (short) 42, (short) 42);
    doTest(rle1.toPixImage().equals(image1),
           "Setting RLE1[1][2] = 42 fails.");


    PixImage image2 = array2PixImage(new int[][] { { 2, 3, 5 },
                                                   { 2, 4, 5 },
                                                   { 3, 4, 6 } });

    System.out.println("Testing one-parameter RunLengthEncoding constuctor " +
                       "on another 3x3 image.  Input image:");
    System.out.print(image2);
    RunLengthEncoding rle2 = new RunLengthEncoding(image2);
    rle2.check();
    System.out.println("Testing getWidth/getHeight on a 3x3 encoding.");
    doTest(rle2.getWidth() == 3 && rle2.getHeight() == 3,
           "RLE2 has wrong dimensions");

    System.out.println("Testing toPixImage() on a 3x3 encoding.");
    doTest(rle2.toPixImage().equals(image2),
           "image2 -> RLE2 -> image does not reconstruct the original image");

    System.out.println("Testing setPixel() on a 3x3 encoding.");
    setAndCheckRLE(rle2, 0, 1, 2);
    image2.setPixel(0, 1, (short) 2, (short) 2, (short) 2);
    doTest(rle2.toPixImage().equals(image2),
           "Setting RLE2[0][1] = 2 fails.");

    System.out.println("Testing setPixel() on a 3x3 encoding.");
    setAndCheckRLE(rle2, 2, 0, 2);
    image2.setPixel(2, 0, (short) 2, (short) 2, (short) 2);
    doTest(rle2.toPixImage().equals(image2),
           "Setting RLE2[2][0] = 2 fails.");
  

    PixImage image3 = array2PixImage(new int[][] { { 0, 5 },
                                                   { 1, 6 },
                                                   { 2, 7 },
                                                   { 3, 8 },
                                                   { 4, 9 } });

    System.out.println("Testing one-parameter RunLengthEncoding constuctor " +
                       "on a 5x2 image.  Input image:");
    System.out.print(image3);
    RunLengthEncoding rle3 = new RunLengthEncoding(image3);
    rle3.check();
    System.out.println("Testing getWidth/getHeight on a 5x2 encoding.");
    doTest(rle3.getWidth() == 5 && rle3.getHeight() == 2,
           "RLE3 has wrong dimensions");

    System.out.println("Testing toPixImage() on a 5x2 encoding.");
    doTest(rle3.toPixImage().equals(image3),
           "image3 -> RLE3 -> image does not reconstruct the original image");

    System.out.println("Testing setPixel() on a 5x2 encoding.");
    setAndCheckRLE(rle3, 4, 0, 6);
    image3.setPixel(4, 0, (short) 6, (short) 6, (short) 6);
    doTest(rle3.toPixImage().equals(image3),
           "Setting RLE3[4][0] = 6 fails.");

    System.out.println("Testing setPixel() on a 5x2 encoding.");
    setAndCheckRLE(rle3, 0, 1, 6);
    image3.setPixel(0, 1, (short) 6, (short) 6, (short) 6);
    doTest(rle3.toPixImage().equals(image3),
           "Setting RLE3[0][1] = 6 fails.");

    System.out.println("Testing setPixel() on a 5x2 encoding.");
    setAndCheckRLE(rle3, 0, 0, 1);
    image3.setPixel(0, 0, (short) 1, (short) 1, (short) 1);
    doTest(rle3.toPixImage().equals(image3),
           "Setting RLE3[0][0] = 1 fails.");


    PixImage image4 = array2PixImage(new int[][] { { 0, 3 },
                                                   { 1, 4 },
                                                   { 2, 5 } });

    System.out.println("Testing one-parameter RunLengthEncoding constuctor " +
                       "on a 3x2 image.  Input image:");
    System.out.print(image4);
    RunLengthEncoding rle4 = new RunLengthEncoding(image4);
    rle4.check();
    System.out.println("Testing getWidth/getHeight on a 3x2 encoding.");
    doTest(rle4.getWidth() == 3 && rle4.getHeight() == 2,
           "RLE4 has wrong dimensions");

    System.out.println("Testing toPixImage() on a 3x2 encoding.");
    doTest(rle4.toPixImage().equals(image4),
           "image4 -> RLE4 -> image does not reconstruct the original image");

    System.out.println("Testing setPixel() on a 3x2 encoding.");
    setAndCheckRLE(rle4, 2, 0, 0);
    image4.setPixel(2, 0, (short) 0, (short) 0, (short) 0);
    doTest(rle4.toPixImage().equals(image4),
           "Setting RLE4[2][0] = 0 fails.");

    System.out.println("Testing setPixel() on a 3x2 encoding.");
    setAndCheckRLE(rle4, 1, 0, 0);
    image4.setPixel(1, 0, (short) 0, (short) 0, (short) 0);
    doTest(rle4.toPixImage().equals(image4),
           "Setting RLE4[1][0] = 0 fails.");

    System.out.println("Testing setPixel() on a 3x2 encoding.");
    setAndCheckRLE(rle4, 1, 0, 1);
    image4.setPixel(1, 0, (short) 1, (short) 1, (short) 1);
    doTest(rle4.toPixImage().equals(image4),
           "Setting RLE4[1][0] = 1 fails.");
  }
}
RunLengthEncoding
/* RunIterator.java */

/**
 *  The RunIterator class iterates over a RunLengthEncoding and allows other
 *  classes to inspect the runs in a run-length encoding, one run at a time.
 *  A newly constructed RunIterator "points" to the first run in the encoding
 *  used to construct it.  Each time next() is invoked, it returns a run
 *  (represented as an array of four ints); a sequence of calls to next()
 *  returns run in consecutive order until every run has been returned.
 *
 *  Client classes should never call the RunIterator constructor directly;
 *  instead they should invoke the iterator() method on a RunLengthEncoding
 *  object, which will construct a properly initialized RunIterator for the
 *  client.
 *
 *  Calls to hasNext() determine whether another run is available, or whether
 *  the iterator has reached the end of the run-length encoding.  When
 *  a RunIterator reaches the end of an encoding, it is no longer useful, and
 *  the next() method may throw an exception; thus it is recommended to check
 *  hasNext() before each call to next().  To iterate through the encoding
 *  again, construct a new RunIterator by invoking iterator() on the
 *  RunLengthEncoding and throw the old RunIterator away.
 *
 *  A RunIterator is not guaranteed to work if the underlying RunLengthEncoding
 *  is modified after the RunIterator is constructed.  (Especially if it is
 *  modified by setPixel().)
 */

import java.util.Iterator;
import java.util.NoSuchElementException;

@SuppressWarnings("rawtypes")
public class RunIterator implements Iterator {

  /**
   *  Define any variables associated with a RunIterator object here.
   *  These variables MUST be private.
   */
   private DListNode1 current;



  /**
   *  RunIterator() constructs a new iterator starting with a specified run.
   *
   *  @param node the run where this iterator starts.
   */
  // Unlike all the other methods we have asked you to write, the RunIterator()
  // constructor does not have a predefined signature, because no outside
  // class should ever call this constructor except the iterator() method in
  // the RunLengthEncoding class.  The correct way for outside classes to
  // get access to a RunIterator is to call the iterator() method on a
  // RunLengthEncoding object.  You are welcome to add any parameters to the
  // constructor that you want so that your RunLengthEncoding.iterator()
  // implementation can construct a RunIterator that points to the first run of
  // the encoding.
  RunIterator(DListNode1 itr) {
    current=itr;
    // Your solution here.  You may add parameters to the method signature.
  }

  /**
   *  hasNext() returns true if this iterator has more runs.  If it returns
   *  false, then the next call to next() may throw an exception.
   *
   *  @return true if the iterator has more elements.
   */
  public boolean hasNext() {
    if (current==null) return false;
    else return true;// Replace the following line with your solution.
  }

  /**
   *  next() returns an array of 4 ints that specifies the current run in the
   *  sequence.  It also advances the iterator to the next run, so that the
   *  next call to next() will return the following run.
   *
   *  If "this" RunIterator has returned every run, it cannot be expected to
   *  behave well.  (Technically, it is supposed to throw a
   *  NoSuchElementException, but we haven't learned about exceptions yet.)
   *
   *  @return an array of 4 ints that specify the current run in the sequence.
   *  The pixel count is in index [0]; the red value is in index [1]; the green
   *  value is in index [2]; and the blue value is in index [3].
   *  @throws NoSuchElementException if the iteration has no more elements.
   *  (We strongly recommend calling hasNext() to check whether there are any
   *  more runs before calling next().)
   *
   *  The returned four-int array is constructed in next(), and can be
   *  discarded by the calling method after use.  The array should not be part
   *  of your RunLengthEncoding data structure!  It must be freshly constructed
   *  for the sole purpose of returning four ints.
   */
  public int[] next() {
        int[] k= new int[4];
        if(hasNext()){
        k[0]=current.num;
        k[1]=current.red;
        k[2]=current.green;
        k[3]=current.blue;
         current=current.next;}
        return k;
    // Construct a new array of 4 ints, fill in its values, and return it.
    // Don't forget to advance the RunIterator's pointer so that the next
    // call to next() will return the subsequent run.

    // Replace the following line with your solution.
   
  }

  /**
   *  remove() would remove from the underlying run-length encoding the run
   *  identified by this iterator, but we are NOT implementing it.
   *
   *  DO NOT CHANGE THIS METHOD.
   */
  public void remove() {
    throw new UnsupportedOperationException();
  }
}
RunIterator
/* DListNode1.java */

/**
 *  A DListNode1 is a node in a DList1 (doubly-linked list).
 */

public class DListNode1 {

  /**
   *  item references the item stored in the current node.
   *  prev references the previous node in the DList.
   *  next references the next node in the DList.
   *
   *  DO NOT CHANGE THE FOLLOWING FIELD DECLARATIONS.
   */

  public int red;
  public int green;
  public int blue;
  public int num;
  int item;
  public DListNode1 prev;
  public DListNode1 next;

  /**
   *  DListNode1() constructor.
   */
  DListNode1() {
    red = 0;
    green=0;
    blue=0;
    num=0;
    prev = null;
    next = null;
  }

  DListNode1(int intensity,int num) {
    red = intensity;
    green=intensity;
    blue=intensity;
    this.num=num;
    prev = null;
    next = null;
  }
  DListNode1(int red,int green,int blue,int num){
      this.red=red;
      this.green=green;
      this.blue=blue;
      this.num=num;
      prev = null;
      next = null;
  }
}
DListNode1

原文地址:https://www.cnblogs.com/Jingjunw/p/7296208.html