/*
* 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.nio.ByteBuffer;
public class Util {
// Note, this is purely an exchange class, large arrays should not be stored of these
// ints are used to avoid signing problems with bytes
public static class YUVColor {
public int y, u, v;
}
public static class RGBColor {
public int r, g, b;
public RGBColor() {}
public RGBColor(int rgb) {
r = (rgb >> 16) & 0xff;
g = (rgb >> 8) & 0xff;
b = (rgb ) & 0xff;
}
}
public static int unsign(byte b) {
return (b&0xff);
}
public static int getUByte(ByteBuffer b) {
return unsign(b.get());
}
public static int getUByte(ByteBuffer b, int ind) {
return unsign(b.get(ind));
}
public static int getUByte(byte[] b, int ind) {
return unsign(b[ind]);
}
public static int clamp255(int i) {
if (i < 0) return 0;
if (i > 255) return 255;
return i;
}
public static int clamp255d(double d) {
return clamp255((int)d);
}
public static int avg3(int a, int b, int c) {
return (a + b + b + c +2) >> 2;
}
public static int avg2(int a, int b) {
return (a + b + 1) >> 1;
}
public static int yuvToRGBInt(YUVColor yuv) {
return yuvToRGBInt(yuv.y, yuv.u, yuv.v);
}
public static int yuvToRGBInt(int y, int u, int v) {
int ret = 0;
int r = clamp255d(1.1644*(y-16) + (1.5960 * (v - 128)));
int g = clamp255d(1.1644*(y-16) - (0.3918 * (u - 128)) - (0.8130 * (v - 128)));
int b = clamp255d(1.1644*(y-16) + (2.0172 * (u - 128)));
ret += r << 16;
ret += g << 8;
ret += b;
return ret;
}
public static YUVColor rgbToYUV(RGBColor rgb) {
return rgbToYUV(rgb.r, rgb.g, rgb.b);
}
public static int rgbToY(int rgb) {
int r = (rgb >> 16) & 0xff;
int g = (rgb >> 8) & 0xff;
int b = (rgb ) & 0xff;
return (int)( 16 + 0.2568*r + 0.5052*g + 0.0979*b);
}
public static int rgbToU(int rgb) {
int r = (rgb >> 16) & 0xff;
int g = (rgb >> 8) & 0xff;
int b = (rgb ) & 0xff;
return (int)(128 - 0.1482*r - 0.2910*g + 0.4392*b);
}
public static int rgbToV(int rgb) {
int r = (rgb >> 16) & 0xff;
int g = (rgb >> 8) & 0xff;
int b = (rgb ) & 0xff;
return (int)(128 + 0.4392*r - 0.3678*g - 0.0714*b);
}
public static YUVColor rgbToYUV(int r, int g, int b) {
r = clamp255(r);
g = clamp255(g);
b = clamp255(b);
YUVColor ret = new YUVColor();
ret.y = (int)( 16 + 0.2568*r + 0.5052*g + 0.0979*b);
ret.u = (int)(128 - 0.1482*r - 0.2910*g + 0.4392*b);
ret.v = (int)(128 + 0.4392*r - 0.3678*g - 0.0714*b);
return ret;
}
public static void addResidueToPlane(int x, int y, short[] res, int stride, byte[] plane) {
for (int j = 0; j < 4; ++j) {
for (int i = 0; i < 4; ++i) {
int ind = j*4+i;
int val = Util.getUByte(plane, (y+j)*stride+x+i);
val += res[ind];
plane[(y+j)*stride+x+i] = (byte)Util.clamp255(val);
}
}
}
/**
* Get the rgb average of 4 pixels in a BufferedImage, handles edge cases
* @param img
* @param x
* @param y
* @return
*/
public static RGBColor avgPixel2(BufferedImage img, int x, int y) {
assert(x < img.getWidth());
assert(y < img.getHeight());
int numPixels = 1;
int r = 0, g = 0, b = 0;
RGBColor rgb;
rgb = new RGBColor(img.getRGB(x, y));
r += rgb.r; g += rgb.g; b += rgb.b;
if (x+1 < img.getWidth()) {
rgb = new RGBColor(img.getRGB(x+1, y));
r += rgb.r; g += rgb.g; b += rgb.b;
numPixels++;
}
if (y+1 < img.getHeight()) {
rgb = new RGBColor(img.getRGB(x, y+1));
r += rgb.r; g += rgb.g; b += rgb.b;
numPixels++;
}
if ((x+1 < img.getWidth()) &&(y+1 < img.getHeight())) {
rgb = new RGBColor(img.getRGB(x+1, y+1));
r += rgb.r; g += rgb.g; b += rgb.b;
numPixels++;
}
rgb = new RGBColor();
rgb.r = r / numPixels;
rgb.g = g / numPixels;
rgb.b = b / numPixels;
return rgb;
}
}