Related
I created 2D array of floats in java, representing gray scale image, when each pixel is normalized - it between [0,1].
How can I take the 2D array and display the image (in gray scale of course)?
ty!
The easiest way is to make a BufferedImage out of it. To do that, you'll have to convert the values into colors:
int toRGB(float value) {
int part = Math.round(value * 255);
return part * 0x10101;
}
That first converts the 0-1 range into 0-255 range, then produces a color where all three channels (RGB - red, green and blue) have the same value, which makes a gray.
Then, to make the whole image, set all the pixel values:
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
image.setRGB(x, y, toRGB(theFloats[y][x]));
Once you have the image, you can save it to a file:
ImageIO.save(image, 'png', new File('some/path/file.png'));
Or, display it in some way, perhaps with Swing.. See for example this question.
Hello I have created excel sheet by using POI. I've added picture(jpg-file) in the next way:
Workbook wb = new HSSFWorkbook();
CreationHelper helper = wb.getCreationHelper();
//...
InputStream is = new FileInputStream("img.jpg");
byte[] bytes = IOUtils.toByteArray(is);
int picIdx = wb.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG);
Drawing drawing = sheet.createDrawingPatriarch();
ClientAnchor anchor = helper.createClientAnchor();
anchor.setCol1(5);
anchor.setRow1(5);
Picture pict = drawing.createPicture(anchor, picIdx);
pict.resize();
Now I want the picture to fit into that cell, but i don't want to change its aspect ratio. the scales i can put into resize are in respect to the cell, which obviously can have a different ratio. I tried to calculate the scales but the problem is, that I can't get or set the row height in pixel, only in pt and i can't compute the cells ratio either bc the i can't get width and height in the same unit... Any suggestions?
There is a Units class in POI, which provide convertion between pixel and point.
And here are some methods might be helpful to set cell's width and height.
1.Centimeters to Pixels
public static int cmToPx(double cm) {
return (int) Math.round(cm * 96 / 2.54D);
}
96 is my Monitor's DPI (check yours from dpilove)
and 1 inch = 2.54 centimeters
2.Centimeters to RowHeight
public static int cmToH(double cm) {
return (int) (Units.pixelToPoints(cmToPx(cm)) * 20); //POI's Units
}
Usage: sheet.setDefaultRowHeight(cmToH(1.0))
Reference: HSSFRow#getHeightInPoints
Set the height in "twips" or 1/20th of a point.
3.Centimeters to ColumnWidth
public static int cmToW(double cm) {
return (int) Math.round(((cmToPx(cm) - 5.0D) / 8 * 7 + 5) / 7 * 256);
}
Usage: sheet.setColumnWidth(cmToW(1.0))
Use (px - 5.0D) / 8 to convert from pixels to points in excel width.(When drag column's width in excel, pixels and points will show around your cursor)
Reference: HSSFSheet#setColumnWidth
Set the width (in units of 1/256th of a character width)
Excel uses the following formula (Section 3.3.1.12 of the OOXML spec):
// Excel width, not character width
width = Truncate([{Number of Visible Characters} * {Maximum Digit Width} + {5 pixel padding}]/{Maximum Digit Width} * 256) / 256
Using the Calibri font as an example, the maximum digit width of 11 point font size is 7 pixels (at 96 dpi). If you set a column width to be eight characters wide, e.g. setColumnWidth(columnIndex, 8*256), then the actual value of visible characters (the value shown in Excel) is derived from the following equation:
Truncate([numChars * 7 + 5] / 7 * 256) / 256 = 8;
Use XSSFClientAnchor to resize a picture to fill the cell and keep its ratio:
// set padding between picture and gridlines so gridlines would not covered by the picture
private static final double PADDING_SIZE = 10;
private static final int PADDING = Units.toEMU(PADDING_SIZE);
/**
* Draw Image inside specific cell
*
* #param wb workbook
* #param sheet sheet
* #param cellW cell width in pixels
* #param cellH cell height in pixels
* #param imgPath image path
* #param col the column (0 based) of the first cell.
* #param row the row (0 based) of the first cell.
* #param colSize the column size of cell
* #param rowSize the row size of cell
*/
public static void drawImageInCell(SXSSFWorkbook wb, SXSSFSheet sheet, int cellW, int cellH,
String imgPath, int col, int row, int colSize, int rowSize) throws IOException {
Path path = Paths.get(imgPath);
BufferedImage img = ImageIO.read(path.toFile());
int[] anchorArray = calCellAnchor(Units.pixelToPoints(cellW), Units.pixelToPoints(cellH),
img.getWidth(), img.getHeight());
XSSFClientAnchor anchor = new XSSFClientAnchor(anchorArray[0], anchorArray[1], anchorArray[2],
anchorArray[3], (short) col, row, (short) (col + colSize), row + rowSize);
int index = wb.addPicture(Files.readAllBytes(path), XSSFWorkbook.PICTURE_TYPE_JPEG);
sheet.createDrawingPatriarch().createPicture(anchor, index);
}
/**
* calculate POI cell anchor
*
* #param cellX cell width in excel points
* #param cellY cell height in excel points
* #param imgX image width
* #param imgY image height
*/
public static int[] calCellAnchor(double cellX, double cellY, int imgX, int imgY) {
// assume Y has fixed padding first
return calCoordinate(true, cellX, cellY, imgX, imgY);
}
/**
* calculate cell coordinate
*
* #param fixTop is Y has fixed padding
*/
private static int[] calCoordinate(boolean fixTop, double cellX, double cellY, int imgX, int imgY) {
double ratio = ((double) imgX) / imgY;
int x = (int) Math.round(Units.toEMU(cellY - 2 * PADDING_SIZE) * ratio);
x = (Units.toEMU(cellX) - x) / 2;
if (x < PADDING) {
return calCoordinate(false, cellY, cellX, imgY, imgX);
}
return calDirection(fixTop, x);
}
/**
* calculate X's direction
*
* #param fixTop is Y has fixed padding
* #param x X's padding
*/
private static int[] calDirection(boolean fixTop, int x) {
if (fixTop) {
return new int[] { x, PADDING, -x, -PADDING };
} else {
return new int[] { PADDING, x, -PADDING, -x };
}
}
I am using Base64 image data and I do it like this, for me it adds at given col/row and resizes it properly, also I dont want to to fit the cell it can axpand to whatever to right and bottom:
byte[] imageBase64Data = base64DataString.getBytes();
byte[] imageRawData = Base64.getDecoder().decode(imageBase64Data);
int imgWidth = 1920; // only initial if not known
int imgHeight = 1080; // only initial if not known
try {
BufferedImage img = ImageIO.read(new ByteArrayInputStream(imageRawData));
imgWidth = img.getWidth();
imgHeight = img.getHeight();
} catch (IOException e) {
e.printStackTrace();
}
int pictureIdx = workbook.addPicture(imageRawData, Workbook.PICTURE_TYPE_PNG);
CreationHelper helper = workbook.getCreationHelper();
Drawing drawing = sheet.createDrawingPatriarch();
ClientAnchor anchor = helper.createClientAnchor();
anchor.setCol1(desiredCol);
anchor.setRow1(desiredRow);
Picture picture = drawing.createPicture(anchor, pictureIdx);
picture.resize(0.7 * imgWidth / XSSFShape.PIXEL_DPI, 5 * imgHeight / XSSFShape.PIXEL_DPI);
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")));
Certainly, I am writing a program about Image to ASCII Conversion. I have already convert the image to grayscale, but I don't know to write the code of quantizing the image to MxN blocks
For every sub-image of MxN size, compute its average gray value
Store the computed average gray value to a new image).
Here is the program:
public static char[][] imageToASCII(Image img, int blockWidth, int blockHeight)
{
{
// Convert image from type Image to BufferedImage
BufferedImage bufImg = convert(img);
// Scan through each row of the image
for(int j=0; j<bufImg.getHeight(); j++)
{
// Scan through each columns of the image
for(int i=0; i<bufImg.getWidth(); i++)
{
// Returns an integer pixel in the default RGB color model
int values=bufImg.getRGB(i,j);
// Convert the single integer pixel value to RGB color
Color oldColor = new Color(values);
int red = oldColor.getRed(); // get red value
int green = oldColor.getGreen(); // get green value
int blue = oldColor.getBlue(); // get blue value
// Convert RGB to grayscale using formula
// gray = 0.299 * R + 0.587 * G + 0.114 * B
double grayVal = 0.299*red + 0.587*green + 0.114*blue;
// Assign each channel of RGB with the same value
Color newColor = new Color((int)grayVal, (int)grayVal, (int)grayVal);
// Get back the integer representation of RGB color
// and assign it back to the original position
bufImg.setRGB(i, j, newColor.getRGB());
}
return null;
Maybe you just need to divide the image into blocks of MxN size. This is similar to the Microblock in video coding.
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.