/* * @(#)RotationEffect.java 1.3 01/04/27 * * Copyright (c) 1999-2001 Sun Microsystems, Inc. All Rights Reserved. * * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use, * modify and redistribute this software in source and binary code form, * provided that i) this copyright notice and license appear on all copies of * the software; and ii) Licensee does not utilize the software in a manner * which is disparaging to Sun. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * This software is not designed or intended for use in on-line control of * aircraft, air traffic, aircraft navigation or aircraft communications; or in * the design, construction, operation or maintenance of any nuclear * facility. Licensee represents and warrants that it will not use or * redistribute the Software for such purposes. */ package de.fhkoeln.jmfsamples; import java.awt.Dimension; import javax.media.Buffer; import javax.media.Effect; import javax.media.Format; import javax.media.format.RGBFormat; import javax.media.format.VideoFormat; public class RotationEffect implements Effect { Format inputFormat; Format outputFormat; Format[] inputFormats; Format[] outputFormats; double angle = 0.0; double[] sinTable; double[] cosTable; double[] rateTable; private int count = 0; private int num; public RotationEffect() { this(20); } public RotationEffect(int num) { if (num <= 0) this.num = 20; else this.num = num; this.angle = 2.0 * 3.1415926 / this.num; buildTable(); inputFormats = new Format[] { new RGBFormat(null, Format.NOT_SPECIFIED, Format.byteArray, Format.NOT_SPECIFIED, 24, 3, 2, 1, 3, Format.NOT_SPECIFIED, Format.TRUE, Format.NOT_SPECIFIED), new VideoFormat(VideoFormat.MPEG, null, Format.NOT_SPECIFIED, Format.byteArray, Format.NOT_SPECIFIED) }; outputFormats = new Format[] { new RGBFormat(null, Format.NOT_SPECIFIED, Format.byteArray, Format.NOT_SPECIFIED, 24, 3, 2, 1, 3, Format.NOT_SPECIFIED, Format.TRUE, Format.NOT_SPECIFIED), new VideoFormat(VideoFormat.MPEG, null, Format.NOT_SPECIFIED, Format.byteArray, Format.NOT_SPECIFIED) }; } // methods for interface Codec public Format[] getSupportedInputFormats() { return inputFormats; } public Format[] getSupportedOutputFormats(Format input) { if (input == null) { return outputFormats; } if (matches(input, inputFormats) != null) { return new Format[] { outputFormats[0].intersects(input) }; } else { return new Format[0]; } } public Format setInputFormat(Format input) { inputFormat = input; return input; } public Format setOutputFormat(Format output) { if (output == null || matches(output, outputFormats) == null) return null; RGBFormat incoming = (RGBFormat) output; Dimension size = incoming.getSize(); int maxDataLength = incoming.getMaxDataLength(); int lineStride = incoming.getLineStride(); float frameRate = incoming.getFrameRate(); int flipped = incoming.getFlipped(); int endian = incoming.getEndian(); if (size == null) return null; if (maxDataLength < size.width * size.height * 3) maxDataLength = size.width * size.height * 3; if (lineStride < size.width * 3) lineStride = size.width * 3; if (flipped != Format.FALSE) flipped = Format.FALSE; outputFormat = outputFormats[0] .intersects(new RGBFormat(size, maxDataLength, null, frameRate, Format.NOT_SPECIFIED, Format.NOT_SPECIFIED, Format.NOT_SPECIFIED, Format.NOT_SPECIFIED, Format.NOT_SPECIFIED, lineStride, Format.NOT_SPECIFIED, Format.NOT_SPECIFIED)); // .intersects(VideoFormat(incoming.getEncoding(), incoming.getSize(), // incoming.getMaxDataLength(), incoming.getDataType(), frameRate)); // System.out.println("final outputformat = " + outputFormat); return outputFormat; } public int process(Buffer inBuffer, Buffer outBuffer) { int outputDataLength = ((VideoFormat) outputFormat).getMaxDataLength(); validateByteArraySize(outBuffer, outputDataLength); outBuffer.setLength(outputDataLength); outBuffer.setFormat(outputFormat); outBuffer.setFlags(inBuffer.getFlags()); byte[] inData = (byte[]) inBuffer.getData(); byte[] outData = (byte[]) outBuffer.getData(); RGBFormat vfIn = (RGBFormat) inBuffer.getFormat(); Dimension sizeIn = vfIn.getSize(); int pixStrideIn = vfIn.getPixelStride(); int lineStrideIn = vfIn.getLineStride(); int iw = sizeIn.width; int ih = sizeIn.height; int cx = iw / 2; int cy = ih / 2; int ip = 0; int op = 0; int x, y; double vsin, vcos, ratio; if (outData.length < iw * ih * 3) { System.out.println("the buffer is not full"); return BUFFER_PROCESSED_FAILED; } // System.out.println("count = " + count); vsin = sinTable[count]; vcos = cosTable[count]; ratio = 1.0;// rateTable[count]; // System.out.println("vsin = " + vsin + " vcos = " + vcos); for (int j = -cy; j < ih - cy; j++) for (int i = -cx; i < iw - cx; i++) { x = (int) ((vcos * i - vsin * j) * ratio + cx + 0.5); y = (int) ((vsin * i + vcos * j) * ratio + cy + 0.5); if (x < 0 || x >= iw || y < 0 || y >= ih) { outData[op++] = 0; outData[op++] = 0; outData[op++] = 0; } else { ip = lineStrideIn * y + x * pixStrideIn; outData[op++] = inData[ip++]; outData[op++] = inData[ip++]; outData[op++] = inData[ip++]; } } count++; if (count >= num) count = 0; return BUFFER_PROCESSED_OK; } // methods for interface PlugIn public String getName() { return "Rotation Effect"; } public void open() {} public void close() {} public void reset() {} // methods for interface javax.media.Controls public Object getControl(String controlType) { return null; } public Object[] getControls() { return null; } // Utility methods. Format matches(Format in, Format outs[]) { for (int i = 0; i < outs.length; i++) { if (in.matches(outs[i])) return outs[i]; } return null; } byte[] validateByteArraySize(Buffer buffer, int newSize) { Object objectArray = buffer.getData(); byte[] typedArray; if (objectArray instanceof byte[]) { // is correct type AND not // null typedArray = (byte[]) objectArray; if (typedArray.length >= newSize) { // is sufficient capacity return typedArray; } byte[] tempArray = new byte[newSize]; // re-alloc array System.arraycopy(typedArray, 0, tempArray, 0, typedArray.length); typedArray = tempArray; } else { typedArray = new byte[newSize]; } buffer.setData(typedArray); return typedArray; } private void buildTable() { double aa; sinTable = new double[num]; cosTable = new double[num]; rateTable = new double[num]; for (int i = 0; i < num; i++) rateTable[i] = 1.0; for (int i = 0; i < num; i++) { aa = i * angle; sinTable[i] = Math.sin(aa); cosTable[i] = Math.cos(aa); } for (int i = 0; i < num / 2; i++) rateTable[i] = (1.0 + 0.15 * i); for (int i = num - 1; i >= num / 2; i--) rateTable[i] = (1.0 + 0.15 * (num - 1 - i)); } }