package org.jcodec.common.model; import static java.lang.System.arraycopy; import static org.jcodec.common.model.ColorSpace.MAX_PLANES; import java.lang.IllegalArgumentException; /** * This class is part of JCodec ( www.jcodec.org ) This software is distributed * under FreeBSD License * * A YUV picture * * @author The JCodec project * @deprecated Use org.jcodec.common.model.Picture8Bit and related APIs * */ public class Picture { private ColorSpace color; private int width; private int height; private int[][] data; private Rect crop; private int bitDepth; public static Picture createPicture(int width, int height, int[][] data, ColorSpace color) { return new Picture(width, height, data, color, 8, new Rect(0, 0, width, height)); } public static Picture createPictureWithDepth(int width, int height, int[][] data, ColorSpace color, int bitDepth) { return new Picture(width, height, data, color, bitDepth, new Rect(0, 0, width, height)); } public static Picture createPictureCropped(int width, int height, int[][] data, ColorSpace color, Rect crop) { return new Picture(width, height, data, color, 8, crop); } public Picture(int width, int height, int[][] data, ColorSpace color, int bitDepth, Rect crop) { this.width = width; this.height = height; this.data = data; this.color = color; this.crop = crop; this.bitDepth = bitDepth; } public static Picture clonePicture(Picture other) { return new Picture(other.width, other.height, other.data, other.color, other.bitDepth, other.crop); } public static Picture create(int width, int height, ColorSpace colorSpace) { return doCreate(width, height, colorSpace, 8, null); } public static Picture createWithDepth(int width, int height, ColorSpace colorSpace, int bitDepth) { return doCreate(width, height, colorSpace, bitDepth, null); } public static Picture createCropped(int width, int height, ColorSpace colorSpace, Rect crop) { return doCreate(width, height, colorSpace, 8, crop); } public static Picture doCreate(int width, int height, ColorSpace colorSpace, int bitDepth, Rect crop) { int[] planeSizes = new int[MAX_PLANES]; for (int i = 0; i < colorSpace.nComp; i++) { planeSizes[colorSpace.compPlane[i]] += (width >> colorSpace.compWidth[i]) * (height >> colorSpace.compHeight[i]); } int nPlanes = 0; for (int i = 0; i < MAX_PLANES; i++) nPlanes += planeSizes[i] != 0 ? 1 : 0; int[][] data = new int[nPlanes][]; for (int i = 0, plane = 0; i < MAX_PLANES; i++) { if (planeSizes[i] != 0) { data[plane++] = new int[planeSizes[i]]; } } return new Picture(width, height, data, colorSpace, 8, crop); } public int getWidth() { return width; } public int getHeight() { return height; } public int[] getPlaneData(int plane) { return data[plane]; } public ColorSpace getColor() { return color; } public int[][] getData() { return data; } public int getBitDepth() { return bitDepth; } public Rect getCrop() { return crop; } public int getPlaneWidth(int plane) { return width >> color.compWidth[plane]; } public int getPlaneHeight(int plane) { return height >> color.compHeight[plane]; } public boolean compatible(Picture src) { return src.color == color && src.width == width && src.height == height && src.bitDepth == bitDepth; } public Picture createCompatible() { return Picture.create(width, height, color); } public void copyFrom(Picture src) { if (!compatible(src)) throw new IllegalArgumentException("Can not copy to incompatible picture"); for (int plane = 0; plane < color.nComp; plane++) { if (data[plane] == null) continue; arraycopy(src.data[plane], 0, data[plane], 0, (width >> color.compWidth[plane]) * (height >> color.compHeight[plane])); } } public Picture cropped() { if (crop == null || (crop.getX() == 0 && crop.getY() == 0 && crop.getWidth() == width && crop.getHeight() == height)) return this; Picture result = Picture.createWithDepth(crop.getWidth(), crop.getHeight(), color, bitDepth); for (int plane = 0; plane < color.nComp; plane++) { if (data[plane] == null) continue; cropSub(data[plane], crop.getX() >> color.compWidth[plane], crop.getY() >> color.compHeight[plane], crop.getWidth() >> color.compWidth[plane], crop.getHeight() >> color.compHeight[plane], width >> color.compWidth[plane], result.data[plane]); } return result; } private void cropSub(int[] src, int x, int y, int w, int h, int srcStride, int[] tgt) { int srcOff = y * srcStride + x, dstOff = 0; for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) tgt[dstOff + j] = src[srcOff + j]; srcOff += srcStride; dstOff += w; } } public void setCrop(Rect crop) { this.crop = crop; } public int getCroppedWidth() { return crop == null ? width : crop.getWidth(); } public int getCroppedHeight() { return crop == null ? height : crop.getHeight(); } public void setBitDepth(int bitDepth) { this.bitDepth = bitDepth; } @Override public boolean equals(Object obj) { if (obj == null || !(obj instanceof Picture)) return false; Picture other = (Picture) obj; if (other.getCroppedWidth() != getCroppedWidth() || other.getCroppedHeight() != getCroppedHeight() || other.getColor() != color) return false; for (int i = 0; i < getData().length; i++) if (!planeEquals(other, i)) return false; return true; } private boolean planeEquals(Picture other, int plane) { int cw = color.compWidth[plane]; int ch = color.compHeight[plane]; int offA = other.getCrop() == null ? 0 : ((other.getCrop().getX() >> cw) + (other.getCrop().getY() >> ch) * (other.getWidth() >> cw)); int offB = crop == null ? 0 : ((crop.getX() >> cw) + (crop.getY() >> ch) * (width >> cw)); int[] planeData = other.getPlaneData(plane); for (int i = 0; i < getCroppedHeight() >> ch; i++, offA += (other.getWidth() >> cw), offB += (width >> cw)) { for (int j = 0; j < getCroppedWidth() >> cw; j++) { if (planeData[offA + j] != data[plane][offB + j]) return false; } } return true; } }