简体   繁体   English

Java中难以对一系列图像进行变形

[英]Difficulty morphing a series of images in Java

I'm having a little difficulty doing an assignment. 我在做作业时有点困难。 I'll post the class and explain. 我将上课并解释。

import java.awt.*;
import java.awt.font.*;
import java.awt.geom.*;
import java.text.*;

/**
 * A class that represents a picture.  This class inherits from 
 * SimplePicture and allows the student to add functionality to
 * the Picture class.  
 * 
 * Copyright Georgia Institute of Technology 2004-2005
 * @author Barbara Ericson ericson@cc.gatech.edu
 */
public class Picture extends SimplePicture 
{
  ///////////////////// constructors //////////////////////////////////

  /**
   * Constructor that takes no arguments 
   */
  public Picture ()
  {
    /* not needed but use it to show students the implicit call to super()
     * child constructors always call a parent constructor 
     */
    super();  
  }

  /**
   * Constructor that takes a file name and creates the picture 
   * @param fileName the name of the file to create the picture from
   */
  public Picture(String fileName)
  {
    // let the parent class handle this fileName
    super(fileName);
  }

  /**
   * Constructor that takes the width and height
   * @param width the width of the desired picture
   * @param height the height of the desired picture
   */
  public Picture(int width, int height)
  {
// let the parent class handle this width and height
super(width,height);
  }

  /**
   * Constructor that takes a picture and creates a 
   * copy of that picture
   */
  public Picture(Picture copyPicture)
  {
    // let the parent class do the copy
    super(copyPicture);
  }

  ////////////////////// methods ///////////////////////////////////////

  /**
   * Method to return a string with information about this picture.
   * @return a string with information about the picture such as fileName,
   * height and width.
   */
  public String toString()
  {
    String output = "Picture, filename " + getFileName() + 
      " height " + getHeight() 
      + " width " + getWidth();
    return output;

  }

 /**
  * Modified version of method from page 154 of the textbook for copying pictures
  */
 public void copyPictureTo(Picture sourcePicture, int xStart, int yStart)
 {
   Pixel sourcePixel = null;
   Pixel targetPixel = null;

   //loop through the columns
   try{
   for (int sourceX = 0, targetX = xStart;
        sourceX < sourcePicture.getWidth();
        sourceX++, targetX++)
   {
     //loop through the rows
     for (int sourceY = 0,
          targetY = yStart;
          sourceY < sourcePicture.getHeight();
          sourceY++, targetY++)
     {
       sourcePixel = sourcePicture.getPixel(sourceX,sourceY);
       targetPixel = this.getPixel(targetX,targetY);
       targetPixel.setColor(sourcePixel.getColor());
     } 
   }
  }catch(IndexOutOfBoundsException ex){System.out.println("Either xStart or yStart is out of bounds");System.exit(0);}
} 
 //morphStage() method is located here.

 public void morphStage(Picture startPicture, Picture endPicture, int numStages, int k)
 {
   Pixel[] pixelArrayStart = startPicture.getPixels();
   Pixel[] pixelArrayEnd = endPicture.getPixels();
   Pixel pixelObjEnd = null;
   Pixel pixelObjStart = null;
   Pixel pixelObjNew = null;

   //Colour values for starting picture.

   int startingRedValue = 0;
   int startingGreenValue = 0;
   int startingBlueValue = 0;

   //Colour values for ending picture.

   int endRedValue = 0;
   int endGreenValue = 0;
   int endBlueValue = 0;

   //Colour values for intermediate pictures.

   int redValue = 0;
   int greenValue = 0;
   int blueValue = 0;

   //Loops through each entry int he first array, getting the RGB values
   for (int i = 0; i < pixelArrayStart.length; i++)
   {
     //Loops through each entry in the second array, getting the RGB values
     {
       for (int j = 0; j < pixelArrayEnd.length; j++)
       {
         pixelObjEnd = pixelArrayEnd[j];
         endRedValue = pixelObjEnd.getRed();
         endGreenValue = pixelObjEnd.getGreen();
         endBlueValue = pixelObjEnd.getBlue();
         pixelObjStart = pixelArrayStart[i];
         startingRedValue = pixelObjStart.getRed();
         startingGreenValue = pixelObjStart.getGreen();
         startingBlueValue = pixelObjStart.getBlue();
         redValue = startingRedValue +((endRedValue - startingRedValue)/(numStages + 1))*k; 
         greenValue = startingGreenValue +((endGreenValue - startingGreenValue)/(numStages + 1))*k; 
     blueValue = startingBlueValue +((endBlueValue - startingBlueValue)/(numStages + 1))*k;
         pixelObjNew.setRed(redValue);
         pixelObjNew.setGreen(greenValue);
         pixelObjNew.setBlue(blueValue);
       }
     }
   }
 }
}



 // end of class Picture, put all new methods before this

The idea is to create a series of intermediate pictures using the equation, redValue = startingRedValue +((endRedValue - startingRedValue)/(numStages + 1))*k. 想法是使用等式redValue = startingRedValue +(((endRedValue-startingRedValue)/(numStages + 1))* k创建一系列中间图片。

I'm not sure if I'm writing the code properly, but the idea was to create an array of pixels for the first picture, get the RGB values, create an array of pixels for the second picture, get the RGB values, and then create the a new pixel, pixelObjNew by setting each RGB value using the equation. 我不确定是否编写正确的代码,但是想法是为第一张图片创建一个像素数组,获取RGB值,为第二张图片创建一个像素数组,获取RGB值,以及然后通过使用公式设置每个RGB值来创建一个新像素pixelObjNew。

The code compiles fine, but when I try to run it with two pictures, there's an error. 代码可以很好地编译,但是当我尝试使用两张图片运行它时,出现了错误。 (NB: TestMorphing is the class I wrote for the test) (注意:TestMorphing是我为测试编写的类)

java.lang.NullPointerException
    at Picture.morphStage(Picture.java:149)
    at TestMorphing.main(TestMorphing.java:19)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at     sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at     edu.rice.cs.drjava.model.compiler.JavacCompiler.runCommand(JavacCompiler.java:272)

This is an introduction to computer science class, btw. 这是计算机科学课程的简介,顺便说一句。

Much appreciated! 非常感激!

EDIT: Here's the pixel class. 编辑:这是像素类。

import java.awt.Color;

/**
 * Class that references a pixel in a picture. A pixel has an x and y
 * location in a picture.  A pixel knows how to get and set the red, 
 * green, blue, and alpha values in the picture.  A pixel also knows
 * how to get and set the color using a Color object.
 * 
 * Copyright Georgia Institute of Technology 2004
 * @author Barb Ericson ericson@cc.gatech.edu
 */
public class Pixel
{

  ////////////////////////// fields ///////////////////////////////////

  /** the digital picture this pixel belongs to */
  private DigitalPicture picture;

  /** the x location of this pixel in the picture (0,0) is top left */
  private int x; 

  /** the y location of this pixel in the picture (0,0) is top left */
  private int y; 

  ////////////////////// constructors /////////////////////////////////

  /** 
   * A constructor that take the x and y location for the pixel and
   * the picture the pixel is coming from
   * @param picture the picture that the pixel is in
   * @param x the x location of the pixel in the picture
   * @param y the y location of the pixel in the picture
   */
  public Pixel(DigitalPicture picture, int x, int y)
  {
    // set the picture
    this.picture = picture;

    // set the x location
    this.x = x;

    // set the y location
    this.y = y;

  }

  ///////////////////////// methods //////////////////////////////

  /**
   * Method to get the x location of this pixel.  
   * @return the x location of the pixel in the picture
   */
  public int getX() { return x; }

  /**
   * Method to get the y location of this pixel.
   * @return the y location of the pixel in the picture
   */
  public int getY() { return y; }

  /**
   * Method to get the amount of alpha (transparency) at this pixel.
   * It will be from 0-255.
   * @return the amount of alpha (transparency)
   */
  public int getAlpha() {

    /* get the value at the location from the picture as a 32 bit int
     * with alpha, red, green, blue each taking 8 bits from left to right
     */
    int value = picture.getBasicPixel(x,y);

// get the alpha value (starts at 25 so shift right 24)
// then and it with all 1's for the first 8 bits to keep
// end up with from 0 to 255 
int alpha = (value >> 24) & 0xff;

return alpha;
  }


  /**
   * Method to get the amount of red at this pixel.  It will be
   * from 0-255 with 0 being no red and 255 being as much red as
   * you can have.
   * @return the amount of red from 0 for none to 255 for max
   */
  public int getRed() { 

    /* get the value at the location from the picture as a 32 bit int
     * with alpha, red, green, blue each taking 8 bits from left to right
     */
    int value = picture.getBasicPixel(x,y);

    // get the red value (starts at 17 so shift right 16)
    // then and it with all 1's for the first 8 bits to keep
    // end up with from 0 to 255 
    int red = (value >> 16) & 0xff;

    return red;
  }

  /**
   * Method to get the red value from a pixel represented as an int
   * @param value the color value as an int
   * @return the amount of red
   */
  public static int getRed(int value)
  {
    int red = (value >> 16) & 0xff;
    return red;
  }

  /**
   * Method to get the amount of green at this pixel.  It will be
   * from 0-255 with 0 being no green and 255 being as much green as
   * you can have.
   * @return the amount of green from 0 for none to 255 for max
   */
  public int getGreen() { 

    /* get the value at the location from the picture as a 32 bit int
     * with alpha, red, green, blue each taking 8 bits from left to right
     */
    int value = picture.getBasicPixel(x,y);

    // get the green value (starts at 9 so shift right 8)
    int green = (value >>  8) & 0xff;

    return green;
  }

  /**
   * Method to get the green value from a pixel represented as an int
   * @param value the color value as an int
   * @return the amount of green
   */
  public static int getGreen(int value)
  {
    int green = (value >> 8) & 0xff;
    return green;
  }

  /**
   * Method to get the amount of blue at this pixel.  It will be
   * from 0-255 with 0 being no blue and 255 being as much blue as
   * you can have.
   * @return the amount of blue from 0 for none to 255 for max
   */
  public int getBlue() { 

    /* get the value at the location from the picture as a 32 bit int
     * with alpha, red, green, blue each taking 8 bits from left to right
     */
    int value = picture.getBasicPixel(x,y);

    // get the blue value (starts at 0 so no shift required)
    int blue = value & 0xff;

    return blue;
  }

  /**
   * Method to get the blue value from a pixel represented as an int
   * @param value the color value as an int
   * @return the amount of blue
   */
  public static int getBlue(int value)
  {
    int blue = value & 0xff;
    return blue;
  }

  /**
   * Method to get a color object that represents the color at this pixel.
   * @return a color object that represents the pixel color
   */
  public Color getColor() 
  { 
     /* get the value at the location from the picture as a 32 bit int
     * with alpha, red, green, blue each taking 8 bits from left to right
     */
    int value = picture.getBasicPixel(x,y);

    // get the red value (starts at 17 so shift right 16)
    // then and it with all 1's for the first 8 bits to keep
    // end up with from 0 to 255 
    int red = (value >> 16) & 0xff;

    // get the green value (starts at 9 so shift right 8)
    int green = (value >>  8) & 0xff;

    // get the blue value (starts at 0 so no shift required)
    int blue = value & 0xff;

    return new Color(red,green,blue);
  }

  /**
   * Method to set the pixel color to the passed in color object.
   * @param newColor the new color to use
   */
  public void setColor(Color newColor) 
  {
    // set the red, green, and blue values
    int red = newColor.getRed();
    int green = newColor.getGreen();
    int blue = newColor.getBlue();

    // update the associated picture
    updatePicture(this.getAlpha(),red,green,blue);
  }



  /**
       * Method to update the picture based on the passed color
       * values for this pixel
       * @param alpha the alpha (transparency) at this pixel
       * @param red the red value for the color at this pixel
       * @param green the green value for the color at this pixel
       * @param blue the blue value for the color at this pixel
       */
      public void updatePicture(int alpha, int red, int green, int blue)
      {
        // create a 32 bit int with alpha, red, green blue from left to right
        int value = (alpha << 24) + (red << 16) + (green << 8) + blue;

        // update the picture with the int value
        picture.setBasicPixel(x,y,value);
      }

      /**
       * Method to correct a color value to be within 0 and 255
       * @param the value to use
       * @return a value within 0 and 255
       */
      private static int correctValue(int value)
      {
        if (value < 0)
          value = 0;
        if (value > 255)
          value = 255;
        return value;
      }

      /**
       * Method to set the red to a new red value
       * @param value the new value to use
       */
      public void setRed(int value)
      {
        // set the red value to the corrected value
        int red = correctValue(value);

        // update the pixel value in the picture
        updatePicture(getAlpha(), red, getGreen(), getBlue());
      } 

      /**
       * Method to set the green to a new green value
       * @param value the value to use
       */
      public void setGreen(int value)
      {
        // set the green value to the corrected value
        int green = correctValue(value);

        // update the pixel value in the picture
        updatePicture(getAlpha(), getRed(), green, getBlue());
      } 

      /**
       * Method to set the blue to a new blue value
       * @param value the new value to use
       */
  public void setBlue(int value)
  {
    // set the blue value to the corrected value
    int blue = correctValue(value);

    // update the pixel value in the picture
    updatePicture(getAlpha(), getRed(), getGreen(), blue);
  } 

   /**
   * Method to set the alpha (transparency) to a new alpha value
   * @param value the new value to use
   */
  public void setAlpha(int value)
  {
    // make sure that the alpha is from 0 to 255 
    int alpha = correctValue(value);

    // update the associated picture
    updatePicture(alpha, getRed(), getGreen(), getBlue());
  } 

  /**
  * Method to get the distance between this pixel's color and the passed color
  * @param testColor the color to compare to
  * @return the distance between this pixel's color and the passed color
  */
 public double colorDistance(Color testColor)
 {
   double redDistance = this.getRed() - testColor.getRed();
   double greenDistance = this.getGreen() - testColor.getGreen();
   double blueDistance = this.getBlue() - testColor.getBlue();
   double distance = Math.sqrt(redDistance * redDistance + 
                               greenDistance * greenDistance +
                               blueDistance * blueDistance);
   return distance;
 }

 /**
  * Method to compute the color distances between two color objects
  * @param color1 a color object
  * @param color2 a color object
  * @return the distance between the two colors
  */
 public static double colorDistance(Color color1,Color color2)
 {
   double redDistance = color1.getRed() - color2.getRed();
   double greenDistance = color1.getGreen() - color2.getGreen();
   double blueDistance = color1.getBlue() - color2.getBlue();
   double distance = Math.sqrt(redDistance * redDistance + 
                               greenDistance * greenDistance +
                               blueDistance * blueDistance);
   return distance;
 }

 /**
  * Method to get the average of the colors of this pixel
  * @return the average of the red, green, and blue values
  */
 public double getAverage()
 {
   double average = (getRed() + getGreen() + getBlue()) / 3.0;
   return average;
 }

  /**
   * Method to return a string with information about this pixel
   * @return a string with information about this pixel
   */
  public String toString()
  {
    return "Pixel red=" + getRed() + " green=" + getGreen() + 
      " blue=" + getBlue();
  }

}

Your problem seems to stem from your trying to use the Pixel type variable, pixelObjNew, while it is still null. 您的问题似乎源于您尝试使用Pixel类型变量pixelObjNew,而该变量仍为null的原因。 You appear to be using a 3rd party library, likely part of your Ga Tech class code, and our not being privy to this code will necessary limit our ability help, but having said that, the bottom line is that you should first assign a valid instantiated object to this variable prior to trying to use it. 您似乎正在使用第3方库,这可能是您的Ga Tech类代码的一部分,而我们不了解该代码将有必要限制我们的能力帮助,但请注意,最重要的是,您应该首先分配一个有效的在尝试使用它之前实例化此变量的对象。 This might be as simple as calling, 这可能像调用一样简单,

pixelObjNew = new Pixel();

Or it might be a whole lot more complex. 或者它可能要复杂得多。 Check your library's API, your class notes, your sample code, to find out what you should do. 检查您的库的API,类说明,示例代码,以了解您应该做什么。

Key points for solving NPE: 解决NPE的要点:

  • Finding and inspecting the line that throws the NPE is critical to solving it. 找到并检查抛出NPE的管线对于解决该问题至关重要。
  • A variable that you are trying to use on that line is null, and your trying to dereference it is causing your problem. 您尝试在该行上使用的变量为null,并且尝试取消引用它会导致问题。
  • Often it's obvious by looking at the line to see which variable is at fault. 通常,通过查看行以查看哪个变量有问题,这很明显。
  • At other times you'll need a debugger or System.out.println(...)` statements (the so-called "poor man's debugger") to help you. 在其他时候,您将需要调试器或System.out.println(...)`语句(所谓的“穷人调试器”)来帮助您。

Edit 编辑
On looking at your Pixel class, it appears that 1) using a default constructor won't do, and that 2) a Pixel by itself appears to be meaningless, that it only makes sense in context with the Picture from which it is a component. 在查看Pixel类时,似乎1)使用默认构造函数无效,2)Pixel本身似乎没有意义,它仅在上下文中才有意义,而Picture是它的组成部分。 This would also suggest to me that your current approach to morphing might be (accent on the might ) be off. 这也意味着,我认为当前的做法变形可能是(上威力口音)关闭。

My guess, and please understand that this is a huge guess, is that you might want to create several Picture objects, one for each intermediate stage, and one for the end picture. 我的猜测(请理解这是一个巨大的猜测)是您可能要创建几个Picture对象,每个中间对象一个,最后一个图像一个。 And then you can extract Pixel arrays from each Picture and adjust them (linearly?). 然后,您可以从每张图片中提取像素阵列并进行调整(线性吗?)。 Again this is a silly wild arsed guess. 同样,这是一个愚蠢的疯狂猜测。 Use this advice with caution. 请谨慎使用此建议。

Also, I think that I would not nest for loops to do my morphing if it is to be a linear morph. 另外,我认为如果要成为线性变形,我不会嵌套循环来变形。

pixelObjNew is initialized as null and that never changes. pixelObjNew初始化为null,并且永远不会更改。 So pixelObjNew.setRed(redValue); 所以pixelObjNew.setRed(redValue); is going to throw an NPE. 将要抛出一个NPE。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM