Java: Why/what are these threads monitoring? - java

I have a multithreaded Java application which splits an image into 4 chunks, then 4 threads (I have a quad-core CPU) each work on an individual chunk of the image, converting it to grayscale.
I found that it was quite slow for some reason, so I used the NetBeans profiler and found that the threads were "monitoring" (waiting) quite a lot. For example,
(green = running, red = monitoring)
I experimented with different numbers of threads, e.g. 2, and found that this still happened (the only time it didn't happen was with 1 thread).
Inside the threads, I commented out bits of their code until I narrowed the "big delay" down to this statement:
newImage.setRGB(i,j,newColor.getRGB()); // Write the new value for that pixel
If this is commented out, the code runs MUCH (almost 5x) faster, and there is NO thread monitoring:
So why does that one line cause so much delay? Is it the Color library (alongside BufferedImage)? Right now I'm going to try and get an array of ints as the RGB values instead of using a Color object and see how that goes.
Here is the source code:
PixelsManipulation.java (main class):
public final class PixelsManipulation{
private static Sequential sequentialGrayscaler = new Sequential();
public static void main(String[] args) throws FileNotFoundException, IOException, InterruptedException {
File file = new File("src/pixelsmanipulation/hiresimage.jpg");
FileInputStream fis = new FileInputStream(file);
BufferedImage image = ImageIO.read(fis); //reading the image file
int rows = 2; // 2 rows and 2 cols will split the image into quarters
int cols = 2;
int chunks = rows * cols; // 4 chunks, one for each quarter of the image
int chunkWidth = image.getWidth() / cols; // determines the chunk width and height
int chunkHeight = image.getHeight() / rows;
int count = 0;
BufferedImage imgs[] = new BufferedImage[chunks]; // Array to hold image chunks
for (int x = 0; x < rows; x++) {
for (int y = 0; y < cols; y++) {
//Initialize the image array with image chunks
imgs[count] = new BufferedImage(chunkWidth, chunkHeight, image.getType());
// draws the image chunk
Graphics2D gr = imgs[count++].createGraphics(); // Actually create an image for us to use
gr.drawImage(image, 0, 0, chunkWidth, chunkHeight, chunkWidth * y, chunkHeight * x, chunkWidth * y + chunkWidth, chunkHeight * x + chunkHeight, null);
gr.dispose();
}
}
//writing mini images into image files
for (int i = 0; i < imgs.length; i++) {
ImageIO.write(imgs[i], "jpg", new File("img" + i + ".jpg"));
}
System.out.println("Mini images created");
// Start threads with their respective quarters (chunks) of the image to work on
// I have a quad-core machine, so I can only use 4 threads on my CPU
Parallel parallelGrayscaler = new Parallel("thread-1", imgs[0]);
Parallel parallelGrayscaler2 = new Parallel("thread-2", imgs[1]);
Parallel parallelGrayscaler3 = new Parallel("thread-3", imgs[2]);
Parallel parallelGrayscaler4 = new Parallel("thread-4", imgs[3]);
// Sequential:
long startTime = System.currentTimeMillis();
sequentialGrayscaler.ConvertToGrayscale(image);
long stopTime = System.currentTimeMillis();
long elapsedTime = stopTime - startTime;
System.out.println("Sequential code executed in " + elapsedTime + " ms.");
// Multithreaded (parallel):
startTime = System.currentTimeMillis();
parallelGrayscaler.start();
parallelGrayscaler2.start();
parallelGrayscaler3.start();
parallelGrayscaler4.start();
// Main waits for threads to finish so that the program doesn't "end" (i.e. stop measuring time) before the threads finish
parallelGrayscaler.join();
parallelGrayscaler2.join();
parallelGrayscaler3.join();
parallelGrayscaler4.join();
stopTime = System.currentTimeMillis();
elapsedTime = stopTime - startTime;
System.out.println("Multithreaded (parallel) code executed in " + elapsedTime + " ms.");
}
}
Parallel.java:
// Let each of the 4 threads work on a different quarter of the image
public class Parallel extends Thread{//implements Runnable{
private String threadName;
private static BufferedImage myImage; // Calling it "my" image because each thread will have its own unique quarter of the image to work on
private static int width, height; // Image params
Parallel(String name, BufferedImage image){
threadName = name;
System.out.println("Creating "+ threadName);
myImage = image;
width = myImage.getWidth();
height = myImage.getHeight();
}
public void run(){
System.out.println("Running " + threadName);
// Pixel by pixel (for our quarter of the image)
for (int j = 0; j < height; j++){
for (int i = 0; i < width; i++){
// Traversing the image and converting the RGB values (doing the same thing as the sequential code but on a smaller scale)
Color c = new Color(myImage.getRGB(i,j));
int red = (int)(c.getRed() * 0.299);
int green = (int)(c.getGreen() * 0.587);
int blue = (int)(c.getBlue() * 0.114);
Color newColor = new Color(red + green + blue, red + green + blue, red + green + blue);
myImage.setRGB(i,j,newColor.getRGB()); // Write the new value for that pixel
}
}
File output = new File("src/pixelsmanipulation/"+threadName+"grayscale.jpg"); // Put it in a "lower level" folder so we can see it in the project view
try {
ImageIO.write(newImage, "jpg", output);
} catch (IOException ex) {
Logger.getLogger(Parallel.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("Thread " + threadName + " exiting. ---");
}
}
I am a beginner at threading in Java (as well as using BufferedImage), just curious as to why it's so slow.

Why is Parallel.myImage static? This will cause all the threads to share the same image. That might explain why they are waiting on each other.

Related

Converting audio file to create an Image, and converting audio file into a format usable by class Picture

I have to write a program in Java that uses StdAudio and Picture to create a two-dimensional color visualization of a sound file while it is playing but I'm not really sure how to.
Can someone tell me everything that I need or tell me what I need to do to "convert" the sound file so that it's readable by Picture?
I could grab the samples from the sound file and return them as array of doubles, but then how would that even create an image? How could those values even sync with the image?
I have been playing around in eclipse just trying to figure out how this could possibly even work but my code just ends up being a whole mess.
private final static int SAMPLE_RATE = 44100;
private static int WIDTH = 500;
private static int HEIGHT = 100;
private static JFrame frame;
private static Picture pic;
public static void main(String[] args) throws IOException
{
pic = new Picture(WIDTH, HEIGHT); // <- blank black image
String audioFile = "SampleTest2.wav";
double[] audio = StdAudio.read(audioFile);
frame = new JFrame();
frame.setContentPane(pic.getJLabel());
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setTitle("Sound Visualization");
frame.setResizable(false);
frame.pack();
frame.setVisible(true);
for (int k = 0; k < audio.length; k++)
StdAudio.play(audio[k]);
for (int i = 0; i < pic.width(); i ++)
{
for (int j = 0; j < pic.height(); j++)
{
pic.set(i, j, toColor(audio[SAMPLE_RATE + i]));
//frame.setContentPane(pic.getJLabel());
}
frame.repaint();
}
}
private static Color toColor(double colVal)
{
int r = (int) (((colVal + 1) / 2) * 255);
int g = (int) (((colVal + 1) / 2) * 255);
int b = (int) (((colVal + 1) / 2) * 255);
return new Color(r, g, b);
}
To use StdAudio you need wav file with sampling rate of 44100. It means every second of this sound consists of 44100 values(samples). When you load such file with duration of 1 second using method double[] read(String filename) you will obtain an array with 44100 elements. Javadoc of that method tells us the values will be between -1.0 and +1.0. We can iterate over every sample, map values from -1..1 range to 0..255 range (because colors need values from 0 to 255) and paint each pixel with this color. For better effect let's not paint single pixel but a column of 100 pixels.
I'll create image of 500x100. It will display only 500 samples so it will represent 500/44100 = only 0,01 of a second. To create empty picture of that size use:
Picture p = new Picture(500, 100);
To paint separate pixels along the image use:
for (int i = 0; i < 500; i++) {
p.set(i, 0, color);
}
and to display this picture use:
p.show();
Next, to create a color we need 3 values: red, green and blue components. Here we have only one value so the resulting image will be a greyscale image because saturation of every component will be the same value new Color(value, value, value). To quickly convert a range from -1..1 to 0..255 use such formula: (int) (((d + 1) / 2) * 255)
I used the first sound file from this site:
http://www.music.helsinki.fi/tmt/opetus/uusmedia/esim/index-e.html and the image I obtained is:
The code I used is:
import java.awt.Color;
import java.io.IOException;
public class StackOverflow58899141 {
private static int IMAGE_WIDTH = 500;
private static int IMAGE_HEIGHT = 100;
static String filename = "O:\\1.wav";
public static void main(final String[] args) throws IOException {
// reading sound file to samples
double[] samples = StdAudio.read(filename);
// creating empty image
Picture p = new Picture(IMAGE_WIDTH, IMAGE_HEIGHT);
// filling image from left to right
for (int i = 0; i < IMAGE_WIDTH; i++) {
// filling image from top to bottom
for (int j = 0; j < IMAGE_HEIGHT; j++) {
// adding 44100 to skip 1s of silence at the beginning
p.set(i, j, doubleToColor(samples[44100 + i]));
}
}
p.show();
}
// convert number from range -1.0..1.0 to 0..255
private static Color doubleToColor(double d) {
int val = (int) (((d + 1) / 2) * 255);
return new Color(val, val, val);
}
}
Now you have a solid start to understand how it works. Although Picture class allows easy saving of an image it doesn't allow animating. To achieve that you'd need to create own JFrame and draw image and delay drawing each column of pixels to get the animation effect.

Blur an image using java.util.concurrent, however, the resulting image is entirely black

I'm new to Java and is trying to learn the concept of high level concurrency. I saw this code at Java Tutorial Oracle. However, when I run the code, the IDE output an image that is entire black. Why is this happening? And also, how is the compute() method called?
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
import javax.imageio.ImageIO;
/**
* ForkBlur implements a simple horizontal image blur. It averages pixels in the
* source array and writes them to a destination array. The sThreshold value
* determines whether the blurring will be performed directly or split into two
* tasks.
*
* This is not the recommended way to blur images; it is only intended to
* illustrate the use of the Fork/Join framework.
*/
public class ForkBlur extends RecursiveAction {
private int[] mSource;
private int mStart;
private int mLength;
private int[] mDestination;
private int mBlurWidth = 15; // Processing window size, should be odd.
public ForkBlur(int[] src, int start, int length, int[] dst) {
mSource = src;
mStart = start;
mLength = length;
mDestination = dst;
}
// Average pixels from source, write results into destination.
protected void computeDirectly() {
int sidePixels = (mBlurWidth - 1) / 2;
for (int index = mStart; index < mStart + mLength; index++) {
// Calculate average.
float rt = 0, gt = 0, bt = 0;
for (int mi = -sidePixels; mi <= sidePixels; mi++) {
int mindex = Math.min(Math.max(mi + index, 0), mSource.length - 1);
int pixel = mSource[mindex];
rt += (float) ((pixel & 0x00ff0000) >> 16) / mBlurWidth;
gt += (float) ((pixel & 0x0000ff00) >> 8) / mBlurWidth;
bt += (float) ((pixel & 0x000000ff) >> 0) / mBlurWidth;
}
// Re-assemble destination pixel.
int dpixel = (0xff000000)
| (((int) rt) << 16)
| (((int) gt) << 8)
| (((int) bt) << 0);
mDestination[index] = dpixel;
}
}
protected static int sThreshold = 10000;
#Override
protected void compute() {
if (mLength < sThreshold) {
computeDirectly();
return;
}
int split = mLength / 2;
invokeAll(new ForkBlur(mSource, mStart, split, mDestination),
new ForkBlur(mSource, mStart + split, mLength - split,
mDestination));
}
// Plumbing follows.
public static void main(String[] args) throws Exception {
String srcName = "/Users/justin/NetBeansProjects/JavaTutorialOracle/src/JTOConcurrency/Screen Shot 2016-02-19 at 10.30.51 AM.jpg";
File srcFile = new File(srcName);
BufferedImage image = ImageIO.read(srcFile);
System.out.println("Source image: " + srcName);
BufferedImage blurredImage = blur(image);
String dstName = "blurred-tulips.jpg";
File dstFile = new File(dstName);
ImageIO.write(blurredImage, "jpg", dstFile);
System.out.println("Output image: " + dstName);
}
public static BufferedImage blur(BufferedImage srcImage) {
int w = srcImage.getWidth();
System.out.println("w: " + w);
int h = srcImage.getHeight();
System.out.println("h: " + h);
int[] src = srcImage.getRGB(0, 0, w, h, null, 0, w);
System.out.println("src[0]" + src[0]);
System.out.println("src[src.length - 1]: " + src[src.length - 1]);
int[] dst = new int[src.length];
System.out.println("src.length: " + src.length);
System.out.println("Array size is " + src.length);
System.out.println("Threshold is " + sThreshold);
int processors = Runtime.getRuntime().availableProcessors();
System.out.println(Integer.toString(processors) + " processor"
+ (processors != 1 ? "s are " : " is ")
+ "available");
ForkBlur fb = new ForkBlur(src, 0, src.length, dst);
ForkJoinPool pool = new ForkJoinPool();
long startTime = System.currentTimeMillis();
pool.invoke(fb);
long endTime = System.currentTimeMillis();
System.out.println("Image blur took " + (endTime - startTime) +
" milliseconds.");
BufferedImage dstImage =
new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
dstImage.setRGB(0, 0, w, h, dst, 0, w);
return dstImage;
}
}
Output:
Source image: /Users/justin/NetBeansProjects/JavaTutorialOracle/src/JTOConcurrency/Screen Shot 2016-02-19 at 10.30.51 AM.jpg
w: 454
h: 679
src[0]-5945082
src[src.length - 1]: -9673172
src.length: 308266
Array size is 308266
Threshold is 10000
4 processors are available
Image blur took 53 milliseconds.
Output image: blurred-tulips.jpg
I have attached some information about the photo I am using.
Using Oracle JRE 1.7.0_71 on OS X 10.11, I can reproduce the issue with a completely black output image.
However, there's no bug in your code, as I can see that the dst array contains the expected values after the fork/join blur operation.
Instead, the problem is our old friend, the ImageIO JPEGImageWriter. It does not write ARGB data as per the JPEG conventions, thus other software will misinterpret the colors*.
Simply change the line:
BufferedImage dstImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
to:
BufferedImage dstImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); // No alpha here
This will create an image without alpha. The JPEGImageWriter will just do the right thing, and the final output image looks as expected.
Another option, using a different file format, like PNG, also fixes the issue. I.e.:
ImageIO.write(blurredImage, "PNG", dstFile);
*) You can see this better if you use 0x00 instead of 0xff for alpha in the computeDirectly(...) method. You'll see an image with weird, probably pink/blueish colors.

Splitting an Image Object into a 2D Array in Java

The aim of this little project is to break down an image (in this case a flag) into pieces like a jigsaw and store each piece in part of a 2D array. I then want to be able to view each piece individually so that I know it has worked.
I have created an object class which loads and stores the image. I created the object in my main class and then pass it to my splitImage method which divides the image into chunks and stores in the array. I would like to be able to view a section of the array to check that the splitImage method has worked correctly. Long term however I do need to view the array as I will be determining the colour of the pixel in each image piece and counting how many of each colour is in the image. When I run the current code I get the following in the console,
Exception in thread "main" java.lang.ClassCastException: sun.awt.image.ToolkitImage cannot be cast to java.awt.image.BufferedImage
at sample.ImageFrame.splitImage(ImageFrame.java:28)
at sample.ImageFrame.main(ImageFrame.java:59)
28 is the line - BufferedImage image = (BufferedImage)((Image) icon.getImage());
59 is - ImageFrame.splitImage(imageSwing.label);
I have played around with these for some time, changing the position trying other options and have been unsuccessful. Help on this is much appreciated.
Code is below and thanks in advance.
public class ImageSwing extends JFrame
{
public JLabel label;
public ImageSwing()
{
super("Test Image Array");
setLayout(new FlowLayout());
Icon flag = new ImageIcon(getClass().getResource("Italy_flag.jpg"));
label = new JLabel(flag);
label.setToolTipText("Italian Flag");
add(label);
}//main
}//class
public class ImageFrame
{
//public ImageSwing imageSwing = new ImageSwing();
//ImageSwing imageSwing = new ImageSwing();
public static BufferedImage splitImage(JLabel i) throws IOException
{
//Holds the dimensions of image
int rows = 4;
int cols = 4;
ImageIcon icon = (ImageIcon)i.getIcon();
BufferedImage image = (BufferedImage)((Image) icon.getImage());
int chunks = rows * cols; //Total amount of image pieces
int partWidth = i.getWidth() / cols; // determines the piece width
int partHeight = i.getHeight() / rows; //determines the piece height
int count = 0;
BufferedImage[][] flagArray = new BufferedImage[rows][cols]; //2D Array to hold each image piece
for (int x = 0; x < rows; x++)
{
for (int y = 0; y < cols; y++)
{
//Initialize the image array with image chunks
flagArray[x][y] = new BufferedImage(partWidth, partHeight, image.getType());
// draws the image chunk
Graphics2D gr = flagArray[x][y].createGraphics();
gr.drawImage(image, 0, 0, partWidth, partHeight, partWidth * y, partHeight * x, partWidth * y + partWidth, partHeight * x + partHeight, null);
gr.dispose();
}
}
return flagArray[rows][cols];
}
public static void main(String[] args)
{
ImageSwing imageSwing = new ImageSwing();
try
{
ImageFrame.splitImage(imageSwing.label);
} catch (IOException e)
{
e.printStackTrace();
}
imageSwing.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
imageSwing.setSize(260,180);
imageSwing.setVisible(true);
}//main
}//class
Take a look at Java converting Image to BufferedImage
It provides a way to convert from Image to BufferedImage, which seems to be the problem.

How would I get a BufferedImage from an OpenGL window?

I'm coding a Java LWJGL game, and everything's going along great, except whenever I try to figure out a way to create a BufferedImage of the current game area. I've searched the internet, browsed all of the opengl functions, and I am getting no where... Anyone have any ideas? Here's all I have so far, but it only makes a blank .png:
if(Input.getKeyDown(Input.KEY_F2)) {
try {
String fileName = "screenshot-" + Util.getSystemTime(false);
File imageToSave = new File(MainComponent.screenshotsFolder, fileName + ".png");
int duplicate = 0;
while(true) {
duplicate++;
if(imageToSave.exists() == false) {
imageToSave.createNewFile();
break;
}
imageToSave = new File(MainComponent.screenshotsFolder, fileName + "_" + duplicate + ".png");
}
imageToSave.createNewFile();
// Create a buffered image:
BufferedImage image = new BufferedImage(MainComponent.WIDTH, MainComponent.HEIGHT, BufferedImage.TYPE_INT_ARGB);
//Wrtie the new buffered image to file:
ImageIO.write(image, "png", imageToSave);
} catch (IOException e) {
e.printStackTrace();
}
}
You never actually write something into your BufferedImage.
Read the Buffer
You can use glReadPixels to access the selected buffer. (I assume WIDTH and HEIGHT as your OpenGLContext dimensions.)
FloatBuffer imageData = BufferUtils.createFloatBuffer(WIDTH * HEIGHT * 3);
GL11.glReadPixels(0, 0, WIDTH, HEIGHT, GL11.GL_RGB, GL11.GL_FLOAT, imageData);
imageData.rewind();
Use whatever parameters suit your needs best, I just picked floats randomly.
Set the Image Data
You already figured out how to create and save your image, but in between you should also set some content to the image. You can do this with BufferedImage().setRGB() (Note that I don't use a good naming as you do, to keep this example concise.)
// create image
BufferedImage image = new BufferedImage(
WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB
);
// set content
image.setRGB(0, 0, WIDTH, HEIGHT, rgbArray, 0, WIDTH);
// save it
File outputfile = new File("Screenshot.png");
try {
ImageIO.write(image, "png", outputfile);
} catch (IOException e) {
e.printStackTrace();
}
The most tricky part is now getting the rgbArray. The problems are that
OpenGL gives you three values (in this case, i.e. using GL11.GL_RGB), while the BufferedImage expects one value.
OpenGL counts the rows from bottom to top while BufferedImage counts from top to bottom.
Calculate one Integer from three Floats
To get rid of problem one you have to calculate the integer value which fits the three number you get.
I will show this with a simple example, the color red which is (1.0f, 0.0f, 0.0f) in your FloatBuffer.
For the integer value it might be easy to think of numbers in hex values, as you might know from CSS where it's very common to name colors with those. Red would be #ff0000 in CSS or in Java of course 0xff0000.
Colors in RGB with integers are usually represented from 0 to 255 (or 00 to ff in hex), while you use 0 to 1 with floats or doubles. So first you have to map them to the correct range by simply multiplying the values by 255 and casting them to integers:
int r = (int)(fR * 255);
Now you can think of the hex value as just putting those numbers next to each other:
rgb = 255 0 0 = ff 00 00
To achieve this you can bitshift the integer values. Since one hex value (0-f) is 4 byte long, you have to shift the value of green 8 bytes to the left (two hex values) and the value of red 16 bytes. After that you can simply add them up.
int rgb = (r << 16) + (g << 8) + b;
Getting from BottomUp to TopDown
I know the terminology bottom-up -> top-down is not correct here, but it was catchy.
To access 2D data in a 1D array you usually use some formula (this case row-major order) like
int index = offset + (y - yOffset) * stride + (x - xOffset);
Since you want to have the complete image the offsets can be left out and the formula simplified to
int index = y * stride + x;
Of course the stride is simply the WIDTH, i.e. the maximum achievable x value (or in other terms the row length).
The problem you now face is that OpenGL uses the bottom row as row 0 while the BufferedImage uses the top row as row 0. To get rid of that problem just invert y:
int index = ((HEIGHT - 1) - y) * WIDTH + x;
Filling the int[]-array with the Buffer's Data
Now you know how to calculate the rgb value, the correct index and you have all data you need. Let's fill the int[]-array with those information.
int[] rgbArray = new int[WIDTH * HEIGHT];
for(int y = 0; y < HEIGHT; ++y) {
for(int x = 0; x < WIDTH; ++x) {
int r = (int)(imageData.get() * 255) << 16;
int g = (int)(imageData.get() * 255) << 8;
int b = (int)(imageData.get() * 255);
int i = ((HEIGHT - 1) - y) * WIDTH + x;
rgbArray[i] = r + g + b;
}
}
Note three things about this little piece of code.
The size of the array. Obviously it's just WIDTH * HEIGHT and not WIDTH * HEIGHT * 3 as the buffer's size was.
Since OpenGL uses row-major order, you have to use the column value (x) as the inner loop for this 2D array (and of course there are other ways to write this, but this seemed to be the most intuitive one).
Accessing imageData with imageData.get() is probably not the safest way to do it, but since the calculations are carefully done it should do the job just fine. Just remember to flip() or rewind() the buffer before calling get() the first time!
Putting it all together
So with all the information available now we can just put a method saveScreenshot() together.
private void saveScreenshot() {
// read current buffer
FloatBuffer imageData = BufferUtils.createFloatBuffer(WIDTH * HEIGHT * 3);
GL11.glReadPixels(
0, 0, WIDTH, HEIGHT, GL11.GL_RGB, GL11.GL_FLOAT, imageData
);
imageData.rewind();
// fill rgbArray for BufferedImage
int[] rgbArray = new int[WIDTH * HEIGHT];
for(int y = 0; y < HEIGHT; ++y) {
for(int x = 0; x < WIDTH; ++x) {
int r = (int)(imageData.get() * 255) << 16;
int g = (int)(imageData.get() * 255) << 8;
int b = (int)(imageData.get() * 255);
int i = ((HEIGHT - 1) - y) * WIDTH + x;
rgbArray[i] = r + g + b;
}
}
// create and save image
BufferedImage image = new BufferedImage(
WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB
);
image.setRGB(0, 0, WIDTH, HEIGHT, rgbArray, 0, WIDTH);
File outputfile = getNextScreenFile();
try {
ImageIO.write(image, "png", outputfile);
} catch (IOException e) {
e.printStackTrace();
System.err.println("Can not save screenshot!");
}
}
private File getNextScreenFile() {
// create image name
String fileName = "screenshot_" + getSystemTime(false);
File imageToSave = new File(fileName + ".png");
// check for duplicates
int duplicate = 0;
while(imageToSave.exists()) {
imageToSave = new File(fileName + "_" + ++duplicate + ".png");
}
return imageToSave;
}
// format the time
public static String getSystemTime(boolean getTimeOnly) {
SimpleDateFormat dateFormat = new SimpleDateFormat(
getTimeOnly?"HH-mm-ss":"yyyy-MM-dd'T'HH-mm-ss"
);
return dateFormat.format(new Date());
}
I also uploaded a very simple full working example.

Making a slideshow JAVA

My prompt is the following:
Write a program that takes the names of several image files as command-line arguments and displays them in a slide show (one every two seconds), using a fade effect to black and a fade from black between pictures.
I have the portion that fades the image but I'm having a problem that keeps all the images under one window. For example, when I run my program it will open a new window - fade picture A to the black picture. Open a new window with the black image and then fade to picture c. I'm trying to have it start from picture A, fade to black, and then fade into the new picture without opening a new window. I know it has to do with my pic.show() code but I'm not sure how to fix this.
Here's my code:
package fade;
import edu.princeton.cs.introcs.Picture;
import java.awt.Color;
public class Fade {
public static Color blend(Color c, Color d, double alpha) {
double r = (1 - alpha) * c.getRed() + alpha * d.getRed();
double g = (1 - alpha) * c.getGreen() + alpha * d.getGreen();
double b = (1 - alpha) * c.getBlue() + alpha * d.getBlue();
return new Color((int) r, (int) g, (int) b);
}
public static void pause(int t) {
try { Thread.sleep(t); }
catch (InterruptedException e) { System.out.println("Error sleeping"); }
}
public static void main(String[] args) {
for (int k = 1; k < args.length; k++) {
Picture source = new Picture(args[k]);
Picture target = new Picture(args[0]);
int M = 100;
int width = source.width();
int height = source.height();
Picture pic = new Picture(width, height);
for (int t = 0; t <= M; t++) {
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
Color c0 = source.get(i, j);
Color cM = target.get(i, j);
Color c = blend(c0, cM, (double) t / M);
pic.set(i, j, c);
}
}
pic.show();
}
}
}
}
Since you're only using a few images.
Create a Java Swing JFrame with a JPanel. Extend the JPanel so you can override the paintComponent method and paint a java.awt.image.BufferedImage.
Using javax.imageio.ImageIO, read each picture into a BufferedImage.
Create one BufferedImage that's all black.
Cycle through the BufferedImages.

Categories

Resources