I need to remove blur from the image wherever user touch on screen from an image and save it's state. I have been using the following library.
https://github.com/cats-oss/android-gpuimage
I have used the following example which is using android-gpuimage
https://github.com/ufo22940268/Android-Blur
It removes blur from image wherever I touch but when I touch other parts of the image the later touch point become blur again.
public void onTouch(MotionEvent event){
float y = event.getY(mActionIndex);
float x = event.getX(mActionIndex);
focus(x, y);
requestRender();
}
private void focus(float x, float y) {
GPUImageFilter filter = getFilter();
if (filter != null && filter instanceof GPUImageBoxBlurFilter) {
GPUImageBoxBlurFilter blurFilter = (GPUImageBoxBlurFilter) filter;
blurFilter.focus(x, y);
}
}
public void focus(final float x, final float y) {
runOnDraw(new Runnable() {
#Override
public void run() {
float[] focusLocation = new float[]{normalize(x, mOutputWidth), -normalize(y, mOutputHeight)};
GPUImageFilter filter = mFilters.get(0);
int screenRatioLocation = GLES20.glGetUniformLocation(filter.getProgram(), "focusLocation");
filter.setFloatVec2(screenRatioLocation, focusLocation);
filter = mFilters.get(1);
screenRatioLocation = GLES20.glGetUniformLocation(filter.getProgram(), "focusLocation");
filter.setFloatVec2(screenRatioLocation, focusLocation);
initTexelOffsets();
}
});
}
private float normalize(float x, int outputWidth) {
return x / outputWidth * 2 - 1;
}
protected void initTexelOffsets() {
float ratio = getHorizontalTexelOffsetRatio();
GPUImageFilter filter = mFilters.get(0);
int texelWidthOffsetLocation = GLES20.glGetUniformLocation(filter.getProgram(), "texelWidthOffset");
int texelHeightOffsetLocation = GLES20.glGetUniformLocation(filter.getProgram(), "texelHeightOffset");
filter.setFloat(texelWidthOffsetLocation, ratio / mOutputWidth);
filter.setFloat(texelHeightOffsetLocation, 0);
ratio = getVerticalTexelOffsetRatio();
filter = mFilters.get(1);
texelWidthOffsetLocation = GLES20.glGetUniformLocation(filter.getProgram(), "texelWidthOffset");
texelHeightOffsetLocation = GLES20.glGetUniformLocation(filter.getProgram(), "texelHeightOffset");
filter.setFloat(texelWidthOffsetLocation, 0);
filter.setFloat(texelHeightOffsetLocation, ratio / mOutputHeight);
}
Whenever user select unblur then touching on image should remove blur from that point and save image so that when user touch another point both or more points should be unblured.
Need vice versa of this as well, if user select blur it should blur that point.
As I am pretty noob in opengl any help will be greately appreciated.
Related
I have set up a game where Actor fireflies randomly fly across the screen, while glowing on and off — and a user can drag them into a mason jar. Pretty happy I've got this working, but I'd like to add a bit more detail. I'd like to add a two-step animation so that it looks like their wings are flapping.
I know how to do this with the Animation class, making use of TextureAtlas and TextureRegion. But that was prior to me heading in this Drag n Drop direction.
My issue, I think, is that I'm using skins, and they might not play nice with Animations.
///////////////////
Portions of my code.
///////////////////
Some of the items I declare up top:
private TextureAtlas textureAtlas;
private Texture texture;
private TextureRegion[] regions = new TextureRegion[3];
private Animation ffFlapping;
Setting up my TextureAtlas:
textureAtlas = new TextureAtlas(Gdx.files.internal("Player Animation/player_animation.png.atlas"));
texture = new Texture(Gdx.files.internal("Player Animation/player_animation.png.png"));
Setting up the skin:
final Skin skin = new Skin();
skin.addRegions(textureAtlas);
Doing the animation:
TextureRegion[] ffAnimation = new TextureRegion[2];
ffAnimation[0] = (textureAtlas.findRegion("firefly-0"));
ffAnimation[1] = (textureAtlas.findRegion("firefly-1"));
ffFlapping = new Animation(0.01f, ffAnimation);
For loop to create all my fireflies:
// ********************************************
// iterate through the number of fireflies
// we want to draw out using fireflyCount
// ********************************************
for (int fireflyIndex = 0; fireflyIndex < fireflyCount; fireflyIndex++) {
// YELLOW FIREFLY HERE
String fireflyName = "firefly" + fireflyIndex;
// if I replace ffFlapping below with object, I get no errors,
// but also no animation
skin.add(fireflyName, ffFlapping);
final Firefly ff = new Firefly(skin, fireflyName);
System.out.println("Fireflies objects:" + fireflyIndex);
// Not sure this affected the color, but it starts the alpha at 0
ff.setColor(150, 150, 150, 0);
ff.setOrigin(ff.getWidth()/2, ff.getHeight()/2);
stage.addActor(ff);
// This was set up in the attempt to continue movement if user misses target
final MoveToAction actionRight = new MoveToAction();
final MoveToAction actionLeft = new MoveToAction();
// setting up right and left targets, with a random Y position
float toRight = Gdx.graphics.getWidth() + 60;
float toLeft = (Gdx.graphics.getWidth() -Gdx.graphics.getWidth())-60f;
// sets up speed of glow, and the random time firefly is off, and also on
float glow = MathUtils.random(.5f, 1f);
float delayRandomOff = MathUtils.random(2.3f, 4.5f);
float delayRandomOn = MathUtils.random(.5f, .9f);
// sets up first variable to randomly choose between toRight and toLeft
// assigns direction to that value
float randomDirection = MathUtils.random.nextBoolean() ? toRight : toLeft;
float direction = randomDirection;
SequenceAction sequence = new SequenceAction();
AlphaAction aa = new AlphaAction();
Action alphaStartOn = Actions.delay(delayRandomOn, Actions.fadeOut(glow));
Action alphaStartOff = Actions.delay(delayRandomOff, Actions.fadeIn(glow));
// toRight is the x value ... it goes (x, y, duration)
Action startRight = Actions.moveTo(toRight, MathUtils.random(50, Gdx.graphics.getHeight() - 40), MathUtils.random(10f, 45f));
// toLeft is the x value ... it goes (x, y, duration)
// 170 makes sure they don't fly on top of mason jar
Action startLeft = Actions.moveTo(toLeft, MathUtils.random(170, Gdx.graphics.getHeight() - 40), MathUtils.random(10f, 45f));
Action faceOpposite = Actions.rotateBy(180f);
Action faceOpposite2 = Actions.rotateBy(180f);
// THIS ENDLESSLY LOOPS THEM ON THE SCREEN
Action loopRight = Actions.forever(Actions.sequence(faceOpposite, startRight, faceOpposite2, startLeft));
Action loopLeft = Actions.forever(Actions.sequence(startLeft, faceOpposite, startRight, faceOpposite2));
Action loopGlow1 = Actions.forever(Actions.sequence(alphaStartOn, alphaStartOff));
Action loopGlow2 = Actions.forever(Actions.sequence(alphaStartOff, alphaStartOn));
// THIS IS DEFINITELY TRIGGERING THE MOVEMENT
if(direction == toRight) {
ff.addAction(loopRight);
ff.addAction(loopGlow1);
} else {
ff.addAction(loopLeft);
ff.addAction(loopGlow2);
}
// MAKE EACH FIREFLY DRAGGABLE, and SET LARGER SIZE as you drag
dragAndDrop.addSource(new DragAndDrop.Source(ff) {
public DragAndDrop.Payload dragStart (InputEvent event, float x, float y, int pointer) {
DragAndDrop.Payload payload = new DragAndDrop.Payload();
payload.setObject("Firefly captured");
payload.setDragActor(ff);
ff.clearActions();
getActor().setSize(80, 80);
// Firefly freezes on drag, and enlarges ... disappears if dropped in jar
// Does not visually drag with cursor since it was part of animation.
return payload;
}
// IF YOU DON'T DROP FIREFLY ON TARGET, MAKE SURE IT STAYS ON STAGE
// AND GOES BACK TO THE NORMAL SIZE
#Override
public void dragStop(InputEvent event, float x, float y, int pointer, DragAndDrop.Payload payload, DragAndDrop.Target target) {
if(target == null)
stage.addActor(ff);
ff.addAction(actionLeft);
getActor().setSize(50, 50);
}
});
// MAKE EACH FIREFLY DRAGGABLE, and SET LARGER SIZE as you drag
dragAndDrop.addSource(new DragAndDrop.Source(ff) {
public DragAndDrop.Payload dragStart (InputEvent event, float x, float y, int pointer) {
DragAndDrop.Payload payload = new DragAndDrop.Payload();
payload.setObject("Firefly captured");
payload.setDragActor(ff);
ff.clearActions();
getActor().setSize(80, 80);
// Firefly freezes on drag, and enlarges ... disappears if dropped in jar
// Does not visually drag with cursor since it was part of animation.
return payload;
}
// IF YOU DON'T DROP FIREFLY ON TARGET, MAKE SURE IT STAYS ON STAGE
// AND GOES BACK TO THE NORMAL SIZE
#Override
public void dragStop(InputEvent event, float x, float y, int pointer, DragAndDrop.Payload payload, DragAndDrop.Target target) {
if(target == null)
stage.addActor(ff);
ff.addAction(actionLeft);
getActor().setSize(50, 50);
}
});
} // ***** END OF FOR LOOP ***********
And here's my Firefly code:
public class Firefly extends Image {
private float x = MathUtils.random(20, Gdx.graphics.getWidth() -40);
private float y = MathUtils.random(200, Gdx.graphics.getHeight() - 40);
private float width = 70;
private float height = 70;
public Firefly(Skin skin, String drawableName) {
super(skin, drawableName);
this.setBounds(x, y, width, height);
}
} // firefly
The error I'm getting is:
com.badlogic.gdx.utils.GdxRuntimeException: No Drawable, NinePatch, TextureRegion, Texture, or Sprite registered with name: firefly-2
///////////////////////////////
Any tips are very much appreciated.
In the meantime, I'm creating a new feature branch and keeping at it.
My guess is that I need to somehow make my two-step animation into some kind of Drawable.
Thanks!
— Bill
I'm having a hard time believing this isn't possible. I have a map in an ImageViewTouch view, and I'm trying to add a "You Are Here" image on the image that I move (within the map image) based on the user's location.
When the user pans around on the map, I'd like the You Are Here to pan too by being inside the ImageViewTouch. (Ideally I'd like it to scale with zooming too, but I'll take what I can get!)
I've considered using Canvas to create a new Bitmap every time the user's location changes, but considering the map is large, it wouldn't be very performant.
Is there any way to do this?
I figured it out! Instead of using Canvas and Bitmap which are slower and cause issues, I was able to use LayerDrawable. In case this helps anyone in the future, here's my code.
public void updateYouAreHere(#Nullable MapLocation location, boolean initial){
Resources resources = getResources();
Drawable drawable;
if (location == null){
drawable = MiscUtil.getDrawable(resources, R.drawable.map_image);
}else{
Drawable[] layers = new Drawable[]{
MiscUtil.getDrawable(resources, R.drawable.map_image),
MiscUtil.getDrawable(resources, R.drawable.you_are_here)
};
mapDrawable = new LayerDrawable(layers);
final int iconWidth = 50;
final int iconHeight = 86;
mapDrawable.setLayerInset(1, location.x, location.y,
(int)(Globals.Map.MapWidth) - location.x - iconWidth, (int)(Globals.Map.MapHeight) - location.y - iconHeight);
drawable = mapDrawable;
}
if (!initial) {
Matrix currentPosition = mapScrollView.getDisplayMatrix();
float minScale = mapScrollView.getMinScale();
float maxScale = mapScrollView.getMaxScale();
mapScrollView.setImageDrawable(drawable, currentPosition, minScale, maxScale);
}else{
mapScrollView.setImageDrawable(drawable);
}
}
private class MapLocation {
public int x;
public int y;
public MapLocation(int x, int y){
this.x = x;
this.y = y;
}
}
Also, MiscUtil.getDrawable is just a wrapper that calls the appropriate getResources().getDrawable() function based on SDK version.
Does anyone know the double-tap-zoom function on normal Android application (like web view or image view) is accomplished by zoom animation or by dividing the zoom into small steps and perform them one by one?
If using zoom animation, since animation is cached drawing, is there any problem when I do zoom in like this?
mView.zoomTo(newScale);
mView.startAnimation(zoomInAnimation);
Should I only set the new scale after animation finished?
And if using multiple steps of zooming, is this really a good approach? How to perform each step? Send messages multiple times?
What is exactly the best way of doing smooth zoom in/out when double tapping?
extend Animation class and override applyTransformarion method, use interpolatedTime parameter to compute the current zoom level
EDIT
as simple as it can be, works with really ancient droids:
public class ZoomAnimation extends Animation {
private float mFrom;
private float mTo;
public ZoomAnimation(float from, float to) {
mFrom = from;
mTo = to;
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
float currentZoom = mFrom + ((mTo - mFrom) * interpolatedTime);
// do something with currentZoom
}
}
While waiting for the best answer, I tried "multiple-step-zooming" by myself, and it turns out charming.
If anyone could give out a better answer, I will accept yours.
The multiple-step-zooming is performed by posting the nested Runnable instance, the mCanvasScale is the field used to control the drawing of the view. setZoomValue() is setting the mCanvasScale and call invalidate().
public void smoothScaleTo(final float targetScale) {
if(targetScale != mCanvasScale) {
post(new SmoothScaleExecutor(mCanvasScale, targetScale));
}
}
private class SmoothScaleExecutor implements Runnable {
public static final int SMOOTH_SCALE_STEPS = 4;
private float mStartingScale;
private float mTargetScale;
private float mScaleStep;
public SmoothScaleExecutor(float startingScale, float targetScale) {
mStartingScale = startingScale;
mTargetScale = targetScale;
mScaleStep = (targetScale - startingScale) / SMOOTH_SCALE_STEPS;
}
#Override
public void run() {
if(mStartingScale < mTargetScale) {
if(mCanvasScale < mTargetScale) {
float f = mCanvasScale + mScaleStep;
if(f > mTargetScale) f = mTargetScale;
setZoomValue(f);
post(this);
}
} else {
if(mCanvasScale > mTargetScale) {
float f = mCanvasScale + mScaleStep;
if(f < mTargetScale) f = mTargetScale;
setZoomValue(f);
post(this);
}
}
}
}
I'm making a game with Andengine and i'm stuck for 2 days on shooting from a rotating sprite. I'm not a hero at geometry and already ask a teacher but he could also not provide me the correct answer. So who is a mathematics hero and help me out :).
The problem is that i cannot figure out where the bullet has to spawn in front of the turret. Rotating and finding the destination where the bullet has to go is no problem. It only about the spawn point.
I removed a lot of not-interesting-code for this question.
Okay so here is the rotating code from the turret-rotation:
public class AlienShip extends Ship {
public static final float BASE_ROTATION_SPEED = 0.25f;
public static final int DEFAULT_IMAGE_ROTATION = 90; //90 degrees
protected PlayerShip ship;
public AlienShip(float pX, float pY, TextureRegion pTextureRegion,
VertexBufferObjectManager pVertexBufferObject,FixedStepPhysicsWorld pw, int baseDurability) {
super(pX, pY, pTextureRegion, pVertexBufferObject, pw, baseDurability);
}
public void rotateToPlayer()
{
if (ship != null) {
float dX = this.getX() - ship.getX();
float dY = this.getY() - ship.getY();
float angle = (float) Math.atan2(-dY, dX);
float rotation = MathUtils.radToDeg(angle) + DEFAULT_IMAGE_ROTATION;
RotationModifier rotMod = new RotationModifier(BASE_ROTATION_SPEED, this.getRotation(), rotation);
this.registerEntityModifier(rotMod);
}
}
public void rotateToInitPos() {
RotationModifier rotMod = new RotationModifier(BASE_ROTATION_SPEED, this.getRotation(), 0);
this.registerEntityModifier(rotMod);
}
}
The code above is working fine.
Here is the code from the laser that the ship is shooting.
Read the comments to find out witch part is not working.
public class GameScene extends Scene {
protected PlayerShip playerShip;
private SpawnCallback createShootCallback(boolean player) {
return new SpawnCallback() {
#Override
public void spawn(SpawnTimer spawnTimer) {
PhysicsSprite laser = null;
AlienShip alienShip = (AlienShip) spawnTimer.getPhysicsSprite();
// laser = alienMissilePool.getMissileFromPool(x,y)
//spawn the laser in front of the rotating ship [Not working :( ]
laser = alienMissilePool.getMissileFromPool( ( alienShip.getX() * FloatMath.cos(MathUtils.degToRad(rotation)) - ((1280 - alienShip.getY() - alienShip.getY()/2) * FloatMath.sin(MathUtils.degToRad(rotation)) ) ) ,
( alienShip.getX() * FloatMath.sin(MathUtils.degToRad(rotation)) + ((1280 - alienShip.getY() - alienShip.getY()/2) * FloatMath.cos(MathUtils.degToRad(rotation)) ) ) );
//Set the rotation from the laser same to the ship rotation [Is working perfectly].
float rotation = alienShip.getRotation();
laser.setRotation(rotation);
//Set laser speed and direction [Is working perfectly]
float pX = 0.01f * (playerShip.getX() - laser.getX());
float pY = 0.01f * (playerShip.getY() - laser.getY());
laser.getSpriteBody().setLinearVelocity(pX, pY);
spawnPhysicsSprite(laser);
}
};
}
}
Here is a link to a drawing that shows the x-axis and y-axis values.
http://s24.postimg.org/citz29339/gamescene.png
Thank you!
Instead of getting into maths, why don't you put an object (Entity) positioned on the place of the turret and use it's position as the spawn point for the laser ?
so your turret would have an Entity attached to it on the place of the gun.
tell me if you need an example code
I am trying to check collisions between lines and a circle, if the circle hits the line, it would work change a boolean to true and once its not touched, it would change it back to false. I am using canvas and surface view.
Here is my code for checking collision which didn't work and ended up in error:
#Override
public void run() {
while(runnable)
{
if(!holder.getSurface().isValid()){
continue;
}
Canvas mCanvas = holder.lockCanvas();
update(mCanvas);
values = new Values(mCanvas);
createPaints();
drawBackground(mCanvas);
drawObjects(mCanvas);
holder.unlockCanvasAndPost(mCanvas);
}
}
Now the collision is processed in the update:
private void update(Canvas c) {
ball.update(c, checkLinesCollision(values.level1, ball.getX(), ball.getY()));
//takes a canvas, and a boolean
}
boolean checkLinesCollision(float[] f,float x,float y){
int c = 0;
for(int i = 0; i < f.length; i+=4){
float x1 = f[i];
float y1 = f[i+1];
float x2 = f[i+2];
float y2 = f[i+3];
if (x> x1 && x<x2 && y>y1 && y>y2){
c++;
}
}
if(c>0){return true;}else{return false;}
}
the values for the level
float yLow = c.getHeight()-c.getHeight()/4;
level1 = new float[]{0,yLow,c.getWidth(),yLow,
40,c.getHeight()/2,300,c.getHeight()/2};
ball update function:
public void update(Canvas c, boolean b) {
if(b){
dy=-dy;
b = false;
}
y -= dy;
dy--;
}
Now according to the logcat the problem is in the main update function.
I think that I am using the wrong function, what can I do to fix it?
Thanks!
I have found the solution. Apparently the problem was with the float array; in my app, i declared the float array in a constructor. After a long time of researching on the web and rechecking my logcat, i found that you cannot declare an array in the constructor. all i did was moving the float array outside of the constructor and everything was alright, even though i found the solution, i am not sure why you cannot declare it in the constructor..