/**
* @(#)Main.java
*
* Copyright (c) 2013 Werner Randelshofer, Goldau, Switzerland.
* All rights reserved.
*
* You may not use, copy or modify this file, except in compliance with the
* license agreement you entered into with Werner Randelshofer.
* For details see accompanying license terms.
*/
package org.monte.quicktimedemo;
import org.monte.quicktimedemo.*;
import org.monte.media.quicktime.QuickTimeReader;
import org.monte.media.Buffer;
import org.monte.media.math.Rational;
import org.monte.media.quicktime.QuickTimeWriter;
import org.monte.media.Format;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.IndexColorModel;
import java.io.*;
import java.util.Random;
import static org.monte.media.VideoFormatKeys.*;
/**
* Demonstrates the use of {@link QuickTimeReader} and {@link QuickTimeWriter}.
*
* @author Werner Randelshofer
* @version $Id: Main.java 307 2013-01-06 11:06:05Z werner $
*/
public class Main {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
System.out.println("QuickTimeDemo "+Main.class.getPackage().getImplementationVersion());
System.out.println("This is a demo of the Monte Media library.");
System.out.println("Copyright © Werner Randelshofer. All Rights Reserved.");
System.out.println("License: Creative Commons Attribution 3.0.");
System.out.println();
try {
test(new File("quicktimedemo-jpg.mov"), new Format(EncodingKey, ENCODING_QUICKTIME_JPEG, DepthKey, 24, QualityKey, 1f));
test(new File("quicktimedemo-jpg-q0.5.mov"), new Format(EncodingKey, ENCODING_QUICKTIME_JPEG, DepthKey, 24, QualityKey, 0.5f));
test(new File("quicktimedemo-png.mov"), new Format(EncodingKey, ENCODING_QUICKTIME_PNG, DepthKey, 24));
test(new File("quicktimedemo-raw24.mov"), new Format(EncodingKey, ENCODING_QUICKTIME_RAW, DepthKey, 24));
test(new File("quicktimedemo-raw8.mov"), new Format(EncodingKey, ENCODING_QUICKTIME_RAW, DepthKey, 8));
test(new File("quicktimedemo-anim8.mov"), new Format(EncodingKey, ENCODING_QUICKTIME_ANIMATION, DepthKey, 8));
test(new File("quicktimedemo-tscc8.mov"), new Format(EncodingKey, ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE, DepthKey, 8));
test(new File("quicktimedemo-tscc24.mov"), new Format(EncodingKey, ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE, DepthKey, 24));
//test(new File("quicktimedemo-rle4.mov"), QuickTimeOutputStreamOLD.QuickTimeVideoFormat.RLE, 4, 1f);
} catch (IOException ex) {
ex.printStackTrace();
}
}
private static void test(File file, Format format) throws IOException {
testWriting(file,format);
try {
testReading(file);
} catch (UnsupportedOperationException e) {
e.printStackTrace();
}
}
private static void testWriting(File file, Format format) throws IOException {
System.out.println("Writing " + file);
// Make the format more specific
format = format.prepend(MediaTypeKey, MediaType.VIDEO, //
FrameRateKey, new Rational(30, 1),//
WidthKey, 320, //
HeightKey, 160);
// Create a buffered image for this format
BufferedImage img = createImage(format);
Graphics2D g = img.createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
QuickTimeWriter out = null;
try {
// Create the writer
out = new QuickTimeWriter(file);
// Add a track to the writer
out.addTrack(format);
out.setVideoColorTable(0, img.getColorModel());
// initialize the animation
Random rnd = new Random(0); // use seed 0 to get reproducable output
g.setBackground(Color.WHITE);
g.clearRect(0, 0, img.getWidth(), img.getHeight());
for (int i = 0; i < 100; i++) {
// Create an animation frame
g.setColor(new Color(rnd.nextInt()));
g.fillOval(rnd.nextInt(img.getWidth() - 30), rnd.nextInt(img.getHeight() - 30), 30, 30);
// write it to the writer
out.write(0, img, 1);
}
} finally {
// Close the writer
if (out != null) {
out.close();
}
// Dispose the graphics object
g.dispose();
}
}
private static void testReading(File file) throws IOException {
System.out.println("Reading " + file);
QuickTimeReader in = null;
try {
// Create the reader
in = new QuickTimeReader(file);
// Look for the first video track
int track = 0;
while (track < in.getTrackCount()
&& in.getFormat(track).get(MediaTypeKey) != MediaType.VIDEO) {
track++;
}
// Read images from the track
BufferedImage img = null;
do {
img = in.read(track, img);
//...to do: do something with the image...
} while (img != null);
} finally {
// Close the rader
if (in != null) {
in.close();
}
}
}
/** Creates a buffered image of the specified depth with a random color palette.*/
private static BufferedImage createImage(Format format) {
int depth = format.get(DepthKey);
int width = format.get(WidthKey);
int height = format.get(HeightKey);
Random rnd = new Random(0); // use seed 0 to get reproducable output
BufferedImage img;
switch (depth) {
case 24:
default: {
img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
break;
}
case 8: {
byte[] red = new byte[256];
byte[] green = new byte[256];
byte[] blue = new byte[256];
for (int i = 0; i < 255; i++) {
red[i] = (byte) rnd.nextInt(256);
green[i] = (byte) rnd.nextInt(256);
blue[i] = (byte) rnd.nextInt(256);
}
rnd.setSeed(0); // set back to 0 for reproducable output
IndexColorModel palette = new IndexColorModel(8, 256, red, green, blue);
img = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_INDEXED, palette);
break;
}
case 4: {
byte[] red = new byte[16];
byte[] green = new byte[16];
byte[] blue = new byte[16];
for (int i = 0; i < 15; i++) {
red[i] = (byte) rnd.nextInt(16);
green[i] = (byte) rnd.nextInt(16);
blue[i] = (byte) rnd.nextInt(16);
}
rnd.setSeed(0); // set back to 0 for reproducable output
IndexColorModel palette = new IndexColorModel(4, 16, red, green, blue);
img = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_INDEXED, palette);
break;
}
}
return img;
}
}