/*
* JaamSim Discrete Event Simulation
* Copyright (C) 2012 Ausenco Engineering Canada Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jaamsim.video.vp8;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class YUVImage {
final byte[] yPlane;
final byte[] uPlane;
final byte[] vPlane;
final int width;
final int height;
public static YUVImage fromFile(String filename) {
FileInputStream in;
try {
in = new FileInputStream(filename);
int w = in.read() + (in.read() << 8) + (in.read() << 16) + (in.read() << 24);
int h = in.read() + (in.read() << 8) + (in.read() << 16) + (in.read() << 24);
YUVImage ret = new YUVImage(w, h);
int read = in.read(ret.yPlane);
if (read != w*h) {
System.out.printf("Only read %d bytes for y\n", read);
in.close();
return null;
}
read = in.read(ret.uPlane);
if (read != w*h/4) {
System.out.printf("Only read %d bytes for u\n", read);
in.close();
return null;
}
read = in.read(ret.vPlane);
if (read != w*h/4) {
System.out.printf("Only read %d bytes for v\n", read);
in.close();
return null;
}
in.close();
return ret;
} catch (FileNotFoundException ex) {
System.out.println("Could not open file");
System.out.println(ex.getMessage());
return null;
} catch (IOException ex) {
System.out.println(ex.getMessage());
return null;
}
}
public YUVImage(int width, int height) {
this.width = width;
this.height = height;
yPlane = new byte[width * height];
int cWidth = (width + 1) >> 1;
int cHeight = (height + 1) >> 1;
uPlane = new byte[cWidth * cHeight];
vPlane = new byte[cWidth * cHeight];
}
/**
* Debug, show this image in a JFrame
* @param scale
* @param withChroma
* @param title
*/
public void show(int scale, boolean withChroma, String title) {
BufferedImage image = new BufferedImage(width*scale, height*scale, BufferedImage.TYPE_INT_RGB);
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
int chX = x >> 1;
int chY = y >> 1;
int chW = width >> 1;
int index = y*width + x;
int chIndex = chY*chW + chX;
int val = 0;
if (withChroma) {
val = Util.yuvToRGBInt(Util.getUByte(yPlane, index), Util.getUByte(uPlane, chIndex), Util.getUByte(vPlane, chIndex));
} else {
val = Util.yuvToRGBInt(Util.getUByte(yPlane, index), 128, 128);
}
for (int j = 0; j < scale; ++j) {
for (int i = 0; i < scale; ++i) {
image.setRGB(x*scale+i, y*scale+j, val);
}
}
}
}
JFrame frame = new JFrame(title);
ImageIcon icon = new ImageIcon(image);
JLabel label = new JLabel(icon, JLabel.CENTER);
label.setSize(width*scale, height*scale);
frame.add(label);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
/**
* Note, for performance reasons, this will ONLY work on BufferedImage's that use the TYPE_INT_ARGB or TYPE_INT_RGB data types.
* @param img
*/
public void fillFromBuffered(BufferedImage img) {
int w = img.getWidth();
int h = img.getHeight();
int blockW = (w + 15) & ~0x0f;
int blockH = (h + 15) & ~0x0f;
assert(blockW <= width);
assert(blockH <= height);
// Going to do two passes on this image, one for Y, one for UV as they use different
// resolutions
DataBufferInt ints = (DataBufferInt)img.getData().getDataBuffer();
int[] rgbs = ints.getData();
for (int y = 0; y < h; ++y) {
for (int x = 0; x < w; ++x) {
int luma = Util.rgbToY(rgbs[y*w+x]);
yPlane[y*width+x] = (byte)luma;
if ((y&1) == 0 && (x&1) == 0) {
// Add color
int u = Util.rgbToU(rgbs[y*w+x]);
int v = Util.rgbToV(rgbs[y*w+x]);
uPlane[y*width/4+x/2] = (byte)u;
vPlane[y*width/4+x/2] = (byte)v;
}
}
}
}
}