Java: My height map generator only writes binary - java

So today I started with a new project. I want to make a simple heightmap generator in java, so I tried the following:
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Heightmap {
public static int width = 200;
public static int height = 200;
public static void main(String[] args) {
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY );
for(int x = 0; x < width; x++){
for(int y = 0; y < height; y++){
bufferedImage.setRGB(x, y, (byte )(Math.random() * 256 + 128) ); // + 128 because byte goes from -128 to 127
}
}
File outputFile = new File("heightmap.png");
try {
ImageIO.write(bufferedImage, "png", outputFile);
}catch (IOException ioex){
ioex.printStackTrace();
}
}
}
The code is very simple, I plan to try perlin noise as the next step. But first I need to resolve this problem:
Generated Heightmap
The pixels in heightmap.png are either completely white, or completely black. There's no grays in the image, which of course is necessary in a heightmap. Does anyone know what I did wrong?
is it the BufferedImage.TYPE_BYTE_GRAY part? If so, what should I use instead?

After a friend set me on the right track, I found the solution.
Instead of BufferedImage.TYPE_BYTE_GRAY I used BufferdImage.TYPE_INT_RGB. So this is indeed where I went wrong. Also I added the object Color randomColor, wherein the RGB values all share the same integer with a value from 0 to 255. Then in BufferedImage.setRGB I use the color code of randomColor (so R,G,B = 255 gives #FFFFFF, which is white) as the value of pixel (x,y):
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Heightmap {
public static int width = 200;
public static int height = 200;
public static void main(String[] args) {
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB );
for(int x = 0; x < width; x++){
for(int y = 0; y < height; y++){
int randomValue = (int)(Math.random() * 256);
Color randomColor = new Color( randomValue, randomValue, randomValue);
bufferedImage.setRGB(x, y, randomColor.getRGB());
}
}
File outputFile = new File("heightmap.png");
try {
ImageIO.write(bufferedImage, "png", outputFile);
}catch (IOException ioex){
ioex.printStackTrace();
}
}
}
Now the heightmap.png gives what I expected: Heightmap.png

Related

Color Parameter Outside of Expected Range Error

I am writing a program for my high school CS class to change the color filter on an image to red. When I try to run the test file I am getting an error that says "Color parameter outside of expected range: Red Green Blue". I have no experience with color filtering in Java so this problem has thrown me for an absolute loop in this class.
In the color.getColor section of my code I tried to add to Red, and also took that off and tried to just subtract the other colors. Here is my code:
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
public class CopyToRed {
public static void toRedScale(File input, File output) {
try {
ImageInputStream iis = ImageIO.createImageInputStream(input);
Iterator<ImageReader> iterator = ImageIO.getImageReaders(iis);
ImageReader reader = iterator.next();
String imageFormat = reader.getFormatName();
BufferedImage image = ImageIO.read(iis);
int width = image.getWidth();
int height = image.getHeight();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
Color color = new Color(image.getRGB(x, y));
int red = (int)(color.getRed());
int green = (int)(color.getGreen());
int blue = (int)(color.getBlue());
int sum = red + green + blue;
Color shadeOfRed = new Color(sum, sum, sum);
image.setRGB(x, y, shadeOfRed.getRGB());
}
}
ImageIO.write(image, imageFormat, output);
} catch(IOException ex) {
ex.printStackTrace();
}
}
}

A program that cuts GIFs into frames and converts them into pixels is using too much memory

I wrote a code which splits a gif-image into frames.
Then, they are scaled-down into smaller ones, the resolution is 128 * 128 pixels. Then they combine a full frame with a specific resolution.
The getFrames (String path) method gets the GIF file along the path from the jar and creates image frames.
The getResizedimages (…) method cuts the frame into smaller 128 by 128 images.
The getPixels (Bufferedlmage image) method gets an array of pixels from an image.
The problem is that during the execution of this code (via the test method), a very very large amount of memory is used even at the stage of execution of the getFrames (…) method or the getFramesRaw (…) method.
import com.sun.imageio.plugins.gif.GIFImageReader;
import com.sun.imageio.plugins.gif.GIFImageReaderSpi;
import org.apache.commons.io.FileUtils;
import org.bukkit.map.MapPalette;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class Gif {
static void test(String path, int height, int width) {
List<BufferedImage> images = getFrames(path);
for (int x = 0; x < width; x ++) for (int y = 0; y < height; y ++)
getResizedFrames(images, width, height, x, y).forEach(image -> getPixels(image));
}
#SuppressWarnings("deprecation")
public static byte[] getPixels(BufferedImage image) {
int pixelCount = image.getWidth() * image.getHeight();
int[] pixels = new int[pixelCount];
image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
byte[] colors = new byte[pixelCount];
for (int i = 0; i < pixelCount; i++)
colors[i] = MapPalette.matchColor(new Color(pixels[i], true));
return colors;
}
public static BufferedImage getScaledImage(BufferedImage image) {
BufferedImage newImg = new BufferedImage(128, 128, 3);
Graphics2D g2 = newImg.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(image, 0, 0, 128, 128, null);
g2.dispose();
return newImg;
}
public static BufferedImage cropImage(BufferedImage completeImg, int width, int height, int xCoord, int yCoord) {
int coordWidth = completeImg.getWidth() / width;
int coordHeight = completeImg.getHeight() / height;
BufferedImage croppedImg = new BufferedImage(completeImg.getWidth(), completeImg.getHeight(), 1);
Graphics2D g2 = (Graphics2D)croppedImg.getGraphics();
g2.drawImage(completeImg, 0, 0, completeImg.getWidth(), completeImg.getHeight(), null);
g2.dispose();
BufferedImage image = croppedImg.getSubimage(coordWidth * xCoord, coordHeight * yCoord, coordWidth, coordHeight);
return getScaledImage(image);
}
public static java.util.List<BufferedImage> getFramesRaw(String path) {
java.util.List<BufferedImage> frames = new ArrayList<>();
try {
File file = File.createTempFile("data", ".gif");
InputStream stream = Main.class.getResourceAsStream(path);
FileUtils.copyInputStreamToFile(stream, file);
stream.close();
ImageInputStream inputStream = ImageIO.createImageInputStream(file);
ImageReader ir = new GIFImageReader(new GIFImageReaderSpi());
ir.setInput(inputStream);
int number = ir.getNumImages(true);
for (int i = 0; i < number; i++) frames.add(ir.read(i));
inputStream.close();
System.gc();
} catch (Exception e) {
e.printStackTrace();
}
return frames;
}
public static java.util.List<BufferedImage> getFrames(String path) {
java.util.List<BufferedImage> copies = new ArrayList<>();
java.util.List<BufferedImage> frames = getFramesRaw(path);
copies.add(frames.remove(0));
int width = copies.get(0).getWidth(), height = copies.get(0).getHeight();
for (BufferedImage frame : frames) {
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics();
g.drawImage(copies.get(copies.size()-1),0,0,null);
g.drawImage(frame,0,0,null);
copies.add(img);
}
return copies;
}
public static java.util.List<BufferedImage> getResizedFrames(java.util.List<BufferedImage> frames, int width, int height, int x, int y) {
List<BufferedImage> copies = new ArrayList<>();
for (BufferedImage image : frames)
copies.add(cropImage(image, width, height, width - 1 - x, height - 1 - y));
return copies;
}
}
I need your help.
The reason your program uses a lot of memory, is because your code operates at all the frames at each step (in many small loops). All the decoded image data for all the frames will be held in memory at the same time, resulting in unnecessary memory usage. While this may feel logical, it is for sure not efficient.
Instead, create one loop that does all the needed operations for a single frame, before moving on to the next.
Something like this:
public static void test(String path) throws IOException {
List<BufferedImage> thumbnails = new ArrayList<>();
readFrames(path, image -> thumbnails.add(getScaledImage(image)));
}
private static void readFrames(String path, Consumer<BufferedImage> forEachFrame) throws IOException {
try (ImageInputStream inputStream = ImageIO.createImageInputStream(GifSplitter.class.getResourceAsStream(path))) {
Iterator<ImageReader> readers = ImageIO.getImageReaders(inputStream); // ImageIO detects format, no need to hardcode GIF plugin
if (!readers.hasNext()) {
return;
}
ImageReader ir = readers.next();
ir.setInput(inputStream);
// For GIF format (which does not contain frame count in header),
// it's more efficient to just read each frame until IOOBE occurs,
// instead of invoking getNumImages(true)
int i = 0;
while (i >= 0) {
try {
BufferedImage image = ir.read(i++);
// crop, scale, etc, for a SINGLE image
forEachFrame.accept(image);
}
catch (IndexOutOfBoundsException endOfGif) {
// No more frames
break;
}
}
ir.dispose();
}
}

Comparing two pixels ( Color of them )

Im making project for my uni, and I have a problem with one thing - everything works well, but there is bug with comparing colors of two pixels.
I have to count area of some figure, and I have to use MonteCarlo method. ( generate random points, count points in figure and out, calculete figure area )
And some points are counted well, some dont, I have no idea whats wrong, Im trying to solve that few hours...
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.*;
public class Runner extends JApplet{
private BufferedImage img;
public ArrayList<Point> w;
public ArrayList<Point> poza;
public BufferedImage output;
public void init(){
try{
img = ImageIO.read(new File("figura.gif"));
} catch (IOException e){
e.getStackTrace();
System.err.println("Nie ma obrazkaXD");
}
}
public void paint(Graphics g){
w = new ArrayList<Point>();
poza = new ArrayList<>();
super.paint(g);
Random random = new Random();
int wys = img.getHeight();
int szer = img.getWidth();
g.drawImage(img, 0, 0, wys, szer, null);
for (int i = 0; i < 1000; i++) {
int x = random.nextInt(wys);
int y = random.nextInt(szer);
Point p = new Point(x,y);
g.setColor(Color.GREEN);
g.drawOval(y, x, 1, 1);
Color c = new Color(img.getRGB(y, x));;
if(c.equals(Color.BLACK)){
w.add(p);
g.setColor(Color.RED);
g.drawOval(y, x, 1, 1);
}else{
poza.add(p);
}
}
float a = w.size();
float b = poza.size()+w.size();
float poleProstokata = wys*szer;
float pole = a/b*poleProstokata;
}
I would suggest you to switch the y and y Coordinate, because as described in the Oracle Documentation :
https://docs.oracle.com/javase/7/docs/api/java/awt/image/BufferedImage.html#getRGB(int,%20int)
The method getRGB takes the X first and the Y second, so you'll have to use
Color c = new Color(img.getRGB(x, y));
instead of
Color c = new Color(img.getRGB(y, x));;
and why dont use an int ? I mean, you always convert the returned int from getRGB to a color and compare it. But why dont create a int from the Color Black and compare it to the int returned from getRGB(x,y) ?
Heres what I suggest :
int black=Color.BLACK.getRGB();
at the beginning of your paint method
and in your loop :
int c=img.getRGB(y, x);
and compare them :
if (black==c) {
//Do your stuff...
}

Converting BufferedImage to binary without image going completely black

i am trying to create an OCR to read 7 segment led off of old camera reals. this is my pre processing (ignore the random imports been trying a bunch of options)right now i am changing the image to negative from orange and gray and changing it to Grayscale, once i try to change gray scale to binary it just blacks out the image and i have no clue to remedy it with this code.
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.color.*;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class PreProcess2 {
public static void main(String [] args) {
BufferedImage img = null;
File dir = new File ("Directory/file/example photo");
File[] dirList = dir.listFiles();
for (int i = 1; i < dirList.length; i++) {
try{
img = ImageIO.read(dirList[i].getAbsoluteFile());
int d = 2;
int iw = img.getWidth();
int ih = img.getHeight();
int xb = ((((iw/d)/d)+(iw/d)));
int yb = ((((ih/d)/d)+(ih/d)));
try {
//Isolates Width
for (int x = xb ; x <= (iw-1); x++){
//Isolates Height
for (int y = yb; y <= (ih-1); y++){
int p = img.getRGB(x, y);
int a = (p>>24)&0xff;
int r = (p>>16)&0xff;
int g = (p>>8)&0xff;
int b = p&0xff;
//subtract RGB from 255
r = 255 - r;
g = 255 - g;
b = 255 - b;
//set new RGB from 255
p = (a<<24) | (r<<16) | (g<<8) | b;
img.setRGB(x, y, p);
}
}
//Prints out if pixel is out of bounds
}catch (ArrayIndexOutOfBoundsException e) {
System.out.println("out of bounds");
}
BufferedImage result = new BufferedImage(
img.getWidth(),
img.getHeight(),
BufferedImage.TYPE_BYTE_GRAY);
Graphics g = result.getGraphics();
g.drawImage(img, 0, 0, null);
g.dispose();
BufferedImage gray = new BufferedImage(result.getWidth(), result.getHeight(),
BufferedImage.TYPE_BYTE_BINARY);
BufferedImage croppedImage = gray.getSubimage(615, 445, 110, 35);
//Saves file to processed file location
File outputfile = new File(dir +"/Processed/" + dirList[i].getName());
ImageIO.write(croppedImage, "jpg", outputfile);
//Print out if not able to retrieve file
} catch (IOException e) {
System.out.println("Done");
}
}
}
}
Blacked out
Negative
UPDATE:
BufferedImage binary = new BufferedImage(iw, ih, BufferedImage.TYPE_BYTE_BINARY);
Graphics biG = binary.getGraphics();
biG.drawImage(gray, 0, 0, null);
biG.dispose();
managed to find a partial answer with the help of a colleague now i need to figure out how to clean up the noise in the images, any ideas?

Get color of each pixel of an image using BufferedImages

I am trying to get every single color of every single pixel of an image.
My idea was following:
int[] pixels;
BufferedImage image;
image = ImageIO.read(this.getClass.getResources("image.png");
int[] pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();
Is that right? I can't even check what the "pixels" array contains, because i get following error:
java.awt.image.DataBufferByte cannot be cast to java.awt.image.DataBufferInt
I just would like to receive the color of every pixel in an array, how do i achieve that?
import java.io.*;
import java.awt.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
public class GetPixelColor {
public static void main(String args[]) throws IOException {
File file = new File("your_file.jpg");
BufferedImage image = ImageIO.read(file);
// Getting pixel color by position x and y
int clr = image.getRGB(x, y);
int red = (clr & 0x00ff0000) >> 16;
int green = (clr & 0x0000ff00) >> 8;
int blue = clr & 0x000000ff;
System.out.println("Red Color value = " + red);
System.out.println("Green Color value = " + green);
System.out.println("Blue Color value = " + blue);
}
}
of course you have to add a for loop for all pixels
The problem (also with the answer that was linked from the first answer) is that you hardly ever know what exact type your buffered image will be after reading it with ImageIO. It could contain a DataBufferByte or a DataBufferInt. You may deduce it in some cases via BufferedImage#getType(), but in the worst case, it has type TYPE_CUSTOM, and then you can only fall back to some instanceof tests.
However, you can convert your image into a BufferedImage that is guaranteed to have a DataBufferInt with ARGB values - namely with something like
public static BufferedImage convertToARGB(BufferedImage image)
{
BufferedImage newImage = new BufferedImage(
image.getWidth(), image.getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = newImage.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
return newImage;
}
Otherwise, you can call image.getRGB(x,y), which may perform the required conversions on the fly.
BTW: Note that obtaining the data buffer of a BufferedImage may degrade painting performance, because the image can no longer be "managed" and kept in VRAM internally.
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
BufferedImage bufferedImage = ImageIO.read(new File("norris.jpg"));
int height = bufferedImage.getHeight(), width = bufferedImage.getWidth();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int RGBA = bufferedImage.getRGB(x, y);
int alpha = (RGBA >> 24) & 255;
int red = (RGBA >> 16) & 255;
int green = (RGBA >> 8) & 255;
int blue = RGBA & 255;
}
}
}
}
Assume the buffered image represents an image with 8-bit RGBA color components packed into integer pixels, I search for "RGBA color space" on wikipedia and found following:
In the byte-order scheme, "RGBA" is understood to mean a byte R,
followed by a byte G, followed by a byte B, and followed by a byte A.
This scheme is commonly used for describing file formats or network
protocols, which are both byte-oriented.
With simple Bitwise and Bitshift you can get the value of each color and the alpha value of the pixel.
Very interesting is also the other order scheme of RGBA:
In the word-order scheme, "RGBA" is understood to represent a complete
32-bit word, where R is more significant than G, which is more
significant than B, which is more significant than A. This scheme can
be used to describe the memory layout on a particular system. Its
meaning varies depending on the endianness of the system.
byte[] pixels
not
int[] pixels
try this : Java - get pixel array from image
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class ImageUtil {
public static Color[][] loadPixelsFromImage(File file) throws IOException {
BufferedImage image = ImageIO.read(file);
Color[][] colors = new Color[image.getWidth()][image.getHeight()];
for (int x = 0; x < image.getWidth(); x++) {
for (int y = 0; y < image.getHeight(); y++) {
colors[x][y] = new Color(image.getRGB(x, y));
}
}
return colors;
}
public static void main(String[] args) throws IOException {
Color[][] colors = loadPixelsFromImage(new File("image.png"));
System.out.println("Color[0][0] = " + colors[0][0]);
}
}
I know this has already been answered, but the answers given are a bit convoluted and could use improvement.
The simple idea is to just loop through every (x,y) pixel in the image, and get the color of that pixel.
BufferedImage image = MyImageLoader.getSomeImage();
for ( int x = 0; x < image.getWidth(); x++ ) {
for( int y = 0; y < image.getHeight(); y++ ) {
Color pixel = new Color( image.getRGB( x, y ) );
// Do something with pixel color here :)
}
}
You could then perhaps wrap this method in a class, and implement Java's Iterable API.
class IterableImage implements Iterable<Color> {
private BufferedImage image;
public IterableImage( BufferedImage image ) {
this.image = image;
}
#Override
public Iterator<Color> iterator() {
return new Itr();
}
private final class Itr implements Iterator<Color> {
private int x = 0, y = 0;
#Override
public boolean hasNext() {
return x < image.getWidth && y < image.getHeight();
}
#Override
public Color next() {
x += 1;
if ( x >= image.getWidth() ) {
x = 0;
y += 1;
}
return new Color( image.getRGB( x, y ) );
}
}
}
The usage of which might look something like the following
BufferedImage image = MyImageLoader.getSomeImage();
for ( Color color : new IterableImage( image ) ) {
// Do something with color here :)
}

Categories

Resources