I am currently trying to draw just a section of a BufferedImage that is within the bounds of a Rectangle on the fly. The image gets moved, and thus the size of the image in the rectangle changes.
Visual depiction:
Currently, this is what I have and it works great with a low res image. But if I scale the minimap up, this becomes very inefficient and causes lag
private BufferedImage extractPixels() {
int[] imagePixels = new int[scaledImage.getWidth() * scaledImage.getHeight()];
scaledImage.getRGB(0, 0, scaledImage.getWidth(), scaledImage.getHeight(), imagePixels,
0, scaledImage.getWidth());
int maxX = 0, maxY = 0;
boolean first = false;
for (int y = 0; y < scaledImage.getHeight(); y++) {
for (int x = 0; x < scaledImage.getWidth(); x++) {
int px = (int)(this.x + x);
int py = (int)(this.y + y);
if (viewingArea.contains(px, py)) {
if (x > maxX) maxX = x;
if (y > maxY) maxY = y;
if (!first) {
imageX = x;
imageY = y;
first = true;
}
}
}
}
int xCount = maxX - imageX;
int yCount = maxY - imageY;
if (imageX < 0 || imageX > scaledImage.getWidth() || imageX + xCount > scaledImage.getWidth()) return null;
if (imageY < 0 || imageY > scaledImage.getHeight() || imageY + yCount > scaledImage.getHeight()) return null;
return scaledImage.getSubimage(imageX, imageY, xCount, yCount);
}
In Render loop:
public void Render(PixelRenderer renderer) {
BufferedImage image = extractPixels();
if (image != null) renderer.renderImage(image, x + imageX, y + imageY);
}
Is there a way to do this more efficiently, so that re-scaling has less of an effect on performance?
Fixed by calculating where the image should subimage from, and the size of the subimage dependent on the position of the main image.
private BufferedImage extractPixels() {
double xp = viewingArea.x - this.x;
double yp = viewingArea.y - this.y;
double iw = viewingArea.width;
double ih = viewingArea.height;
int rightBound = scaledImage.getWidth() - viewingArea.width;
int bottomBound = scaledImage.getHeight() - viewingArea.height;
if (xp < 0) {
xp = 0;
iw = viewingArea.width - (this.x - viewingArea.x);
imageX = viewingArea.x + (viewingArea.width - (int)iw);
} else if (xp >= 0 && xp < rightBound) {
xp -= dx;
iw -= dx;
imageX = viewingArea.x;
}
if (xp >= rightBound) {
iw = viewingArea.width - ((int)xp - (scaledImage.getWidth() - viewingArea.width));
imageX = viewingArea.x;
}
if (yp < 0) {
yp = 0;
ih = viewingArea.height - (this.y - viewingArea.y);
imageY = viewingArea.x + (viewingArea.height - (int)ih);
} else if (yp >= 0 && yp < bottomBound) {
yp -= dy;
ih -= dy;
imageY = viewingArea.y;
}
if (yp >= bottomBound) {
ih = viewingArea.height - ((int)yp - (scaledImage.getHeight() - viewingArea.height));
imageY = viewingArea.y;
}
if (iw < 0) iw = Math.abs(iw);
if (ih < 0) ih = Math.abs(ih);
if (xp < 0) xp = Math.abs(xp);
if (yp < 0) yp = Math.abs(yp);
BufferedImage result = new BufferedImage((int)iw, (int)ih, BufferedImage.TYPE_INT_RGB);
try {
result = scaledImage.getSubimage((int)xp, (int)yp, (int)iw, (int)ih);
} catch (Exception e) {
//TODO: Log to game engine something bad has happened
e.printStackTrace();
}
return result;
}
Related
I am doing my program using jfeaturelib for searching glcm features. I am using this haralick.java and already run my program perfectly using this demo HaralickDemo.java. All I want to know is how to use horizontal neigbhor 0 degree only or 90 degree only. This is the code:
private void calculate() {
calculateGreyValues();
final int imageWidth = image.getWidth();
final int imageHeight = image.getHeight();
final int d = HARALICK_DIST;
int i, j, pos;
// image is not empty per default
for (int y = 0; y < imageHeight; y++) {
for (int x = 0; x < imageWidth; x++) {
pos = imageWidth * y + x;
// horizontal neighbor: 0 degrees
i = x - d;
// j = y;
if (!(i < 0)) {
increment(grayValue[pos], grayValue[pos - d]);
}
// vertical neighbor: 90 degree
// i = x;
j = y - d;
if (!(j < 0)) {
increment(grayValue[pos], grayValue[pos - d * imageWidth]);
}
// 45 degree diagonal neigbor
i = x + d;
j = y - d;
if (i < imageWidth && !(j < 0)) {
increment(grayValue[pos], grayValue[pos + d - d * imageWidth]);
}
// 135 vertical neighbor
i = x - d;
j = y - d;
if (!(i < 0) && !(j < 0)) {
increment(grayValue[pos], grayValue[pos - d - d * imageWidth]);
}
}
}
And can you explain me detail of this haralick.java program?
I am trying to make a processing program, but if I use P2D, P3D, or OPENGL mode I get an error:
com.sun.jdi.VMDisconnectedException
at com.sun.tools.jdi.TargetVM.waitForReply(TargetVM.java:285)
at com.sun.tools.jdi.VirtualMachineImpl.waitForTargetReply(VirtualMachineImpl.java:1015)
at com.sun.tools.jdi.PacketStream.waitForReply(PacketStream.java:51)
at com.sun.tools.jdi.JDWP$ObjectReference$InvokeMethod.waitForReply(JDWP.java:4589)
at com.sun.tools.jdi.ObjectReferenceImpl.invokeMethod(ObjectReferenceImpl.java:374)
at processing.mode.java.runner.Runner.findException(Runner.java:701)
at processing.mode.java.runner.Runner.reportException(Runner.java:652)
at processing.mode.java.runner.Runner.exception(Runner.java:595)
at processing.mode.java.runner.EventThread.exceptionEvent(EventThread.java:367)
at processing.mode.java.runner.EventThread.handleEvent(EventThread.java:255)
at processing.mode.java.runner.EventThread.run(EventThread.java:89)
the error message itself varies between P2D and P3D, but they both get a no framebuffer objects available error. I am using processing 2.0b7, please help and let me know if you need more info.
Note: I don't know if this is a separate issue or not, but I am also getting GLSL shader errors to.
Now, here is my code:
Cell[][] Cells = new Cell[50][50];
byte Direction = 1;
byte Times = 1;
int oldwidth = 500;
int oldheight = 500;
void setup() {
size(oldwidth, oldheight, OPENGL);
background(255);
colorMode(HSB,250);
for (int x = 0; x < 50; x++) {
for (int y = 0; y < 50; y++) {
Cells[x][y] = new Cell(x * 5, y * 5, 255, x * (width / 50), y * (height / 50), width / 50, height / 50);
}
}
}
void draw() {
for (int x = 0; x < 50; x++) {
for (int y = 0; y < 50; y++) {
if (width == oldwidth) Cells[x][y].Width = width / 50;
if (height == oldheight) Cells[x][y].Height = height / 50;
if (Direction == 1){
Cells[x][y].Hue += 5;
if (Cells[x][y].Hue > 250) Cells[x][y].Hue -= 250;
}
if (Direction == 2){
Cells[x][y].Saturation -= 5;
if (Cells[x][y].Saturation < 0) Cells[x][y].Saturation += 500;
}
if (Direction == 3){
Cells[x][y].Hue -= 5;
if (Cells[x][y].Hue < 0) Cells[x][y].Hue += 250;
}
if (Direction == 4){
Cells[x][y].Saturation += 5;
if (Cells[x][y].Saturation > 500) Cells[x][y].Saturation -= 500;
}
Cells[x][y].Draw();
}
}
if (Times == 50){
Times = 1;
if (Direction == 4) Direction = 1; else Direction += 1;
} else Times += 1;
delay(10);
}
class Cell {
int X;
int Y;
int Width;
int Height;
float Hue;
float Saturation;
float Brightness;
Cell(color parC, int parX, int parY, int parWidth, int parHeight) {
Hue = hue(parC);
Saturation = saturation(parC);
Brightness = brightness(parC);
X = parX;
Y = parY;
Width = parWidth;
Height = parHeight;
}
Cell(float parHue, float parSaturation, float parBrightness, int parX, int parY, int parWidth, int parHeight) {
Hue = parHue;
Saturation = parSaturation;
Brightness = parBrightness;
X = parX;
Y = parY;
Width = parWidth;
Height = parHeight;
}
void Draw() {
if (Saturation > 250) if (Saturation > 500) stroke(color(Hue,0,Brightness)); else stroke(color(Hue,Saturation - (Saturation - 250) * 2,Brightness)); else stroke(color(Hue,Saturation,Brightness));
if (Saturation > 250) if (Saturation > 500) fill(color(Hue,0,Brightness)); else fill(color(Hue,Saturation - (Saturation - 250) * 2,Brightness)); else fill(color(Hue,Saturation,Brightness));
rect(X, Y, Width, Height);
}
}
I just realized that it is just that my graphics card does not support OPENGL 2.0
I have a set of bitmaps. They are all transparent to some extent, and I don't know in advance which parts are transparent. I would like to create a new bitmap out of the original bitmap that excludes the transparent parts, but in a square. I think this image explains it:
I know how to create a bitmap out of a existing bitmap, but I don't know how to find out which part is transparent and how to use that to achieve my goal.
This is how I plan on doing this:
public Bitmap cutImage(Bitmap image) {
Bitmap newBitmap = null;
int width = image.getWidth();
int height = image.getHeight();
newBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(newBitmap);
//This is where I need to find out correct values of r1 and r1.
Rect r1 = new Rect(?, ?, ?, ?);
Rect r2 = new Rect(?, ?, ?, ?);
canvas.drawBitmap(image, r1, r2, null);
return newBitmap;
}
Does anyone know how to achieve this?
EDIT:
I got it work using the following algorithm to find left, right, top and bottom values:
private int x1;
private int x2;
private int y1;
private int y2;
private void findRectValues(Bitmap image)
{
for(int x = 0; x < image.getWidth(); x++)
{
for(int y = 0; y < image.getHeight(); y++)
{
if(image.getPixel(x, y) != Color.TRANSPARENT)
{
System.out.println("X1 is: " + x);
x1 = x;
break;
}
}
if(x1 != 0)
break;
}
for(int x = image.getWidth()-1; x > 0; x--)
{
for(int y = 0; y < image.getHeight(); y++)
{
if(image.getPixel(x, y) != Color.TRANSPARENT)
{
System.out.println("X2 is: " + x);
x2 = x;
break;
}
}
if(x2 != 0)
break;
}
for(int y = 0; y < image.getHeight(); y++)
{
for(int x = 0; x < image.getWidth(); x++)
{
if(image.getPixel(x, y) != Color.TRANSPARENT)
{
System.out.println("Y1 is: " + y);
y1 = y;
break;
}
}
if(y1 != 0)
break;
}
for(int y = image.getHeight()-1; y > 0; y--)
{
for(int x = 0; x < image.getWidth(); x++)
{
if(image.getPixel(x, y) != Color.TRANSPARENT)
{
System.out.println("Y2 is: " + y);
y2 = y;
break;
}
}
if(y2 != 0)
break;
}
}
i think this is a bit more efficient and it works great for me
public Bitmap cropBitmapToBoundingBox(Bitmap picToCrop, int unusedSpaceColor) {
int[] pixels = new int[picToCrop.getHeight() * picToCrop.getWidth()];
int marginTop = 0, marginBottom = 0, marginLeft = 0, marginRight = 0, i;
picToCrop.getPixels(pixels, 0, picToCrop.getWidth(), 0, 0,
picToCrop.getWidth(), picToCrop.getHeight());
for (i = 0; i < pixels.length; i++) {
if (pixels[i] != unusedSpaceColor) {
marginTop = i / picToCrop.getWidth();
break;
}
}
outerLoop1: for (i = 0; i < picToCrop.getWidth(); i++) {
for (int j = i; j < pixels.length; j += picToCrop.getWidth()) {
if (pixels[j] != unusedSpaceColor) {
marginLeft = j % picToCrop.getWidth();
break outerLoop1;
}
}
}
for (i = pixels.length - 1; i >= 0; i--) {
if (pixels[i] != unusedSpaceColor) {
marginBottom = (pixels.length - i) / picToCrop.getWidth();
break;
}
}
outerLoop2: for (i = pixels.length - 1; i >= 0; i--) {
for (int j = i; j >= 0; j -= picToCrop.getWidth()) {
if (pixels[j] != unusedSpaceColor) {
marginRight = picToCrop.getWidth()
- (j % picToCrop.getWidth());
break outerLoop2;
}
}
}
return Bitmap.createBitmap(picToCrop, marginLeft, marginTop,
picToCrop.getWidth() - marginLeft - marginRight,
picToCrop.getHeight() - marginTop - marginBottom);
}
If all the images you want to crop are more or less in the center of the original canvas, I guess you could so something like this:
Start from each border working your way inwards the image searching for non-transparent pixels
Once you've found the top-left pixel and the right-bottom, you'll have your desired target.
Copy the image as you please
Now, the question remains is what you consider a transparent pixel. Does alpha trasparency counts? if so, how much alpha until you decide it's transparent enough to be cut from the image?
To find the non-transparent area of your bitmap, iterate across the bitmap in x and y and find the min and max of the non-transparent region. Then crop the bitmap to those co-ordinates.
Bitmap CropBitmapTransparency(Bitmap sourceBitmap)
{
int minX = sourceBitmap.getWidth();
int minY = sourceBitmap.getHeight();
int maxX = -1;
int maxY = -1;
for(int y = 0; y < sourceBitmap.getHeight(); y++)
{
for(int x = 0; x < sourceBitmap.getWidth(); x++)
{
int alpha = (sourceBitmap.getPixel(x, y) >> 24) & 255;
if(alpha > 0) // pixel is not 100% transparent
{
if(x < minX)
minX = x;
if(x > maxX)
maxX = x;
if(y < minY)
minY = y;
if(y > maxY)
maxY = y;
}
}
}
if((maxX < minX) || (maxY < minY))
return null; // Bitmap is entirely transparent
// crop bitmap to non-transparent area and return:
return Bitmap.createBitmap(sourceBitmap, minX, minY, (maxX - minX) + 1, (maxY - minY) + 1);
}
I'm trying to make a program that simulates the physics of fluids in Processing. In the IDE there's an included example:
/**
* Fluid
* by Glen Murphy.
*
* Click and drag the mouse to move the simulated fluid.
* Adjust the "res" variable below to change resolution.
* Code has not been optimised, and will run fairly slowly.
*/
int res = 2;
int penSize = 30;
int lwidth;
int lheight;
int pnum = 30000;
vsquare[][] v;
vbuffer[][] vbuf;
particle[] p = new particle[pnum];
int pcount = 0;
int mouseXvel = 0;
int mouseYvel = 0;
void setup()
{
size(200, 200);
noStroke();
frameRate(30);
lwidth = width/res;
lheight = height/res;
v = new vsquare[lwidth+1][lheight+1];
vbuf = new vbuffer[lwidth+1][lheight+1];
for (int i = 0; i < pnum; i++) {
p[i] = new particle(random(res,width-res),random(res,height-res));
}
for (int i = 0; i <= lwidth; i++) {
for (int u = 0; u <= lheight; u++) {
v[i][u] = new vsquare(i*res,u*res);
vbuf[i][u] = new vbuffer(i*res,u*res);
}
}
}
void draw()
{
background(#666666);
int axvel = mouseX-pmouseX;
int ayvel = mouseY-pmouseY;
mouseXvel = (axvel != mouseXvel) ? axvel : 0;
mouseYvel = (ayvel != mouseYvel) ? ayvel : 0;
for (int i = 0; i < lwidth; i++) {
for (int u = 0; u < lheight; u++) {
vbuf[i][u].updatebuf(i,u);
v[i][u].col = 32;
}
}
for (int i = 0; i < pnum-1; i++) {
p[i].updatepos();
}
for (int i = 0; i < lwidth; i++) {
for (int u = 0; u < lheight; u++) {
v[i][u].addbuffer(i, u);
v[i][u].updatevels(mouseXvel, mouseYvel);
v[i][u].display(i, u);
}
}
}
class particle {
float x;
float y;
float xvel;
float yvel;
int pos;
particle(float xIn, float yIn) {
x = xIn;
y = yIn;
}
void updatepos() {
float col1;
if (x > 0 && x < width && y > 0 && y < height) {
int vi = (int)(x/res);
int vu = (int)(y/res);
vsquare o = v[vi][vu];
float ax = (x%res)/res;
float ay = (y%res)/res;
xvel += (1-ax)*v[vi][vu].xvel*0.05;
yvel += (1-ay)*v[vi][vu].yvel*0.05;
xvel += ax*v[vi+1][vu].xvel*0.05;
yvel += ax*v[vi+1][vu].yvel*0.05;
xvel += ay*v[vi][vu+1].xvel*0.05;
yvel += ay*v[vi][vu+1].yvel*0.05;
o.col += 4;
x += xvel;
y += yvel;
}
else {
x = random(0,width);
y = random(0,height);
xvel = 0;
yvel = 0;
}
xvel *= 0.5;
yvel *= 0.5;
}
}
class vbuffer {
int x;
int y;
float xvel;
float yvel;
float pressurex = 0;
float pressurey = 0;
float pressure = 0;
vbuffer(int xIn,int yIn) {
x = xIn;
y = yIn;
pressurex = 0;
pressurey = 0;
}
void updatebuf(int i, int u) {
if (i>0 && i<lwidth && u>0 && u<lheight) {
pressurex = (v[i-1][u-1].xvel*0.5 + v[i-1][u].xvel + v[i-1][u+1].xvel*0.5 - v[i+1][u-1].xvel*0.5 - v[i+1][u].xvel - v[i+1][u+1].xvel*0.5);
pressurey = (v[i-1][u-1].yvel*0.5 + v[i][u-1].yvel + v[i+1][u-1].yvel*0.5 - v[i-1][u+1].yvel*0.5 - v[i][u+1].yvel - v[i+1][u+1].yvel*0.5);
pressure = (pressurex + pressurey)*0.25;
}
}
}
class vsquare {
int x;
int y;
float xvel;
float yvel;
float col;
vsquare(int xIn,int yIn) {
x = xIn;
y = yIn;
}
void addbuffer(int i, int u) {
if (i>0 && i<lwidth && u>0 && u<lheight) {
xvel += (vbuf[i-1][u-1].pressure*0.5
+vbuf[i-1][u].pressure
+vbuf[i-1][u+1].pressure*0.5
-vbuf[i+1][u-1].pressure*0.5
-vbuf[i+1][u].pressure
-vbuf[i+1][u+1].pressure*0.5
)*0.25;
yvel += (vbuf[i-1][u-1].pressure*0.5
+vbuf[i][u-1].pressure
+vbuf[i+1][u-1].pressure*0.5
-vbuf[i-1][u+1].pressure*0.5
-vbuf[i][u+1].pressure
-vbuf[i+1][u+1].pressure*0.5
)*0.25;
}
}
void updatevels(int mvelX, int mvelY) {
if (mousePressed) {
float adj = x - mouseX;
float opp = y - mouseY;
float dist = sqrt(opp*opp + adj*adj);
if (dist < penSize) {
if (dist < 4) dist = penSize;
float mod = penSize/dist;
xvel += mvelX*mod;
yvel += mvelY*mod;
}
}
xvel *= 0.99;
yvel *= 0.99;
}
void display(int i, int u) {
float tcol = 0;
if (col > 255) col = 255;
if (i>0 && i<lwidth-1 && u>0 && u<lheight-1) {
tcol = (+ v[i][u+1].col
+ v[i+1][u].col
+ v[i+1][u+1].col*0.5
)*0.4;
tcol = (int)(tcol+col*0.5);
}
else {
tcol = (int)col;
}
fill(tcol, tcol, tcol);
rect(x,y,res,res);
}
}
It's not really commented and I'm somewhat new to programming, so I have no idea where to start as far as understanding it. Is there any good reading on fluid physics? I'm more interesting in the visual effect than the accuracy of the simulation.
A good starting point could be the paper Stable Fluids, it will show you the math behind the fluid simulation, and in the third chapter it describe the implementation of a fluid solver. There is also an open source implementation available in sourceforge (you will need to checkout the source with cvs).
I am trying to make a bounding box over the blue-colored pixels (from Kinect v1 camera, using Processing). Y-axis of bounding box works perfectly but x-axis is very off.
void display() {
PImage img = kinect.getDepthImage();
float maxValue = 0;
float minValue = kinect.width*kinect.height ;
float maxValueX = 0;
float maxValueY = 0;
float minValueX = kinect.width;
float minValueY = kinect.height;
// Being overly cautious here
if (depth == null || img == null) return;
display.loadPixels();
for (int x = 0; x < kinect.width; x++) { //goes through all the window
for (int y = 0; y < kinect.height; y++) {
int offset = x + y * kinect.width;
// Raw depth
int rawDepth = depth[offset];
int pix = x + y * display.width; //why is it y*width
if (rawDepth < threshold) {
// A blue color instead
display.pixels[pix] = color(0, 0, 255); //set correct pixels to blue
if(pix > maxValue){
maxValue = pix;
maxValueX = x;
maxValueY = y;
}
if(pix < minValue){
minValue = pix;
minValueX = x;
minValueY = y;
}
} else {
display.pixels[pix] = img.pixels[offset];
}
}
}
display.updatePixels();
image(display, 0, 0);
rect(minValueX, minValueY, maxValueX-minValueX, maxValueY-minValueY);
}
You have to calculate the minimum and maximum values for each index or coordinate separately. Use the min respectively max function for this:
maxValue = max(maxValue, pix);
minValue = min(minValue, pix);
maxValueX = max(maxValueX, x);
minValueX = min(minValueX, x);
maxValueY = max(maxValueY, y);
minValueY = min(minValueY, y);
or with an ifstatement:
if (pix > maxValue) { maxValue = pix; }
if (pix < minValue) { minValue = pix; }
if (x > maxValueX) { maxValueX = x; }
if (x < minValueX) { minValueX = x; }
if (y > maxValueY) { maxValueY = y; }
if (y < minValueY) { minValueY = y; }