looping through bitmap into array - java

is it possible to loop through bitmap and set each color value to an array? at the moment only top row of array is getting written to dst bitmap. eg
.
Bitmap dst = Bitmap.createBitmap(width, height,input.getConfig() ); //output pic
int origPixel = 0;
int []arr = new int[input.getWidth()*input.getHeight()];
int color = 0;
for(int j=0;j<dst.getHeight();j++){
for(int i=0;i<dst.getWidth();i++){
origPixel= input.getPixel(i,j);
color = ........do something special with that pixel transform it whatever
if( Math.pow(i - centerX, 2) + ( Math.pow(j - centerY, 2) ) <= 22500 ){
arr[i]=color;
}else{
arr[i]=origPixel;
}
}
}
Bitmap dst2 = Bitmap.createBitmap(arr,width,height,input.getConfig());
return dst2;

you need to update arr[k] where k initialize before first loop and increment in the second loop see the modified code a hunk of your code:
int k =0;
for(int j=0;j<dst.getHeight();j++){
for(int i=0;i<dst.getWidth();i++, k++){
origPixel= input.getPixel(i,j);
color = ........do something special with that pixel transform it whatever
if( Math.pow(i - centerX, 2) + ( Math.pow(j - centerY, 2) ) <= 22500 ){
arr[k]=color;
}else{
arr[k]=origPixel;
}
you are overriding values in array.

Related

Detecting when a PNG image has been "wiped transparent" in Processing?

i'm trying to create a game using Kinect where you have to use your hand movements to wipe away an image to make it disappear revealing another image beneath it within 30 seconds. Now I have already done the code for the loosing condition where if you do not wipe away the image under 30 seconds, the loosing screen will pop up.
However, I am not sure how to code the part to detect when the entire PNG image has been "wiped away". Does this involve using get()? I am not sure how to approach this.
Imagine there are 2 Pimages moondirt.png and moonsurface.png
The Kinect controls the wiping and making Pimage moondirt.png transparent to reveal moonsurface.png
void kinect() {
//----------draw kinect------------
// Draw moon surface
image(moonSurface, 0, 0, width, height);
// Draw the moon dirt
image(moonDirt, 0, 0, width, height);
// Threshold the depth image
int[] rawDepth = kinect.getRawDepth();
for (int i=0; i < rawDepth.length; i++) {
if (rawDepth[i] >= minDepth && rawDepth[i] <= maxDepth) {
depthImg.pixels[i] = color(255);
maskingImg.pixels[i] = color(255);
} else {
depthImg.pixels[i] = color(0);
}
}
//moonDirt.resize(640, 480); //(640, 480);
moonDirt.loadPixels();
for (int i=0; i < rawDepth.length; i++) {
if ( maskingImg.pixels[i] == color(255) ) {
moonDirt.pixels[i] = color( 0, 0, 0, 0 );
}
}
moonDirt.updatePixels();
image(moonDirt, 0, 0, width, height);
color c = moonDirt.get(width, height);
updatePixels();
//--------timer-----
if (countDownTimer.complete() == true){
if (timeLeft > 1 ) {
timeLeft--;
countDownTimer.start();
} else {
state = 4;
redraw();
}
}
//show countDown TIMER
String s = "Time Left: " + timeLeft;
textAlign(CENTER);
textSize(30);
fill(255,0,0);
text(s, 380, 320);
}
//timer
class Timer {
int startTime;
int interval;
Timer(int timeInterval) {
interval = timeInterval;
}
void start() {
startTime = millis();
}
boolean complete() {
int elapsedTime = millis() - startTime;
if (elapsedTime > interval) {
return true;
}else {
return false;
}
}
}
I see the confusion in this section:
moonDirt.loadPixels();
for (int i=0; i < rawDepth.length; i++) {
if ( maskingImg.pixels[i] == color(255) ) {
moonDirt.pixels[i] = color( 0, 0, 0, 0 );
}
}
moonDirt.updatePixels();
image(moonDirt, 0, 0, width, height);
color c = moonDirt.get(width, height);
You are already using pixels[] which is more efficient than get() which is great.
Don't forget to call updatePixels() when you're done. You already do that for moonDirt, but not for maskingImg
If you want to find out if an image has been cleared (where clear means transparent black (color(0,0,0,0)) in this case).
It looks like you're already familiar with functions that take parameters and return values. The count function will need to:
take 2 arguments: the image to process and the colour to check and count
return the total count
iterate through all pixels: if any pixels match the 2nd argument, the total count increments
Something like this:
/**
* countPixels - counts pixels of of a certain colour within an image
* #param image - the PImage to loop through
* #param colorToCount - the colour to count pixels present in the image
* return int - the number of found pixels (between 0 and image.pixels.length)
*/
int countPixels(PImage image,color colorToCount){
// initial transparent black pixel count
int count = 0;
// make pixels[] available
image.loadPixels();
// for each pixel
for(int i = 0 ; i < image.pixels.length; i++){
// check if it's transparent black
if(image.pixels[i] == colorToCount){
// if so, increment the counter
count++;
}
}
// finally return the count
return count;
}
Within your code you could use it like so:
...
// Threshold the depth image
int[] rawDepth = kinect.getRawDepth();
for (int i=0; i < rawDepth.length; i++) {
if (rawDepth[i] >= minDepth && rawDepth[i] <= maxDepth) {
depthImg.pixels[i] = color(255);
maskingImg.pixels[i] = color(255);
} else {
depthImg.pixels[i] = color(0);
}
}
maskingImg.updatePixels();
//moonDirt.resize(640, 480); //(640, 480);
moonDirt.loadPixels();
for (int i=0; i < rawDepth.length; i++) {
if ( maskingImg.pixels[i] == color(255) ) {
moonDirt.pixels[i] = color( 0, 0, 0, 0 );
}
}
moonDirt.updatePixels();
image(moonDirt, 0, 0, width, height);
int leftToReveal = moonDirt.pixels.length;
int revealedPixels = countPixels(moonDirt,color(0,0,0,0));
int percentageClear = round(((float)revealedPixels / leftToReveal) * 100);
println("revealed " + revealedPixels + " of " + leftToReveal + " pixels -> ~" + percentageClear + "% cleared");
...
You have the option to set the condition for all pixels to be cleared or a ratio/percentage (e.g. if more 90% is clear, that's good enough) to then change the game state accordingly.

How convert Bitmap Object to Image Object and vice versa in android 'java'

How convert Image obj to Bitmap obj and vice versa?
I have a method that get Image object input and return Image object but i want give bitmap object input and then get bitmap object output my code is this:
public Image edgeFilter(Image imageIn) {
// Image size
int width = imageIn.getWidth();
int height = imageIn.getHeight();
boolean[][] mask = null;
Paint grayMatrix[] = new Paint[256];
// Init gray matrix
for (int i = 0; i <= 255; i++) {
Paint p = new Paint();
p.setColor(Color.rgb(i, i, i));
grayMatrix[i] = p;
}
int [][] luminance = new int[width][height];
for (int y = 0; y < height ; y++) {
for (int x = 0; x < width ; x++) {
if(mask != null && !mask[x][y]){
continue;
}
luminance[x][y] = (int) luminance(imageIn.getRComponent(x, y), imageIn.getGComponent(x, y), imageIn.getBComponent(x, y));
}
}
int grayX, grayY;
int magnitude;
for (int y = 1; y < height-1; y++) {
for (int x = 1; x < width-1; x++) {
if(mask != null && !mask[x][y]){
continue;
}
grayX = - luminance[x-1][y-1] + luminance[x-1][y-1+2] - 2* luminance[x-1+1][y-1] + 2* luminance[x-1+1][y-1+2] - luminance[x-1+2][y-1]+ luminance[x-1+2][y-1+2];
grayY = luminance[x-1][y-1] + 2* luminance[x-1][y-1+1] + luminance[x-1][y-1+2] - luminance[x-1+2][y-1] - 2* luminance[x-1+2][y-1+1] - luminance[x-1+2][y-1+2];
// Magnitudes sum
magnitude = 255 - Image.SAFECOLOR(Math.abs(grayX) + Math.abs(grayY));
Paint grayscaleColor = grayMatrix[magnitude];
// Apply the color into a new image
imageIn.setPixelColor(x, y, grayscaleColor.getColor());
}
}
return imageIn;
}
If you want to convert an Image object to a Bitmap and the format has been selected as JPEG, then you can accomplish this by using the following code (if it is not a JPEG, then additional conversions will be needed):
...
if(image.getFormat() == ImageFormat.JPEG)
{
ByteBuffer buffer = capturedImage.getPlanes()[0].getBuffer();
byte[] jpegByteData = new byte[buffer.remaining()];
Bitmap bitmapImage = BitmapFactory.decodeByteArray(jpegByteData, 0, jpegByteData.length, null);
}
...
This link gives more into on saving images as a png format.
it is difficult to see what you are attempting to do, are you trying to alter this code so it also works for bitmap formats?
here is a answer of someone doing stuff with bitmap images, should be give you a idea of what other people do

negative values in the writableraster

I'm trying to implement averaging filter with different sizes 3x3 , 5x5 , 7x7 and 11x11 .. I did the calculations and the results are correct while debugging but the problem is that it is saved in the writable raster in negative, so I'm getting weird results. The second weird thing is that when I want to get the value of the same pixel that was saved in negative, it is retrieved with positive value !!
I'm using int.
What's wrong? any help ?!!
Here is my code for the 5x5 averaging filter.
public static BufferedImage filter5x5_2D(BufferedImage paddedBI , BufferedImage bi , double[][]filter)
{
WritableRaster myImage = paddedBI.copyData(null);
BufferedImage img = new BufferedImage(bi.getWidth(), bi.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
WritableRaster myImage2 = img.copyData(null);
for(int i =2; i< myImage.getHeight()-2; i++)
{
for(int j =2; j< myImage.getWidth()-2; j++)
{
int value = 0;
int copyi = i-2;
for (int m = 0 ; m<5 ; m++)
{
int copyj = j-2;
for (int n = 0; n<5; n++)
{
int result = myImage.getSample(copyj , copyi, 0);
double f = filter[m][n];
double add = result * filter[m][n];
value += (int) (filter[m][n] * myImage.getSample(copyj , copyi, 0));
copyj ++;
}
copyi++;
//myImage2.setSample(j-1 , i-1, 0, value);
}
myImage2.setSample(j-2 , i-2, 0, value);
//int checkResult = myImage2.getSample(j-1,i-1,0);
}
}
BufferedImage res= new BufferedImage(bi.getWidth(),bi.getHeight(),BufferedImage.TYPE_BYTE_GRAY);
res.setData(myImage2);
return res;
}
I do not find any negative values. Here is my main with what I have tested this code:
public static void main(String[] args) throws IOException {
BufferedImage bi = ImageIO.read(new File("C:/Tmp/test.bmp"));
BufferedImage newImage = new BufferedImage(bi.getWidth()+4, bi.getHeight()+4, bi.getType());
Graphics g = newImage.getGraphics();
g.setColor(Color.white);
g.fillRect(0,0,bi.getWidth()+4,bi.getHeight()+4);
g.drawImage(bi, 2, 2, null);
g.dispose();
double[][] filter = new double[5][5];
for( int i = 0; i < 5; ++i){
for( int j = 0; j < 5; ++j){
filter[i][j] = 1.0/(5*5);
}
}
BufferedImage filtered = filter5x5_2D(newImage, bi, filter);
ImageIO.write(filtered, "bmp", new File("C:/tmp/filtered.bmp"));
}
You should consider that your variables result, f and add are unused. Also it would be better if value would be of type double instead of int. In a worst case, you would get 25 times a value of 11 which will be rounded to zero after multiplying with 1/25. This would result in your code as a grey value of zero while it should result in 11.

OutofBoundsException setpixels

I am trying to fill a rectangle of pixels, but I always get Arrayindexoutofbounds at the below line:
targetwr.setPixels(i, j, 3, 3, pixel);
Here is my code:
WritableRaster sourcewr = source.getRaster();
BufferedImage bi = new BufferedImage(source.getWidth(),
source.getHeight(), BufferedImage.TYPE_INT_ARGB);
WritableRaster targetwr = bi.getRaster();
for (int i = 0; i < sourcewr.getWidth() - rate; i += rate) {
for (int j = 0; j < sourcewr.getHeight() - rate; j += rate) {
int[] pixel = null;
pixel = sourcewr.getPixel(i, j, pixel);
System.out.println(i + " " + j);
targetwr.setPixels(i, j, 3, 3, pixel);
}
}
Pretty straightforward. The sourcewr raster is larger than the targetwr raster. You are iterating over the length and height of the sourcewr and never check to see if the coordinates are in-bounds for the targetwr.
You can check to see if i and j are within bounds or ensure that the rasters are the same size before the nested for loops. e.g.,
if(i < targetwr.getWidth() && j < targetwr.getHeight()) {
targetwr.setPixels(i, j, 3, 3, pixel);
}
This is obviously also affected by the variable rate, whatever that is. It's not defined in your code snippet.

storing bitmap in integer array

what is the best way to do this. i have an array of height*width in length. do i simply loop through bitmap setting each pixel to the array based on the loop index? thanks
[update]
It's an app that places a fisheye distortion on a bitmap. i'm trying to store the pixel data in an array opposed to calling Bitmap.setPixel() as this comes with a massive GC overhead
for (int j=0;j<dst.getHeight();j++) {
for (int i=0;i<dst.getWidth();i++) {
origPixel= input.getPixel(i,j);
getRadXStart = System.currentTimeMillis();
float x = getRadialX((float)j,(float)i,centerX,centerY,k);
float y = getRadialY((float)j,(float)i,centerX,centerY,k);
sampleImage(input,x,y);
color = ((s[1]&0x0ff)<<16)|((s[2]&0x0ff)<<8)|(s[3]&0x0ff);
// System.out.print(i+" "+j+" \\");
//if( Math.sqrt( Math.pow(i - centerX, 2) + ( Math.pow(j - centerY, 2) ) ) <= 150 ){
if (Math.pow(i - centerX, 2) + ( Math.pow(j - centerY, 2) ) <= 22500 ) {
// dst.setPixel(i, j, color);
arr[i]=color;
} else {
//dst.setPixel(i,j,origPixel);
arr[i]=origPixel;
}
}
}
Bitmap dst2 = Bitmap.createBitmap(arr,width,height,input.getConfig());
return dst2;
Have you tried the method getPixels(...) on Bitmap?
To fill it, you will have to loop through the Bitmap to set each pixel. That said, I don't know if you'll see a major performance increase.

Categories

Resources