Difficulty morphing a series of images in Java - 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.
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.
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)
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. 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. 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.
Key points for solving NPE:
Finding and inspecting the line that throws the NPE is critical to solving it.
A variable that you are trying to use on that line is null, and your trying to dereference it is causing your problem.
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.
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. 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. 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. So pixelObjNew.setRed(redValue); is going to throw an NPE.

Related

Convert colorPrimary to colorPrimaryDark (how much darker)

In guidance with Material Design, how much darker should the statusbar be than the actionbar?
I have a color set for the actionbar at runtime and have no way of knowing this colour at programming time, so how can I get the correct statusbar colour?
I know i can darken a colour using this
this.getSupportActionBar().setBackgroundDrawable(new ColorDrawable(colorPrimary));
float[] hsv = new float[3];
Color.colorToHSV(colorPrimary, hsv);
hsv[2] *= 0.8f;
int colorPrimaryDark = Color.HSVToColor(hsv);
if(Build.VERSION.SDK_INT>=21)
Chat.this.getWindow().setStatusBarColor(colorPrimaryDark);
But I'm not sure how much to darken it
Material design color palette was not generated by manipulating the color in HSV. It was done with HSL (Hue, Saturation, Lightness).
Here is a utility class that will darken/lighten a color using HSL
package com.ammar.materialcolorizer;
import android.graphics.Color;
/**
* A utility class for darkening and lightening colors in the same way as
* material design color palettes
* Created by Ammar Mardawi on 12/4/16.
*/
public class ColorUtil {
/**
* Darkens a given color
* #param base base color
* #param amount amount between 0 and 100
* #return darken color
*/
public static int darken(int base, int amount) {
float[] hsv = new float[3];
Color.colorToHSV(base, hsv);
float[] hsl = hsv2hsl(hsv);
hsl[2] -= amount / 100f;
if (hsl[2] < 0)
hsl[2] = 0f;
hsv = hsl2hsv(hsl);
return Color.HSVToColor(hsv);
}
/**
* lightens a given color
* #param base base color
* #param amount amount between 0 and 100
* #return lightened
*/
public static int lighten(int base, int amount) {
float[] hsv = new float[3];
Color.colorToHSV(base, hsv);
float[] hsl = hsv2hsl(hsv);
hsl[2] += amount / 100f;
if (hsl[2] > 1)
hsl[2] = 1f;
hsv = hsl2hsv(hsl);
return Color.HSVToColor(hsv);
}
/**
* Converts HSV (Hue, Saturation, Value) color to HSL (Hue, Saturation, Lightness)
* Credit goes to xpansive
* https://gist.github.com/xpansive/1337890
* #param hsv HSV color array
* #return hsl
*/
private static float[] hsv2hsl(float[] hsv) {
float hue = hsv[0];
float sat = hsv[1];
float val = hsv[2];
//Saturation is very different between the two color spaces
//If (2-sat)*val < 1 set it to sat*val/((2-sat)*val)
//Otherwise sat*val/(2-(2-sat)*val)
//Conditional is not operating with hue, it is reassigned!
// sat*val/((hue=(2-sat)*val)<1?hue:2-hue)
float nhue = (2f - sat) * val;
float nsat = sat * val / (nhue < 1f ? nhue : 2f - nhue);
if (nsat > 1f)
nsat = 1f;
return new float[]{
//[hue, saturation, lightness]
//Range should be between 0 - 1
hue, //Hue stays the same
// check nhue and nsat logic
nsat,
nhue / 2f //Lightness is (2-sat)*val/2
//See reassignment of hue above
};
}
/**
* Reverses hsv2hsl
* Credit goes to xpansive
* https://gist.github.com/xpansive/1337890
* #param hsl HSL color array
* #return hsv color array
*/
private static float[] hsl2hsv(float[] hsl) {
float hue = hsl[0];
float sat = hsl[1];
float light = hsl[2];
sat *= light < .5 ? light : 1 - light;
return new float[]{
//[hue, saturation, value]
//Range should be between 0 - 1
hue, //Hue stays the same
2f * sat / (light + sat), //Saturation
light + sat //Value
};
}
}
According to Material Design Color Generator, to generate primaryColorDark, you need to darken by 12. Here is how to generate the full color palette exactly as Material Design Color Generator:
setColor("50", ColorUtil.lighten(color, 52), mTv50);
setColor("100", ColorUtil.lighten(color, 37), mTv100);
setColor("200", ColorUtil.lighten(color, 26), mTv200);
setColor("300", ColorUtil.lighten(color, 12), mTv300);
setColor("400", ColorUtil.lighten(color, 6), mTv400);
setColor("500", ColorUtil.lighten(color, 0), mTv500);
setColor("600", ColorUtil.darken(color, 6), mTv600);
setColor("700", ColorUtil.darken(color, 12), mTv700);
setColor("800", ColorUtil.darken(color, 18), mTv800);
setColor("900", ColorUtil.darken(color, 24), mTv900);
One way of knowing exactly how much darker it should be is using Material Color Tool. Just enter the hex value of your primary color and it will generate the light and dark versions for you.
Google suggests using the 500 colors as the primary colors in your app and the other colors as accents colors.
Toolbars and larger color blocks should use the 500 color of the primary color of your app.
So primaryColor should be tint 500.
The status bar should be the darker 700 tint of your primary color.
So primaryColorDark should be tint 700.
So I guess the primaryColorDark should be 200 tint darker than the primaryColor.
https://www.google.com/design/spec/style/color.html
The official Material Color Tool calculates the darkened/brightened colors based on the JS library chroma.js, using the chroma.darken() / chroma.brighten() function, whose algorithm is based on the CIELAB color space.
snippet from the source code on Github
Color.prototype.darken = function(amount=1) {
const me = this;
const lab = me.lab();
lab[0] -= LAB_CONSTANTS.Kn * amount;
return new Color(lab, 'lab').alpha(me.alpha(), true);
}
Material Color Tool simply uses the fallback value of the amount parameter, while the LAB_CONSTANTS.Kn is 18, it subtracts 18 (to darken) / adds 18 (to brighten) to the lightness component L* of the given base color.
IMHO, how "darker" should it must be, it's on your own.
If you are using Android Studio, when in colors.xml, double-click in the preview of the color, switch to HSV mode, and decrease the brightness. (similar to what are you doing programmatically)
Android java code:
public static int darkenColor(int color) {
int alpha = Color.alpha(color);
int red = Color.red(color);
int green = Color.green(color);
int blue = Color.blue(color);
return Color.argb(alpha, (int) (red * 0.9), (int) (green * 0.9), (int) (blue * 0.9));
}
public static String intColor2String(int intColor) {
String strColor = String.format("#%06X", 0xFFFFFF & intColor);
return strColor;
}
How to use?
String dakenColor = Utils.intColor2String(
Utils.darkenColor(Color.parseColor("#21BBA6")));

Getting Input (0,0,0) instead of (50,40,30) [Java]

I'm getting wrong output. I'll put the 3 codes here, they are pretty basic as I've just started to study. (The third code is the tester)
The problem: in the tester I'm getting that input (0,0,0), but I need to get (50,40,30)
I think the main problem is here:
public void setColor (RGBColor color)
{
}
I tried playing with it, and I don't have a better solution than:
_color = new RGBColor(color);
_color.setRed(color.getRed());
_color.setGreen(color.getGreen());
_color.setBlue(color.getBlue());
RGBColor class.
/**
* This program is used to represent 3 Colors: Red, Green, Blue. (RGB)
* These colors hold values between 0 and 255.
*
*
* #Author doesn't matter ;)
*/
public class RGBColor
{
/**
* attributes: red, green and blue component of a color.
*/
private int _red,_green,_blue;
/**
* final variables.
*/
private final int MAX_VALUE = 255,MIN_VALUE = 0;
private final double THIRTY_PERCENT = 0.3,FIFTY_NINE_PERCENT = 0.59,ELEVEN_PERCENT = 0.11;
/**
* Consctructor which gets 3 colors (RGB), we check here if their range is valid (0 - 255), if not we assign black to it.
*
* #param red - The red color component value.
* #param green - The green color component value.
* #param blue - The blue color component value
*/
public RGBColor(int red, int green, int blue)
{
if(isValid(red,green,blue))
{
_red = red;
_green = green;
_blue = blue;
}
else
doBlack();
}
/**
* Construct a black RGBColor. i.e. red = green = blue = 0
*/
public RGBColor()
{
doBlack();
}
/**
* Construct a new RGBColor which is a copy of the given color.
*
* #param other - The RGBColor to copy.
*/
public RGBColor(RGBColor other)
{
_red = other._red;
_green = other._green;
_blue = other._blue;
}
/**
* Returns the Red component of RGBColor.
*
* #return The red color component value of this RGBColor.
*/
public int getRed()
{
return _red;
}
/**
* Returns the Green component of RGBColor.
*
* #return The green color component value of this RGBColor.
*/
public int getGreen()
{
return _green;
}
/**
* Returns the blue component of RGBColor.
*
* #return The blue color component value of this RGBColor.
*/
public int getBlue()
{
return _blue;
}
/**
* Sets the red color component value of this RGBColor, only if the color range is valid (0-255).
*
* #param num - The red color component value to set.
*/
public void setRed(int num)
{
if(isValid(num))
_red = num;
}
/**
* Sets the green color component value of this RGBColor, only if the color range is valid (0-255).
*
* #param num - The green color component value to set.
*/
public void setGreen(int num)
{
if(isValid(num))
_green = num;
}
/**
* Sets the blue color component value of this RGBColor, only if the color range is valid (0-255).
*
* #param num - The blue color component value to set.
*/
public void setBlue(int num)
{
if(isValid(num))
_blue = num;
}
/**
* Compares the 3 RGB colors, returns true if all are equal.
*
* #return true if the RGBColors are equal; false otherwise.
*/
public boolean equals(RGBColor other)
{
return ((_red == other._red) &&
(_green == other._green) &&
(_blue == other._blue));
}
/**
* Changes this color to be a mix of this and other RGBColors, It simply takes this color and other RGBColor and makes and average of them.
* For example (255,0,0) and (0,0,255) becomes: (127,0,127). Note that it returns integer numbers and not fraction numbers.
*
* #param other is the other color.
*/
public void mix(RGBColor other)
{
_red = (_red + other._red) / 2;
_green = (_green + other._green) / 2;
_blue = (_blue + other._blue) / 2;
}
/**
* Returns the grayscale value of this RGBColor.
* Grayscale is defined by taking Red multipled by 30% plus green multiplied by 59% plus blue multipled by 11%.
*
* #return The grayscale value of this RGBColor, a double number.
*/
public double convertToGrayscale()
{
return ((THIRTY_PERCENT * _red) + (FIFTY_NINE_PERCENT * _green) + (ELEVEN_PERCENT * _blue));
}
/**
* Inverts the color of RGBColor, every spot is reduced relative to 255. For example: (10,20,30) becomes (245,235,225).
*/
public void invert()
{
_red = (MAX_VALUE - _red);
_green = (MAX_VALUE - _green);
_blue = (MAX_VALUE - _blue);
}
/**
* Here we check if the color number was entered correctly.
* It has to be an integer (whole number) between 0-255.
*
* #param nums - a component value, should be the number between 1-4
* #param return - return true if the number is between 1-4, false otherwise.
*/
private boolean isValid(int nums)
{
return ((nums >= MIN_VALUE) && (nums <= MAX_VALUE));
}
/**
* Here we check if the color number was entered correctly.
* It has to be an integer (whole number) between 0-255.
*
* #param red - the red component
* #param green - the green component
* #param blue - the red component
* #param return true if values are correct, false otherwise.
*/
private boolean isValid(int red, int green, int blue)
{
return ((red <= MAX_VALUE && red >= MIN_VALUE &&
green <= MAX_VALUE && green >= MIN_VALUE &&
blue <= MAX_VALUE && blue >= MIN_VALUE));
}
/**
* Returns RGB color string triplet with numbers between 0-255, i.e. (0,127,127)
*/
public String toString()
{
return ("(" + _red + "," + _green + "," + _blue + ")");
}
/**
* RGBColor will become the color Black. (0,0,0)
*/
private void doBlack()
{
_red = _green = _blue = 0;
}
}
LightBulb Class.
/**
* In this program we use _color to represent the color of the bulb
* And we use _switchedOn to represent whether the bulb is turned on or off.
*
* #author
* #date 20/11/2014.
*/
public class LightBulb
{
/**
instance private variables of the lightbulb's color and the switch state.
*/
private static RGBColor _color;
private boolean _switchedOn;
private int ZERO = 0;
private int MAX = 255;
/**
* Construct a new LightBulb with the given color component values.
* Check if atleast one of the color isn't in the given value range (0-255)
* if not in the range, the default color is black (0,0,0).
*/
public LightBulb(int red, int green, int blue)
{
if(isTrue(red,green,blue))
_color = new RGBColor(red,green,blue);
else
_color = new RGBColor(ZERO,ZERO,ZERO);
_switchedOn = false;
}
/**
* Construct a new LightBulb which is a copy of the given bulb, and turn switch off.
*/
public LightBulb(RGBColor color)
{
_color = new RGBColor(color);
_switchedOn = false;
}
/**
* Construct a new LightBulb which is a copy of the given LightBulb
*/
public LightBulb (LightBulb other)
{
_color = new RGBColor(other._color);
_switchedOn = other._switchedOn;
}
//Return the current color of the bulb.
public RGBColor getColor()
{
return new RGBColor(_color);
}
//Sets the color of the bulb.
public void setColor (RGBColor color)
{
_color = new RGBColor(color);
}
//Checks if the bulb is on, if it is - returns true. else, returns false.
public boolean isSwitchedOn()
{
if(_switchedOn)
return true;
else
return false;
}
//If the lightbulb is turned on, it turns it off. else,if it is off - it turns it on.
public void switchLight()
{
if(_switchedOn)
_switchedOn = false;
else
_switchedOn = true;
}
//Returns a string which prints a triplet of the color in numbers of range (0-255), and the switch state of the bulb.
// e.g. (255,255,0) On , e.g. (255,127,0) Off
public String toString()
{
_color = new RGBColor();
return ("(" +_color.getRed()+ "," +_color.getGreen()+ "," + _color.getBlue() + ")" + " " + switchState());
}
//If the switch is on - returns a string "On". else, if it is off returns a string "Off".
public String switchState()
{
if(_switchedOn)
return ("On");
else
return ("Off");
}
public boolean isTrue(int red, int green, int blue)
{
if( red >= ZERO && red <= MAX &&
green >= ZERO && green <= MAX &&
blue >= ZERO && blue <= MAX )
return true;
else
return false;
}
}
LightBulb tester class.
/**
* Write a description of class Tester here.
*
* #author
* #version (a version number or a date)
*/
public class LightBulbTester
{
/**
*
*/
public static void main(String[] args)
{
// Create two light bulb objects
LightBulb l1 = new LightBulb(127,0,127);
LightBulb l2 = new LightBulb(new RGBColor(127,0,127));
LightBulb l3 = new LightBulb(l2);
// Print (test the get method)
System.out.println("Welcome to Light Bulb tester");
System.out.println("1) color of light object is " + l1.getColor());
// Test the set method
l1.setColor(new RGBColor(50,40,30));
System.out.println("2) The new color of light is :" + l1);
// Test isSwitchedOn
System.out.println("3) Light object is switched on? " + l1.isSwitchedOn());
// Now switch on
l1.switchLight();
System.out.println("4) Light after switchLight():" + l1);
System.out.println("Good luck!");
}
}
In this code -
public String toString()
{
_color = new RGBColor();
return ("(" +_color.getRed()+ "," +_color.getGreen()+ "," + _color.getBlue() + ")" + " " + switchState());
}
you're always outputting the value of a new RGBColor object, which will always give you black. You probably don't want to set _color's value here; just remove that line (or replace it with a null check).
Also, remove the static qualifier from the _color property. You don't want to share the value between all bulbs!

Generating Custom Color Palette for Julia set

I need an algorithm or a method to generate a color palette to Color the Julia set images. When using the escape time algorithm to generate the image I for example come up with the following image:
However I need some way to generate a custom color palette like on the Wikipedia page:
How do I achieve an image similar to that? Also, what color smoothing algorithm should be used for Julia set?
Here is the code snippet for clarification:
int max_iter = 256;
ComplexNumber constant = new ComplexNumber(cReal,cImag);
float Saturation = 1f;
for(int X=0; X<WIDTH; X++)
{
for(int Y=0; Y<HEIGHT; Y++)
{
ComplexNumber oldz = new ComplexNumber();
ComplexNumber newz = new ComplexNumber(2.0*(X-WIDTH/2)/(WIDTH/2), 1.33*(Y-HEIGHT/2)/(HEIGHT/2) );
int i;
for(i=0;i<max_iter; i++)
{
oldz = newz;
newz = newz.square();
newz.add(constant);
if(newz.mod() > 2)
break;
}
float Brightness = i < max_iter ? 1f : 0;
float Hue = (i%256)/255.0f;
Color color = Color.getHSBColor((float)Hue, Saturation, Brightness);
img.setRGB(X,Y,color.getRGB());
}
}
There are many possible approaches for such a color mapping. The simplest is sketched in the program below.
The core of this snippet is the initColorMap method. It takes a number of interpolation steps and an array of colors to interpolate between. In the screenshot, these have been
red
red, green
red, green, blue (like in the first image of the question)
red, yellow, green, cyan, blue, magenta
black, orange, white, blue, dark blue (an attempt to obtain a color map similar to that from the second image in the question)
red, green, blue, sampled with a sine function
The method returns an int array containing the RGB values of the interpolated colors. This might be used directly. But for an improved versatility, these arrays are wrapped into a ColorMap1D interface, which offers a method that returns an RGB color for any given value between 0.0 and 1.0.
For your application case, this could probably used like this:
double value = (double)iterations / maxIterations;
int rgb = colorMap.getColor(value);
(EDIT: The following description and the code have been updated and extended based on the request in the comment)
Such a "normalization" to the range [0.0, 1.0] and the abstraction using interfaces is often beneficial.
As a demonstration of the effects that are possible with this abstraction: The ColorMaps1D class contains several methods to create ColorMap1D instances:
ColorMaps1D#createDefault(int steps, Color ... colors): Creates a default color map that interpolates over a given sequence of colors with a predefined number of steps (the "resolution" of the color map)
ColorMaps1D#create(ColorMap1D delegate, DoubleFunction<Double> function) : This method creates a color map where the argument of the getColor method is transformed with the given function before it is passed the the getColor method of the given delegate.
Thus, one can easily create a ColorMap1D that interpolates non-linearly between colors. One could even create a ColorMap1D implementation that interpolates over several other color maps.
As an example, I have added a color map that uses the default, simple Red->Green->Blue color map, but accesses it with a function that computes the sine of the argument. This way, it is possible to "cycle" through the Red->Green->Blue color map several times.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.util.Arrays;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ColorMapsTest
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().setLayout(new GridLayout(0,1));
int steps = 1024;
f.getContentPane().add(
createPanel(steps, Color.RED));
f.getContentPane().add(
createPanel(steps, Color.RED, Color.GREEN));
f.getContentPane().add(
createPanel(steps, Color.RED, Color.GREEN, Color.BLUE));
f.getContentPane().add(
createPanel(steps,
Color.RED, Color.YELLOW,
Color.GREEN, Color.CYAN,
Color.BLUE, Color.MAGENTA));
f.getContentPane().add(
createPanel(steps,
Color.BLACK, Color.ORANGE, Color.WHITE,
Color.BLUE, new Color(0,0,128)));
JPanel panel = new JPanel(new BorderLayout());
Color colors[] = new Color[]{ Color.RED, Color.GREEN, Color.BLUE };
String info = "With sine over "+createString(colors);
panel.add(new JLabel(info), BorderLayout.NORTH);
ColorMapPanel1D colorMapPanel =
new ColorMapPanel1D(
ColorMaps1D.createSine(
ColorMaps1D.createDefault(steps, colors), Math.PI * 4));
panel.add(colorMapPanel, BorderLayout.CENTER);
f.getContentPane().add(panel);
f.setSize(500, 400);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private static JPanel createPanel(int steps, Color ... colors)
{
JPanel panel = new JPanel(new BorderLayout());
String info = "In "+steps+" steps over "+createString(colors);
panel.add(new JLabel(info), BorderLayout.NORTH);
ColorMapPanel1D colorMapPanel =
new ColorMapPanel1D(ColorMaps1D.createDefault(steps, colors));
panel.add(colorMapPanel, BorderLayout.CENTER);
return panel;
}
private static String createString(Color ... colors)
{
StringBuilder sb = new StringBuilder();
for (int i=0; i<colors.length; i++)
{
sb.append(createString(colors[i]));
if (i < colors.length - 1)
{
sb.append(", ");
}
}
return sb.toString();
}
private static String createString(Color color)
{
return "("+color.getRed()+","+color.getGreen()+","+color.getBlue()+")";
}
}
// NOTE: This is an interface that is equivalent to the functional
// interface in Java 8. In an environment where Java 8 is available,
// this interface may be omitted, and the Java 8 version of this
// interface may be used instead.
interface DoubleFunction<R>
{
R apply(double value);
}
/**
* Interface for classes that can map a single value from the range
* [0,1] to an int that represents an RGB color
*/
interface ColorMap1D
{
/**
* Returns an int representing the RGB color, for the given value in [0,1]
*
* #param value The value in [0,1]
* #return The RGB color
*/
int getColor(double value);
}
/**
* Default implementation of a {#link ColorMap1D} that is backed by
* a simple int array
*/
class DefaultColorMap1D implements ColorMap1D
{
/**
* The backing array containing the RGB colors
*/
private final int colorMapArray[];
/**
* Creates a color map that is backed by the given array
*
* #param colorMapArray The array containing RGB colors
*/
DefaultColorMap1D(int colorMapArray[])
{
this.colorMapArray = colorMapArray;
}
#Override
public int getColor(double value)
{
double d = Math.max(0.0, Math.min(1.0, value));
int i = (int)(d * (colorMapArray.length - 1));
return colorMapArray[i];
}
}
/**
* Methods to create {#link ColorMap1D} instances
*/
class ColorMaps1D
{
/**
* Creates a {#link ColorMap1D} that walks through the given delegate
* color map using a sine function with the given frequency
*
* #param delegate The delegate
* #param frequency The frequency
* #return The new {#link ColorMap1D}
*/
static ColorMap1D createSine(ColorMap1D delegate, final double frequency)
{
return create(delegate, new DoubleFunction<Double>()
{
#Override
public Double apply(double value)
{
return 0.5 + 0.5 * Math.sin(value * frequency);
}
});
}
/**
* Creates a {#link ColorMap1D} that will convert the argument
* with the given function before it is looking up the color
* in the given delegate
*
* #param delegate The delegate {#link ColorMap1D}
* #param function The function for converting the argument
* #return The new {#link ColorMap1D}
*/
static ColorMap1D create(
final ColorMap1D delegate, final DoubleFunction<Double> function)
{
return new ColorMap1D()
{
#Override
public int getColor(double value)
{
return delegate.getColor(function.apply(value));
}
};
}
/**
* Creates a new ColorMap1D that maps a value between 0.0 and 1.0
* (inclusive) to the specified color range, internally using the
* given number of steps for interpolating between the colors
*
* #param steps The number of interpolation steps
* #param colors The colors
* #return The color map
*/
static ColorMap1D createDefault(int steps, Color ... colors)
{
return new DefaultColorMap1D(initColorMap(steps, colors));
}
/**
* Creates the color array which contains RGB colors as integers,
* interpolated through the given colors.
*
* #param steps The number of interpolation steps, and the size
* of the resulting array
* #param colors The colors for the array
* #return The color array
*/
static int[] initColorMap(int steps, Color ... colors)
{
int colorMap[] = new int[steps];
if (colors.length == 1)
{
Arrays.fill(colorMap, colors[0].getRGB());
return colorMap;
}
double colorDelta = 1.0 / (colors.length - 1);
for (int i=0; i<steps; i++)
{
double globalRel = (double)i / (steps - 1);
int index0 = (int)(globalRel / colorDelta);
int index1 = Math.min(colors.length-1, index0 + 1);
double localRel = (globalRel - index0 * colorDelta) / colorDelta;
Color c0 = colors[index0];
int r0 = c0.getRed();
int g0 = c0.getGreen();
int b0 = c0.getBlue();
int a0 = c0.getAlpha();
Color c1 = colors[index1];
int r1 = c1.getRed();
int g1 = c1.getGreen();
int b1 = c1.getBlue();
int a1 = c1.getAlpha();
int dr = r1-r0;
int dg = g1-g0;
int db = b1-b0;
int da = a1-a0;
int r = (int)(r0 + localRel * dr);
int g = (int)(g0 + localRel * dg);
int b = (int)(b0 + localRel * db);
int a = (int)(a0 + localRel * da);
int rgb =
(a << 24) |
(r << 16) |
(g << 8) |
(b << 0);
colorMap[i] = rgb;
}
return colorMap;
}
/**
* Private constructor to prevent instantiation
*/
private ColorMaps1D()
{
// Private constructor to prevent instantiation
}
}
/**
* A panel painting a {#link ColorMap1D}
*/
class ColorMapPanel1D extends JPanel
{
/**
* The {#link ColorMap1D} that is painted
*/
private final ColorMap1D colorMap;
/**
* Creates a new panel that paints the given color map
*
* #param colorMap The {#link ColorMap1D} to be painted
*/
ColorMapPanel1D(ColorMap1D colorMap)
{
this.colorMap = colorMap;
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
for (int x=0; x<getWidth(); x++)
{
double d = (double)x / (getWidth() - 1);
int rgb = colorMap.getColor(d);
g.setColor(new Color(rgb));
g.drawLine(x, 0, x, getHeight());
}
}
}
(Regarding the color smoothing: This is something that should probably be asked in a separate question. Or maybe not, because there already are many questions about that on StackOverflow. For example, see Smooth spectrum for Mandelbrot Set rendering (or many others))

Unable to close the Frame by clicking close X button

I had been through this link1 link2 for an answer, but was not helpful.
Because
frame.setVisible(false);
is giving below exception,
Exception in thread "main" java.lang.NullPointerException
at Simulation.drawOcean(Simulation.java:72)
at Simulation.main(Simulation.java:191)
Application has below 2 java files.
Simulation class launches GUI.
After running Simulation.java with default command line parameters, Frame does not get close, despite finite while loop.
I could not close the Frame by clicking close button(top right - red), after the simulation is done.
Do i need to set some property for Frame?
Please help me!!!
/* Simulation.java */
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.util.Random;
/* DO NOT CHANGE THIS FILE (except as noted). */
/* (You may wish to make temporary changes or insert println() statements) */
/* while testing your code. When you're finished testing and debugging, */
/* though, make sure your code works with the original version of this file */
/**
* The Simulation class is a program that runs and animates a simulation of
* Sharks and Fish.
*
* The Simulation program takes up to four parameters. The first two specify
* the width and height of the ocean. The third parameter specifies the value
* of starveTIme. For example, if you run
*
* java Simulation 25 25 1
*
* then Simulation will animate a 25x25 ocean with a starveTime of 1. If you
* run "java Simulation" with no parameters, by default Simulation will animate
* a 50x25 ocean with a starveTime of 3. With some choices of parameters,
* the ocean quickly dies out; with others;, it teems forever.
*
* #author mohet01
*
*/
public class Simulation {
/**
* The constant cellSize determines the size of each cell on the screen
* during animation. (You may change this if you wish).
*/
private static final int cellSize = 4;
/**
* Default parameters. (You may change this of you wish).
*/
private static int i = 50; //Default ocean width
private static int j = 25; //Default ocean height
private static int starveTime = 3; //Default shark starvation time
/**
* drawOcean() adds cell contents as part of graphics
*/
private static void drawOcean(Graphics graphics, Ocean ocean){
if(ocean != null){
int width = ocean.width();
int height = ocean.height();
for(int row = 0; row < height; row++){
for(int col = 0; col < width; col++){
int contents = ocean.cellContents(row, col);
if(contents == Ocean.SHARK){
//Draw a red Shark
graphics.setColor(Color.red);
graphics.fillRect(row*cellSize, col*cellSize, cellSize, cellSize);
}else if(contents == Ocean.FISH){
// Draw a green fish
graphics.setColor(Color.green);
graphics.fillRect(row * cellSize, col * cellSize, cellSize, cellSize);
}else{
//Clear the rectangle
graphics.clearRect(row, col, cellSize, cellSize);
}
}
}
}
}
/**
* main() reads the parameters and performs the simulation and animation.
* #param args
* #throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
Ocean sea;
/**
* Read the input parameters
*/
if(args.length >0){
try{
i = Integer.parseInt(args[0]);
}catch(NumberFormatException e){
System.out.println("First argument to Simulation is not a number.");
}
}
if(args.length > 1){
try{
j = Integer.parseInt(args[1]);
}catch(NumberFormatException e){
System.out.println("Second argument to Simulation is not a number");
}
}
if(args.length > 2){
try{
starveTime = Integer.parseInt(args[2]);
}catch(NumberFormatException e){
System.out.println("Third argument to Simulation is not a number");
}
}
/**
* Create a window on your screen
*/
Frame frame = new Frame("Sharks and Fish");
frame.setSize(i*cellSize + 10, j*cellSize + 30);
frame.setVisible(true);
/**
* Create a "Canvas" we can draw upon; attach it to the window
*/
Canvas canvas = new Canvas();
canvas.setBackground(Color.white);
canvas.setSize(i*cellSize, j*cellSize);
frame.add(canvas);
Graphics graphics = canvas.getGraphics();
/**
* Create the initial ocean.
*/
sea = new Ocean(i, j, starveTime);
/**
* Visit each cell (in a roundabout order); randomnly place a fish, shark,
* or nothing in each.
*/
Random random = new Random(0);
int x = 0;
int y = 0;
for(int row = 0;row < j; row++){
//This will visit every x-coordinate once.
x = (x + 78887) %j;
if((x & 8) == 0){
for(int col = 0; col < i; col++){
//This will visit every y coordinate once.
y = (y+78887)%i;
if((y & 8) == 0){
int r = random.nextInt();
if(r < 0){
//50% of cells start with fish
//x - width, y - height
sea.addFish(x, y);
}else if(r > 1500000000){
//~15% of cells start with sharks
sea.addShark(x, y);
}
}
}
}
}
/**
* Perform timesteps forever
*/
int timeLeft = 20;
while (timeLeft > 0) {
// Wait one second (1000 milliseconds)
Thread.sleep(1000);
// Draw the current ocean
drawOcean(graphics, sea);
// For fun, you might wish to change the delay in the next line.
// If you make it too short, though, the graphics won't work properly.
// Simulate a timestep
sea = sea.timeStep();
timeLeft--;
}
}
}
/* Ocean.java */
/**
* The Ocean class defines an object that models an ocean full of sharks and
* fish. Descriptions of the methods you must implements appear below. They
* include a constructor of the form
*
* public Ocean(int i, int j, int starveTime);
*
* that creates an empty ocean having width i and height j, in which sharks
* starve after starveTime timesteps.
*
* See the README file accompanying this project for additional details.
*
* #author mohet01
*
*/
public class Ocean {
/**
* Do not rename these constants. WARNING: if you change the numbers, you
* will need to recompile Test4.java. Failure to do so will give you a very
* hard-to-find bug.
*/
public final static int EMPTY = 1;
public final static int SHARK = 2;
public final static int FISH = 3;
/**
* Define any variables associated with an Ocean object here. These
* variables MUST be private.
*
*/
private final static int UNKNOWN = -1; // for unknown return type
private int width;
private int height;
private int[][] oceanMatrix;
//TODO space optimization on below matrix
private int[][] sharkHungerLevelMatrix;
private int starveTime;
/**
* The following methods are required for Part I.
*
*/
/**
* Constructor that creates an empty ocean having width i and
* height j, in which sharks starve until after starveTime timesteps.
*
* #param width(i)
* is the width of the ocean.
* #param height(j)
* is the height of the ocean.
* #param starveTime
* is the number of timeSteps sharks survive without food.
*/
public Ocean(int i, int j, int starveTime) {
this.width = i;
this.height = j;
this.oceanMatrix = new int[j][i];
this.sharkHungerLevelMatrix = new int[j][i];
this.starveTime = starveTime;
for (int row = 0; row < j; row++) {
for (int col = 0; col < i; col++) {
oceanMatrix[row][col] = EMPTY;
}
}
for (int row = 0; row < j; row++) {
for (int col = 0; col < i; col++) {
sharkHungerLevelMatrix[row][col] = EMPTY;
}
}
}
/**
* width() returns the width of an ocean Object.
*
* #return the width of the ocean.
*
*/
public int width() {
return this.width;
}
/**
* height() returns the height of an Ocean object.
*
* #return the height of the Ocean.
*/
public int height() {
return this.height;
}
/**
* starveTime() returns the number of timesteps sharks survive without food.
*
* #return the number of timesteps sharks survive without food.
*/
public int starveTime() {
return starveTime;
}
/**
* addFish() places a fish in cell (x,y) if the cell is empty. If the cell
* is already occupied, leave the cell as it is.
*
* #param x
* is the x-coordinate of the cell to place a fish in.
* #param y
* is the y-coordinate of the cell to place a fish in.
*/
public void addFish(int x, int y) {
if (oceanMatrix[x][y] == EMPTY) {
oceanMatrix[x][y] = FISH;
}
}
/**
* addShark() (with two parameters) places a newborn shark in cell (x, y) if
* the cell is empty. A "newborn" shark is equivalent to a shark that has
* just eaten. If the cell is already occupied, leave the cell as it is.
*
* #param x
* is the x-coordinate of the cell to place a shark in.
* #param y
* is the y-coordinate of the cell to place a shark in.
*/
public void addShark(int x, int y) {
if (oceanMatrix[x][y] == EMPTY) {
oceanMatrix[x][y] = SHARK;
}
}
/**
* cellContents() returns EMPTY is cell (x,y) is empty, FISH if it contains
* a fish, and SHARK if it contains a shark.
*
* #param x
* is the x-coordinate of the cell whose contents are queried.
* #param y
* is the y-coordinate of the cell whose contents are queried.
*/
public int cellContents(int x, int y) {
return oceanMatrix[x][y];
}
/**
* isFish() checks for the existence of fish in that cell.
* #param x
* is the x-coordinate of the cell whose contents are queried.
* #param y
* is the y-coordinate of the cell whose contents are queried.
* #return the boolean value
*/
private boolean isFish(int x, int y){
return (this.oceanMatrix[x][y] == Ocean.FISH);
}
/**
* isShark() checks for the existence of shark in that cell.
* #param x
* is the x-coordinate of the cell whose contents are queried.
* #param y
* is the y-coordinate of the cell whose contents are queried.
* #return the boolean value
*/
private boolean isShark(int x, int y){
return (this.oceanMatrix[x][y] == Ocean.SHARK);
}
/**
* isSharkStarving() checks the hunger level of shark, if reached to starveTime level
* #param x
* is the x-coordinate of the cell whose contents are queried.
* #param y
* is the y-coordinate of the cell whose contents are queried.
* #return the boolean value
*/
private boolean isSharkStarving(int x, int y){
return (this.sharkHungerLevelMatrix[x][y] == (this.starveTime+1));
}
/**
* checkFish() checks the existence of atleast one fish
* surrounding shark cell
* #param x
* is the x-coordinate of the cell whose contents are queried.
* #param y
* is the y-coordinate of the cell whose contents are queried.
* #return returns true on atleast one fish exist otherwise false
*
*/
private boolean checkFish(int x, int y){
for(int i = x-1;i <= x+1; i++){
for(int j = y-1; j <= y+1; j++){
if(this.isFish(mod(i,this.height), mod(j,this.width))){
return true;
}
}
}
return false;
}
/**
* countShark() counts the number of sharks surrounding queried cell
* #param x
* is the x-coordinate of the cell whose contents are queried.
* #param y
* is the y-coordinate of the cell whose contents are queried.
* #return returns number of sharks surrounding fish cell
*/
private int countShark(int x, int y){
int neighbourSharkCount = 0;
for(int i = x-1;i <= x+1; i++){
for(int j = y-1; j <= y+1; j++){
if(this.isShark(mod(i,this.height), mod(j,this.width))){
neighbourSharkCount++;
}
} // end inner for loop
}//end outer for loop
return neighbourSharkCount;
}
/**
* countFish() counts the number of fish surrounding queried cell
* #param x
* is the x-coordinate of the cell whose contents are queried.
* #param y
* is the y-coordinate of the cell whose contents are queried.
* #return returns number of sharks surrounding queried cell
*/
private int countFish(int x, int y){
int neighbourFishCount = 0;
for(int i = x-1;i <= x+1; i++){
for(int j = y-1; j <= y+1; j++){
if(this.isFish(mod(i,this.height), mod(j,this.width))){
neighbourFishCount++;
}
} // end inner for loop
}//end outer for loop
return neighbourFishCount;
}
/**
* mod() performs the modulo operation using euclidean divison
*
* #param n
* is the numerator
* #param d
* is the denominator
* #return the remainder
*/
private int mod(int n, int d) {
if (n >= 0)
return n % d;
else
return d + ~(~n % d);
}
/**
* timeStep() performs a simulation timestep as described in README.
*
* #return an ocean representing the elapse of one timestep.
*/
public Ocean timeStep() {
Ocean sea = new Ocean(width, height, starveTime);
for (int row = 0; row < this.height; row++) {
for (int col = 0; col < this.width; col++) {
switch(this.oceanMatrix[row][col]){
case Ocean.SHARK:
boolean gotTheFish = false;
//Check all the 8 neighbors of a Shark Cell for fish
if(this.checkFish(row,col)){
gotTheFish = true;
}
//Updating Shark Cell
if(gotTheFish){
/*
* 1) If a cell contains a shark, and any of its neighbors is a fish, then the
* shark eats during the time step, and it remains in the cell at the end of the
* time step. (We may have multiple sharks sharing the same fish. This is fine;
* they all get enough to eat.)
*/
sea.oceanMatrix[row][col] = Ocean.SHARK; // for next time step
}else{
/*
* 2) If a cell contains a shark, and none of its neighbors is a fish, it gets
* hungrier during the time step. If this time step is the (starveTime + 1)th
* time step the shark has gone through without eating, then the shark dies
* (disappears). Otherwise, it remains in the cell.
*/
this.sharkHungerLevelMatrix[row][col]++;
if(this.isSharkStarving(row,col)){
this.oceanMatrix[row][col] = Ocean.EMPTY; // for this time step
this.sharkHungerLevelMatrix[row][col] = Ocean.EMPTY; // for this time step
}
sea.sharkHungerLevelMatrix[row][col] = this.sharkHungerLevelMatrix[row][col]; // for next time step
sea.oceanMatrix[row][col] = this.oceanMatrix[row][col]; // for next time step
}
break;
case Ocean.FISH:
int neighbourSharkCount=0;
//Check all the 8 neighbors of a Fish cell to count for sharks
neighbourSharkCount=countShark(row,col);
//Updating fish cell for current & next time step
if(neighbourSharkCount ==1){
/*
* 4) If a cell contains a fish, and one of its neighbors is a shark, then the
* fish is eaten by a shark, and therefore disappears.
*/
this.oceanMatrix[row][col] = Ocean.EMPTY; //fish disappears this time step
}
else if(neighbourSharkCount > 1){
/*
* 5) If a cell contains a fish, and two or more of its neighbors are sharks, then
* a new shark is born in that cell. Sharks are well-fed at birth; _after_ they
* are born, they can survive an additional starveTime time steps without eating.
*/
sea.oceanMatrix[row][col] = Ocean.SHARK; // new shark for next time step
}
else if(neighbourSharkCount < 1){
/*
* 3) If a cell contains a fish, and all of its neighbors are either empty or are
* other fish, then the fish stays where it is.
*/
sea.oceanMatrix[row][col] = FISH; //for next time step
}
break;
case Ocean.EMPTY:
int fishCount=0;
int sharkCount=0;
//Check all the 8 neighbors of an Empty cell to count sharks and Fish
fishCount = this.countFish(row,col);
sharkCount = this.countShark(row, col);
//Update Empty Cell for current & next time step.
/* (no need to handle this case)
* 6) If a cell is empty, and fewer than two of its neighbors are fish, then the
* cell remains empty.
*/
if((fishCount >= 2) && (sharkCount <=1)){
/*
* 7) If a cell is empty, at least two of its neighbors are fish, and at most one
* of its neighbors is a shark, then a new fish is born in that cell.
*/
this.oceanMatrix[row][col] = FISH;// for current time step
sea.oceanMatrix[row][col] = FISH; //for next time step
}else if((fishCount >= 2) && (sharkCount >= 2)){
/*
* 8) If a cell is empty, at least two of its neighbors are fish, and at least two
* of its neighbors are sharks, then a new shark is born in that cell. (The new
* shark is well-fed at birth, even though it hasn’t eaten a fish yet.)
*/
sea.oceanMatrix[row][col] = Ocean.SHARK; // for next time step
}
break;
}
}//end inner for loop
}//end outer for loop
return sea;
}
/**
* The following method is required for Part II.
*
*
*/
/**
* addShark() (with three parameters) places a shark in cell (x, y) if the
* cell is empty. The shark's hunger is represented by the third parameter.
* If the cell is already occupied, leave the cell as it is, You will need
* this method to help convert run-length encodings to Oceans.
*
* #param x
* is the x-coordinate of the cell to place a shark in.
* #param y
* is the y-coordinate of the cell to place a shark in.
* #param feeding
* is an integer that indicates the shark's hunger. You may
* encode it any way you want; for instance, "feeding" may be the
* last timestep the shark was fed, or the amount of time that
* has passed since the shark was last fed, or the amount of time
* left before the shark will starve. It's upto you, but be
* consistent.
*/
public void addShark(int x, int y, int feeding) {
this.oceanMatrix[x][y] = Ocean.SHARK;
this.sharkHungerLevelMatrix[x][y] = feeding;
}
/**
* The following method is required for Part III.
*/
/**
* sharkFeeding() returns an integer that indicates the hunger of the shark
* in cell (x, y), using the same "feeding" representation as the parameter
* to addShark() described above. If cell (x, y) does not contain a shark,
* then its return value is undefined--that is, anything you want. Normally,
* this method should not be called if cell (x, y) does not contain a shark.
* You will need this method to help convert Oceans to run-length encodings.
*
* #param x
* is the x-coordinate of the cell whose contents are queried.
* #param y
* is the y-coordinate of the cell whose contents are queried.
*
*/
public int sharkFeeding(int x, int y) {
if(this.isShark(x, y)){
return this.sharkHungerLevelMatrix[x][y];
}
return Ocean.UNKNOWN;
}
}
While this is not a Swing program, you can substitute JFrame for Frame to leverage EXIT_ON_CLOSE.
JFrame frame = new JFrame("Sharks and Fish");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
The AWT approach is to add a WindowListener.
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
Have you tried?
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Monochrome grayscale image, get the intensity of a pixel

I'm attempting to derive an intensity value for a particular pixel in a monochrome "grayscale" image. I have some pseudocode, but thus far I've been unable to implement something that really works.
/**
* Retrieve the intensity value at location ('row', 'column') of the image 'img' and return it
* Note:
* - the 2D image is stored as an 8bit, 1D, row-major array of type byte
* - the data type byte is signed in Java
* - Slide 27 of chapter 2 introduces the representation of an image
* #param img in row major format
* #param row to evaluate
* #param column to evaluate
* #param width of img
* #param height of img
* #return the intensity value at row and column if within bounds, -1 otherwise
*/
public int getIntensityValue(byte[] img, int row, int column, int width, int height) {
int intensity = img[row,column];
return intensity;
}
Maybe this will help you:
http://docs.oracle.com/javase/7/docs/api/java/awt/image/BufferedImage.html
http://docs.oracle.com/javase/7/docs/api/javax/imageio/ImageIO.html
BufferedImage img = ImageIO.read(new File("filePath.png"));
int sRbgColor = img.getRGB(int x, int y);
Color c = new Color(sRbgColor);
int red = c.getRed();
int green = c.getGreen();
int blue = c.getBlue();
If it's monochrome, then red green and blue should be equal.

Categories

Resources