Libgdx get Texture from Image or Drawable - java

I would like to get the Texture data out of an image, so it may be rendered directly, but I see no straightforward way of making it, google searches show the other way around only.
I am able to get the Drawable, but the interface doesn't specify the exact texture data, so there's no way that I see to convert an Image actor into a Texture.
What I am trying to achieve is to have brushes, where the data of the brushes are stored in the image of an ImageButton. So upon clicking on an ImageButton The user would be able to draw on the screen based on the image stored in the buttons.
How might I be able to do that?

After digging deeper, I found a solution on the forums:
Your best bet is probably to draw your textures to a FrameBuffer with
a 1:1 scale, then you can use
ScreenUtils.getFrameBufferPixmap
To copy a pixmap off the FrameBuffer and resize as you wish.
Something like this:
fb.begin();
sb.begin();
sb.draw(texture, 0, 0);
sb.end();
Pixmap pm = ScreenUtils.getFrameBufferPixmap(0, 0, width, height);
fb.end();
It's not exactly a texture, but it is exactly what I would have needed: the pixel data extracted from a drawable.
After much thought I decided that it is easier to just store the texture data redundantly next to to the Imagebuttons, and query directly the stored data, instead of using the ImageButton as a kind of container, which it shouldn't be.

Related

Draw a single sprite to Pixmap - LibGDX

I am currently working on a game in which i need pixel perfect collision with objects. The only obstacle i had gotten to however, is with actually getting a mask of the object. I thought about rendering a sprite of an object (which is properly scaled and transformed) to FrameBuffer, which then i'd convert to a pixmap, but i had no luck doing it (tried many methods, including this)
So, my question is: Is there a way of rendering a single sprite to a pixmap in LibGDX?
Sounds like putting the horse behind the cart. A Sprite is a region of a Texture, which in turn is an image loaded from file aka Pixmap. If you just want to load the image from file then you can do: new Pixmap(Gdx.files.internal("yourfile.png"));. You can also scale and transform your coordinates without rendering to a FBO first.
That said; getting the Pixmap of a FrameBuffer is as "simple" as taking a screenshot while the FBO is bound, because it is exactly that.
fbo.begin();
Gdx.gl.glClear(...);
... //render to the FBO
Pixmap pixmap = ScreenUtils.getFrameBufferPixmap(0, 0, fbo.getWidth(), fbo.getHeight());
fbo.end();
Note that this will look like it is up-side-down.
But you are probably only interested in the pixel data, so you might as well skip the Pixmap step in that case and use the ScreenUtils.getFrameBufferPixels method.
However, that said; using the pixel data for collision detection is most likely not the best solution for whatever it is you are trying to achieve. Instead I'd advise to look into other options, for example have a look at this tool which can be used to convert your images into a collision shape.

ImageView doesn't stretch image properly

So I have no clue why this is happening. I am using Universal Image Loader to load these images. It seems like the last line of pixels is being streched for some weird reason. I want the image to just stretch out evenly. (I don't care that it will look weird. The images below are for demo purposes.)
Also, don't mind the first and last image. I purposely blurred that out because it had someone's face on it.
This is how I set up my Universal Image Loader:
//setup Image Loader for loading cruise line logos
displayImageOptions = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.ic_launcher)//show this image when image is loading
.showImageForEmptyUri(R.drawable.ic_launcher)//show this image incase image doesn't exist
.showImageOnFail(R.drawable.ic_launcher)//show this image if fetching image from URL didn't work
.cacheInMemory(true)//cache image in RAM
.cacheOnDisc(true)//cache image in device for later use
.considerExifParams(true)
.displayer(new RoundedBitmapDisplayer(5))//super subtle rounded corners on images
.build();
This is caused by the way RoundedBitmapDisplayer draws the bitmap.
If you look at the source, you'll see that it uses a RoundedDrawable, which uses canvas.drawRoundRect() to draw a rounded rectangle of the desired size of the Drawable, using the downloaded image as the texture via a BitmapShader. BitmapShader does not support scaling (only clamping and tile modes). Try using a SimpleBitmapDisplayer instead which uses the normal ImageView.setImageBitmap() way of displaying the image.
If you need rounded corners, you'll have to find a different way to implement that, for example by scaling the Bitmap to the desired size first. Another option is to call Canvas.saveLayer() before delegating to BitmapDrawable for the scaling, and then applying the rounded corner masking effect using PorterDuff.Mode.DST_IN. Either way you'll end up writing a bit more low-level code, but you should be able to encapsulate everything nicely in a custom BitmapDisplayer.

What is the easiest way to convert all the pixels of a specific color to transparent in a BMP?

Looking for the least painful way to grab a Bitmap and translate every pixel of a specific color to transparent.
In particular, I have set all the pixels I want to be transparent to 0xFF00FF, but I am not seeing any native method that do this.
Do I have to actually loop through all the pixels comparing values? And if so, can I change them in place or do I need to make a new bitmap array and create a new bitmap?
Bitmaps don't have alpha channels like PNG/GIF. It's up to the application to use a transparency mask.

Crop and keep the size of an image android

This is a really hard question to explain in words (well it is for me anyway). I need to be able to take an image (bitmap) and crop the image down to a certain size in the centre of the screen but keeping the size of the image the same. Hopefully the picture below can explain what I mean:
So the image as a whole is cropped down to the square in the middle but is not stretched across the screen and remains in the centre, so basically removing the pointless part of the image but keeping to co-ordinates of the pixels the same.
So let's say you have done your face detection, and have found one face in your image. Your image is 320 x 240, and the face is bound by the rectangle with location 100,40 and width 20 x 30. Now what would you like to do with that information? I'll do my best to help, but you'll probably need to clear up any poor assumptions on my part.
First, you can grab the face and store it into a new bitmap with something like Bitmap.createBitmap():
Bitmap face = Bitmap.createBitmap(largeSource, 100, 40, 20, 30);
This should be done outside of the draw loop, like in onCreate or some other initialization step.
It sounds like you've got some container (ImageView? Custom View with overridden onDraw?) which is housing your large image. And now you want to just draw the face in that container, at its original position? If you've got a custom view, that's as simple as the following in your onDraw:
canvas.drawBitmap(face, 100, 40, facePaint);
If you're using an ImageView instead, I'd suggest going to a custom-drawn view instead, since it sounds like you need some fine-grained drawing control.
Finally, if you've got a bunch of these faces, create a new FaceObj POJO object, which just has a bitmap, x, and y coordinate. As you detect faces, add them to an ArrayList, and then iterate over this in in your onDraw to draw all your faces:
faces.add(new FaceObj(Bitmap.createBitmap(largeSource, 100, 40, 20, 30), 100, 40);
...
foreach(FaceObj f : faces)
canvas.drawBitmap(f.bitmap, f.x, f.y, facePaint);
If I understand you don't really want to crop your image but "hide" any pixels around the square.
There are many ways to do this depending on what you are trying to do. For example you can fill the uninteresting part of the picture with black or make it transparent.
This way the coordinates of your "cropped" picture will remain the same on the screen.
If all you are interested in is the center of the image, then one really easy way to do this is to just add the android:scaleType="center" attribute to your ImageView, and set the ImageView to the crop size you want. If you're wanting it to be positionable, though, that's a different story.
Using Canvas.drawBitmap() you might be able to work to copy a part of the image to a different bitmap, and discard the other. With this particular version of the method, you can send in the array of colors you get with getPixels(), and set an offset, and the width and height that you want to copy. The stride parameter is important though, as it needs to be set to the width of the original image, even if your final image will be smaller, as it's pulling pixels from the original image.

Why does my smudge image algorithm make the image darker?

I'm trying to write a graphical effect where a circle moves around an image smudging the image as it goes (like the way the smudge tool in Gimp or Photoshop would work). The basic algorithm I'm using is:
the circle moves from position A to position B on the bitmap
copy a circle of pixels from position A into a temporary bitmap
draw this circle of pixels from the temporary bitmap to position B using alpha of about 50%.
This works fine and looks like what I would expect, where the image will look like it's getting smudged if the circle moves 1 pixel at a time over the image.
I now want to add some texture to the smudge effect. I have a bitmap that contains a picture of a paint blob. The algorithm from the above is modified to the following so the smudge takes the shape of this paint blob:
as before
replace the temporary bitmap pixels with the paint blob texture then copy the circle of pixels from position A into the temporary bitmap but only keep the pixels that match up against paint blob pixels (i.e. use Porter-Duff "source in destination" mode when drawing the circle into the temporary bitmap).
as before
This almost works and it looks like it's fine initially but gradually the smudging makes the colors in my image darker! If the circle passes over the same area several times, the colors eventually change to black. Any ideas what I could be doing wrong?
I've implemented the above in Android. I happened upon this post about bitmaps in Android (like my paint blob texture) being loaded with "premultiplied alpha", where the author says it caused his images to become darker because of it:
http://www.kittehface.com/2010/06/androidbitmap-and-premultiplied-alpha.html
I suspect I'm suffering from a similar problem but I don't understand what's going on well enough and don't know how to fix it. Does anyone have hints at what might be going on?
Well from first glance the reason the image is getting darker is because #3 in the first three steps. You overlaying a pixel over an existing pixel at 50%. You might want to consider using the mean of the original pixel value and the new pixel value. You might want to research some blurring algorithms.

Categories