mirror of https://github.com/apache/cloudstack.git
153 lines
5.6 KiB
Java
153 lines
5.6 KiB
Java
// Licensed to the Apache Software Foundation (ASF) under one
|
|
// or more contributor license agreements. See the NOTICE file
|
|
// distributed with this work for additional information
|
|
// regarding copyright ownership. The ASF licenses this file
|
|
// to you 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 common;
|
|
|
|
import java.awt.image.BufferedImage;
|
|
import java.awt.image.DataBuffer;
|
|
import java.awt.image.DataBufferInt;
|
|
import java.util.Arrays;
|
|
|
|
import org.apache.log4j.Logger;
|
|
|
|
import streamer.BaseElement;
|
|
import streamer.ByteBuffer;
|
|
import streamer.Element;
|
|
import streamer.Link;
|
|
|
|
public class BufferedImagePixelsAdapter extends BaseElement {
|
|
private static final Logger s_logger = Logger.getLogger(BufferedImagePixelsAdapter.class);
|
|
|
|
public static final String TARGET_X = "x";
|
|
public static final String TARGET_Y = "y";
|
|
public static final String WIDTH = "width";
|
|
public static final String HEIGHT = "height";
|
|
public static final String RGB888LE32 = "RGB888LE32";
|
|
public static final String PIXEL_FORMAT = "pixel_format";
|
|
|
|
protected BufferedImageCanvas canvas;
|
|
|
|
public BufferedImagePixelsAdapter(String id, BufferedImageCanvas canvas) {
|
|
super(id);
|
|
this.canvas = canvas;
|
|
declarePads();
|
|
}
|
|
|
|
private void declarePads() {
|
|
inputPads.put(STDIN, null);
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return "Renderer(" + id + ")";
|
|
}
|
|
|
|
@Override
|
|
public void handleData(ByteBuffer buf, Link link) {
|
|
if (verbose)
|
|
s_logger.debug("[" + this + "] INFO: Data received: " + buf + ".");
|
|
|
|
int x = (Integer)buf.getMetadata(TARGET_X);
|
|
int y = (Integer)buf.getMetadata(TARGET_Y);
|
|
int rectWidth = (Integer)buf.getMetadata(WIDTH);
|
|
int rectHeight = (Integer)buf.getMetadata(HEIGHT);
|
|
String format = (String)buf.getMetadata(PIXEL_FORMAT);
|
|
|
|
int bpp;
|
|
// Support RGB888/32 little endian only
|
|
if (format != null && RGB888LE32.equals(format)) {
|
|
bpp = 4;
|
|
// TODO: support more formats
|
|
} else
|
|
throw new RuntimeException("Unsupported format: " + format + ". Supported formats: " + RGB888LE32 + ".");
|
|
|
|
int dataLength = rectWidth * rectHeight * bpp;
|
|
if (!cap(buf, dataLength, dataLength, link, false))
|
|
return;
|
|
|
|
// Draw rectangle on offline buffer
|
|
BufferedImage image = canvas.getOfflineImage();
|
|
|
|
DataBuffer dataBuf = image.getRaster().getDataBuffer();
|
|
|
|
switch (dataBuf.getDataType()) {
|
|
|
|
case DataBuffer.TYPE_INT: {
|
|
|
|
// Convert array of bytes to array of int's
|
|
int[] intArray = buf.toIntLEArray();
|
|
|
|
// We chose RGB888 model, so Raster will use DataBufferInt type
|
|
DataBufferInt dataBuffer = (DataBufferInt)dataBuf;
|
|
|
|
int imageWidth = image.getWidth();
|
|
int imageHeight = image.getHeight();
|
|
|
|
// Paint rectangle directly on buffer, line by line
|
|
int[] imageBuffer = dataBuffer.getData();
|
|
|
|
for (int srcLine = 0, dstLine = y; srcLine < rectHeight && dstLine < imageHeight; srcLine++, dstLine++) {
|
|
try {
|
|
System.arraycopy(intArray, srcLine * rectWidth, imageBuffer, x + dstLine * imageWidth, rectWidth);
|
|
} catch (IndexOutOfBoundsException e) {
|
|
s_logger.info("[ignored] copy error",e);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
throw new RuntimeException("Unsupported data buffer in buffered image: expected data buffer of type int (DataBufferInt). Actual data buffer type: "
|
|
+ dataBuf.getClass().getSimpleName());
|
|
}
|
|
|
|
// Request update of repainted area
|
|
canvas.repaint(x, y, rectWidth, rectHeight);
|
|
|
|
buf.unref();
|
|
}
|
|
|
|
public static void main(String args[]) {
|
|
System.setProperty("streamer.Element.debug", "true");
|
|
|
|
BufferedImageCanvas canvas = new BufferedImageCanvas(4, 4);
|
|
|
|
Element renderer = new BufferedImagePixelsAdapter("renderer", canvas);
|
|
|
|
byte[] pixels = new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5,
|
|
6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
|
|
|
|
int[] pixelsLE = new int[] {0x04030201, 0x08070605, 0x0c0b0a09, 0x100f0e0d, 0x04030201, 0x08070605, 0x0c0b0a09, 0x100f0e0d, 0x04030201, 0x08070605,
|
|
0x0c0b0a09, 0x100f0e0d, 0x04030201, 0x08070605, 0x0c0b0a09, 0x100f0e0d};
|
|
|
|
ByteBuffer buf = new ByteBuffer(pixels);
|
|
buf.putMetadata(TARGET_X, 0);
|
|
buf.putMetadata(TARGET_Y, 0);
|
|
buf.putMetadata(WIDTH, 4);
|
|
buf.putMetadata(HEIGHT, 4);
|
|
buf.putMetadata(PIXEL_FORMAT, RGB888LE32);
|
|
|
|
renderer.handleData(buf, null);
|
|
|
|
String actualData = Arrays.toString(((DataBufferInt)canvas.getOfflineImage().getRaster().getDataBuffer()).getData());
|
|
String expectedData = Arrays.toString(pixelsLE);
|
|
if (!actualData.equals(expectedData))
|
|
s_logger.error("Actual image: " + actualData + "\nExpected image: " + expectedData + ".");
|
|
|
|
}
|
|
|
|
}
|