Android OpenGL Screenshot - android

I've searched a lot about taking screenshot of my OpenGL object on Android and come up with this solution. It worked great but in my case I have camera view and opengl view(with transparent background) on top of camera view. So what I want to do is to get opengl screenshot with transparent background instead of black.
As I said I have tried link above and it worked but I'm stuck with black background. It's little bit complicated to figure out how to get rid of the black background in this particular case.
Hope somebody could help me and asap if it's possible(also I think the solution is easy, I'm just missing something simple).
Thank you.

I used following method and worked like a champ.
public static Bitmap SavePixels(int x, int y, int w, int h, GL10 gl)
{
int b[]=new int[w*(y+h)];
int bt[]=new int[w*h];
IntBuffer ib=IntBuffer.wrap(b);
ib.position(0);
gl.glReadPixels(x, 0, w, y+h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, ib);
for(int i=0, k=0; i<h; i++, k++)
{//remember, that OpenGL bitmap is incompatible with Android bitmap
//and so, some correction need.
for(int j=0; j<w; j++)
{
int pix=b[i*w+j];
int pb=(pix>>16)&0xff;
int pr=(pix<<16)&0x00ff0000;
int pix1=(pix&0xff00ff00) | pr | pb;
bt[(h-k-1)*w+j]=pix1;
}
}
Bitmap sb=Bitmap.createBitmap(bt, w, h, Bitmap.Config.ARGB_8888);
return sb;
}
You just need to call
YourClass.SavePixels(0,0,width,height,gl);
I hope this will work for you...
Thanks,
Midhun

The solution you mentioned is using a Bitmap.Config.RGB_565 which doesn't support alpha channels.
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Instead you should use Bitmap.Config.ARGB_8888 or Bitmap.Config.ARGB_4444.

Related

Set all black in image to another color (ImageView/Bitmap)

I'm trying to convert all the black pixels in one Bitmap (Created from an ImageView that was a PNG file)..
I've tried it in many ways but I still couldn't succeed in that.
Please help me I'm trying it for like 3 days straight...
A little example of my code:
headSkin.buildDrawingCache();
final Bitmap bmp = headSkin.getDrawingCache();
int w = bmp.getWidth();
int h = bmp.getHeight();
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
int color = bmp.getPixel(x, y);
// Shift your alpha component value to the red component's.
bmp.setPixel(x, y, Color.RED);
}
}
As you can see... I didn't even state an IF statement..
I just tried to make all the pixels red in this bitmap and even this didn't work.. pls help?
I see 2 problems here,
First, you have this Bitmap object in your memory, and you change the black pixels to red, but how do you know if it is changed or not? You should set an ImageView to this Bitmap to see the result (or save it to file etc.)
Second, use getPixels and setPixels instead, getPixels will give you 1 dimensional array, it goes like 1.row, 2.row, 3.row etc. And setPixels also accepts a 1 dimensional array. This function is incredibly faster than altering pixels 1 by 1.
#Anil
Hi dude, just tried it and I can't use it 'cuz of IndexOutOfBound exception...
headSkin.buildDrawingCache();
bmp = headSkin.getDrawingCache();
int [] allpixels = new int [bmp.getHeight()*bmp.getWidth()];
bmp.getPixels(allpixels, 0, bmp.getWidth(), 0, 0, bmp.getWidth(), bmp.getHeight());
for(int i = 0; i < allpixels.length; i++)
{
if(allpixels[i] == Color.BLACK)
{
allpixels[i] = Color.RED;
}
}
bmp.setPixels(allpixels, 0, bmp.getWidth(), 0, 0, bmp.getWidth(), bmp.getHeight());
headSkin.setImageBitmap(bmp);
what is the problem here?
EDIT: Just tried it now while running, not debugging and it doesn't even show me an error or something.. It just makes about 1-2 single pixels red in this whole bitmap
headSkin.buildDrawingCache();
final Bitmap bmp = headSkin.getDrawingCache();
I think you have problem on these lines. The rest of the code looks fine.
Maybe the bitmap is not initialized, so you only have a Bitmap reference, instead of Bitmap object with data inside.
Can you delete the bitmap part from your code and initialize Bitmap like this:
Bitmap myBitmap = Bitmap.createBitmap(500, 500, Bitmap.Config.RGB8888);
and then perform pixel operations like you did above, just set all the pixels to same color.

Bitmap threshold quicker

I am trying to write a method that will take a Bitmap and force it to a strict black and white image (no shades of grey).
I first pass the bitmap to a method that makes it greyscale using colormatrix:
public Bitmap toGrayscale(Bitmap bmpOriginal)
{
int width, height;
height = bmpOriginal.getHeight();
width = bmpOriginal.getWidth();
Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Canvas c = new Canvas(bmpGrayscale);
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
c.drawBitmap(bmpOriginal, 0, 0, paint);
return bmpGrayscale;
}
that works nice and fast..
then i pass it to another method to force the greyscaled image to a 2 color image (black and white) this method works but obviously it is going through each pixel and that takes a long time:
public Bitmap toStrictBlackWhite(Bitmap bmp){
Bitmap imageOut = bmp;
int tempColorRed;
for(int y=0; y<bmp.getHeight(); y++){
for(int x=0; x<bmp.getWidth(); x++){
tempColorRed = Color.red(imageOut.getPixel(x,y));
Log.v(TAG, "COLOR: "+tempColorRed);
if(imageOut.getPixel(x,y) < 127){
imageOut.setPixel(x, y, 0xffffff);
}
else{
imageOut.setPixel(x, y, 0x000000);
}
}
}
return imageOut;
}
anyone know a faster more efficient way to do this?
Don't use getPixel() and setPixel().
Use getPixels() which will return a multidimensional array of all pixels. Do your operations locally on this array, then use setPixels() to set back the modified array. This will be significantly faster.
Have you tried something like converting it into a byte array (see the answer here)?
And, as I look into this, the Android reference for developers about Bitmap processing might help you as well.

OpenGL screenshot Android

I have an application that uses GLSurfaceView to do some 3-D goodness in Android. I'd like the user to be able to take a screenshot. I think this snippet of code should be storing the pixel colors and storing them inside a bitmap. However, does anyone know how to access the gl10 element that the screen is using, so I can feed it into this function?
public static Bitmap savePixelsOnScreen(int x, int y, int width, int height, GL10 gl){
int b[]=new int[w*(y+h)];
int bt[]=new int[w*h];
IntBuffer ib=IntBuffer.wrap(b);
ib.position(0);
//gl.glReadPixels(x, y, w, h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, ib);
gl.glReadPixels(x, 0, w, y+h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, ib);
for(int i=0, k=0; i<h; i++, k++)
{//remember, that OpenGL bitmap is incompatible with Android bitmap
//and so, some correction need.
for(int j=0; j<w; j++)
{
int pix=b[i*w+j];
int pb=(pix>>16)&0xff;
int pr=(pix<<16)&0x00ff0000;
int pix1=(pix&0xff00ff00) | pr | pb;
bt[(h-k-1)*w+j]=pix1;
}
}
Bitmap sb=Bitmap.createBitmap(bt, w, h, Bitmap.Config.ARGB_8888);
return sb;
return bitmap;
I had tried to do this from within the Activity that calls the GLSurfaceView:
EGL10 egl = (EGL10)EGLContext.getEGL();
GL10 gl = (GL10)egl.eglGetCurrentContext().getGL();
But every element of the int buffer is zero so I think this is not correct.
put the code under draw(GL10 gl) method of your CClayer/CCNode class and also maintain boolean variable to draw it only once. Draw method will be called 60+ times per second.

How to get access to main screen/OpenGL buffer in Android?

I'd like to get access to the main (OpenGL) screen in Android to implement some overlay 3D effects.
Is it possible to do so?
If yes, how can I do it?
When amending this context, my application should be a service, right?
You cannot get access to the framebuffer, for obvious security reasons.
What you will probably want to do is research the glReadPixels() function. I ran a test where I had the screen split with a glsurfaceview and image view and wanted to see if I could grab the pixels from the glview and create a Bitmap and then apply that to the ImageView. After some research, I found using glReadPixels() works, but you have to tranform the pixels before using them for an android bitmap. This is the method I ended up using. I'm confident that I found it exactly this way on another forum.
public Bitmap SaveGLPixels(int x, int y, int w, int h, GL10 gl)
{
int b[]=new int[w*h];
int bt[]=new int[w*h];
IntBuffer ib=IntBuffer.wrap(b);
ib.position(0);
gl.glReadPixels(x, y, w, h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, ib);
for(int i=0; i<h; i++)
{//remember, that OpenGL bitmap is incompatible with Android bitmap
//and so, some correction need.
for(int j=0; j<w; j++)
{
int pix=b[i*w+j];
int pb=(pix>>16)&0xff;
int pr=(pix<<16)&0x00ff0000;
int pix1=(pix&0xff00ff00) | pr | pb;
bt[(h-i-1)*w+j]=pix1;
}
}
Bitmap.Config bconfig = Bitmap.Config.RGB_565;
Bitmap sb=Bitmap.createBitmap(bt, w, h, bconfig);
return sb;
}

Android opengl screenshot with alpha channel support

I'm currently developing an augmented reality application in android. Textured openGL object is drawn over the camera view. I had tried so many methods to take the screen shot of android openGL view (GLSurfaceview). But no success. I want the screenshot with transparent background so that I could draw it over camera image to produce an ARImage. Can any one help me? I know that I have to read the pixels of opengl using glReadPixels() function. I tried it using GL_RGBA mode and created bitmap (used ARGB_8888 and RGB_565). Using ARGB_8888 format I'll get a transparent image with no object and in RGB_565 mode I'll get a image filled with black color. Can any one guide me? Thanks in advance.
Thanks,
Midhun
Hi I found the solution to my question and I'll paste the code here. It may be useful for others who need alpha support.
public static Bitmap SavePixels(int x, int y, int w, int h, GL10 gl)
{
int b[]=new int[w*(y+h)];
int bt[]=new int[w*h];
IntBuffer ib=IntBuffer.wrap(b);
ib.position(0);
gl.glReadPixels(x, 0, w, y+h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, ib);
for(int i=0, k=0; i<h; i++, k++)
{//remember, that OpenGL bitmap is incompatible with Android bitmap
//and so, some correction need.
for(int j=0; j<w; j++)
{
int pix=b[i*w+j];
int pb=(pix>>16)&0xff;
int pr=(pix<<16)&0x00ff0000;
int pix1=(pix&0xff00ff00) | pr | pb;
bt[(h-k-1)*w+j]=pix1;
}
}
Bitmap sb=Bitmap.createBitmap(bt, w, h, Bitmap.Config.ARGB_8888);
return sb;
}
This so called "solution" is simply making a screen shot. Alpha values that you get from glReadPixels are up to full 255 although you didn't draw anything to those pixels. If it's possible it will be an OpenGL-settings solution.

Categories

Resources