java - 在 Java 中对一系列图像进行变形的困难

标签 java

我在完成作业时遇到了一些困难。我将发布类(class)并进行解释。

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

这个想法是使用公式 redValue =startingRedValue +((endRedValue -startingRedValue)/(numStages + 1))*k 创建一系列中间图片。

我不确定我是否正确编写了代码,但想法是为第一张图片创建一个像素数组,获取 RGB 值,为第二张图片创建一个像素数组,获取 RGB 值,然后通过使用公式设置每个 RGB 值来创建一个新像素,pixelObjNew。

代码编译得很好,但是当我尝试用两张图片运行它时,出现错误。 (注意: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)

顺便说一句,这是计算机科学类(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();
  }

}

最佳答案

您的问题似乎源于您尝试使用 Pixel 类型变量,pixelObjNew,而它仍然为空。您似乎正在使用第 3 方库,可能是您的 Ga Tech 类代码的一部分,并且我们不了解此代码将必然限制我们的帮助能力,但话虽如此,底线是您应该在尝试使用此变量之前首先为其分配一个有效的实例化对象。这可能就像调用一样简单,

pixelObjNew = new Pixel();

或者可能会更加复杂。检查你的图书馆的 API、你的类笔记、你的示例代码,找出你应该做什么。

解决NPE的要点:

  • 找到并检查引发 NPE 的线路对于解决该问题至关重要。
  • 您尝试在该行上使用的变量为 null,并且您尝试取消引用它会导致出现问题。
  • 通常通过查看该行即可明显看出哪个变量出了问题。
  • 有时您需要调试器或 System.out.println(...)` 语句(所谓的“穷人的调试器”)来帮助您。
<小时/>

编辑
在查看您的 Pixel 类时,似乎 1)使用默认构造函数是行不通的,并且 2)Pixel 本身似乎毫无意义,它仅在其作为组件的图片的上下文中才有意义。这也向我表明,您当前的变形方法可能(重音可能)已关闭。

我的猜测(请理解这是一个巨大的猜测)是,您可能想要创建多个 Picture 对象,一个用于每个中间阶段,一个用于最终图片。然后您可以从每个图片中提取像素阵列并调整它们(线性?)。这又是一个愚蠢、疯狂的猜测。请谨慎使用此建议。

此外,我认为如果要进行线性变形,我不会嵌套 for 循环来进行变形。

关于java - 在 Java 中对一系列图像进行变形的困难,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20015299/

相关文章:

java - 来自 JTextField 的波兰语字母

java - Spring MVC 简单 Controller 示例

java - JFugue Java 音乐 API 在 Android 中的实现

java - 为什么 Spring Data JPA 文档描述的查询方法只以 find 开头?

java - 在 Java 中获取 Ipv6 完整格式

java - Gradle 。不知道自己是子项目的子项目

java - 序列化接口(interface)

java - 一旦定义了另一个类的 ArrayList,如何从它获取值?

Java 泛型 : Unchecked cast from List<capture#10-of ? > 到 List<Object>

java - 如何从 OpenStreetMap 离线创建 map 图 block ,在 Android 上显示?