I want to implement image processing in my project. I had used JLabs library. I want to do using this library following effects.
1) Deboss
2) Engrave
3) Satin etch
4) Custom shape like Cylinder.
This is sample image emboss code.
public class EmbossFilter
extends WholeImageFilter {
private static final float pixelScale = 255.9f;
private float azimuth = 2.3561945f;
private float elevation = 0.5235988f;
private boolean emboss = false;
private float width45 = 3.0f;
public void setAzimuth(float azimuth) {
this.azimuth = azimuth;
}
public float getAzimuth() {
return this.azimuth;
}
public void setElevation(float elevation) {
this.elevation = elevation;
}
public float getElevation() {
return this.elevation;
}
public void setBumpHeight(float bumpHeight) {
this.width45 = 3.0f * bumpHeight;
}
public float getBumpHeight() {
return this.width45 / 3.0f;
}
public void setEmboss(boolean emboss) {
this.emboss = emboss;
}
public boolean getEmboss() {
return this.emboss;
}
#Override
protected int[] filterPixels(int width, int height, int[] inPixels, Rect transformedSpace) {
int index = 0;
int[] outPixels = new int[width * height];
int bumpMapWidth = width;
int bumpMapHeight = height;
int[] bumpPixels = new int[bumpMapWidth * bumpMapHeight];
int i = 0;
while (i < inPixels.length) {
bumpPixels[i] = PixelUtils.brightness(inPixels[i]);
++i;
}
int Lx = (int) (Math.cos(this.azimuth) * Math.cos(this.elevation) * 255.89999389648438);
int Ly = (int) (Math.sin(this.azimuth) * Math.cos(this.elevation) * 255.89999389648438);
int Lz = (int) (Math.sin(this.elevation) * 255.89999389648438);
int Nz = (int) (1530.0f / this.width45);
int Nz2 = Nz * Nz;
int NzLz = Nz * Lz;
int background = Lz;
int bumpIndex = 0;
int y = 0;
while (y < height) {
int s1 = bumpIndex;
int s2 = s1 + bumpMapWidth;
int s3 = s2 + bumpMapWidth;
int x = 0;
while (x < width) {
int shade;
if (y != 0 && y < height - 2 && x != 0 && x < width - 2) {
int NdotL;
int Nx = bumpPixels[s1 - 1] + bumpPixels[s2 - 1] + bumpPixels[s3 - 1] - bumpPixels[s1 + 1] - bumpPixels[s2 + 1] - bumpPixels[s3 + 1];
int Ny = bumpPixels[s3 - 1] + bumpPixels[s3] + bumpPixels[s3 + 1] - bumpPixels[s1 - 1] - bumpPixels[s1] - bumpPixels[s1 + 1];
shade = Nx == 0 && Ny == 0 ? background : ((NdotL = Nx * Lx + Ny * Ly + NzLz) < 0 ? 0 : (int) ((double) NdotL / Math.sqrt(Nx * Nx + Ny * Ny + Nz2)));
} else {
shade = background;
}
if (this.emboss) {
int rgb = inPixels[index];
int a = rgb & -16777216;
int r = rgb >> 16 & 255;
int g = rgb >> 8 & 255;
int b = rgb & 255;
r = r * shade >> 8;
g = g * shade >> 8;
b = b * shade >> 8;
outPixels[index++] = a | r << 16 | g << 8 | b;
} else {
outPixels[index++] = -16777216 | shade << 16 | shade << 8 | shade;
}
++x;
++s1;
++s2;
++s3;
}
++y;
bumpIndex += bumpMapWidth;
}
return outPixels;
}
public String toString() {
return "Stylize/Emboss...";
}
}
How to achieve image effects using Jhlabs library or any other way please share with me.
I'm trying to implement rope swinging in my platformer, following this tutorial. Instead of swing on the rope, the player looks like he's sliding down a slope: he moves very slowly towards the bottom.
This is what it looks like now:
Instead, I want the player to have more natural movement, like he's really swinging on the rope.
This is the update method from my player class:
#Override
public final void update() {
setPosition(getNextPosition());
if (direction == Direction.LEFT && moving) {
getVelocity().x = -WALK_SPEED;
} else if (getVelocity().x < 0) {
getVelocity().x *= COEF_FRIC;
}
if (direction == Direction.RIGHT && moving) {
getVelocity().x = WALK_SPEED;
} else if (getVelocity().x > 0) {
getVelocity().x *= COEF_FRIC;
}
checkAsleep();
animations.update();
if (ropePoint != null) {
//getCenter() returns the center position of the player
if (getCenter().toPoint().distanceSq(ropePoint) > ROPE_LENGTH * ROPE_LENGTH) {
final Vec2D oldPosition = getCenter();
final Vec2D oldVelocity = getVelocity();
final Vec2D ropePosition = new Vec2D(ropePoint);
setCenter((oldPosition.subtract(ropePosition).unit().multiply(ROPE_LENGTH).add(ropePosition)));
setVelocity(oldPosition.subtract(getCenter()).unit().multiply(oldVelocity));
}
}
}
This is my implementation of getNextPosition(), if it is needed.
public final Vec2D getNextPosition() {
final int currCol = (int) (getX() / Tile.SIZE);
final int currRow = (int) (getY() / Tile.SIZE);
final double destX = getX() + moveData.velocity.x;
final double destY = getY() + moveData.velocity.y;
double tempX = getX();
double tempY = getY();
Corners solidCorners = getCornersAreSolid(getX(), destY);
boolean topLeft = solidCorners.topLeft;
boolean topRight = solidCorners.topRight;
boolean bottomLeft = solidCorners.bottomLeft;
boolean bottomRight = solidCorners.bottomRight;
framesSinceLastTopCollision += 1;
framesSinceLastBottomCollision += 1;
framesSinceLastLeftCollision += 1;
framesSinceLastRightCollision += 1;
if (moveData.velocity.y < 0) {
if (topLeft || topRight) {
moveData.velocity.y = 0;
tempY = currRow * Tile.SIZE;
framesSinceLastTopCollision = 0;
} else {
tempY += moveData.velocity.y;
}
} else if (moveData.velocity.y > 0) {
if (bottomLeft || bottomRight) {
moveData.velocity.y = 0;
tempY = (currRow + 1) * Tile.SIZE - moveData.collisionBox.getHeight() % Tile.SIZE - 1;
framesSinceLastBottomCollision = 0;
} else {
tempY += moveData.velocity.y;
}
}
solidCorners = getCornersAreSolid(destX, getY());
topLeft = solidCorners.topLeft;
topRight = solidCorners.topRight;
bottomLeft = solidCorners.bottomLeft;
bottomRight = solidCorners.bottomRight;
if (moveData.velocity.x < 0) {
if (topLeft || bottomLeft) {
moveData.velocity.x = 0;
tempX = currCol * Tile.SIZE;
framesSinceLastLeftCollision = 0;
} else {
tempX += moveData.velocity.x;
}
}
if (moveData.velocity.x > 0) {
if (topRight || bottomRight) {
moveData.velocity.x = 0;
tempX = (currCol + 1) * Tile.SIZE - moveData.collisionBox.getWidth() % Tile.SIZE - 1;
framesSinceLastRightCollision = 0;
} else {
tempX += moveData.velocity.x;
}
}
return new Vec2D(tempX, tempY);
}
What should I change in this code to get natural movement?
My first guess is that the problem lies in that first if statement:
if (direction == Direction.LEFT && moving) {
getVelocity().x = -WALK_SPEED;
} else if (getVelocity().x < 0) {
getVelocity().x *= COEF_FRIC;
}
If the first thing is true, you're going to constantly be setting the velocity to walking pace, which doesn't make sense when your guy is swinging on a rope. He should be speeding up as he goes down and slowing down on the way up.
If the first thing is false, then since he is going left, you're definitely going to go into the else if statement, and he'll be slowed down by friction. I don't see where you set that, but it seems to still be the friction he has on the ground, which would seem to explain why he's all stuttery and looks more like he's sliding than falling.
You might want to add different states instead of just "moving", (perhaps jumping, swinging, walking, running, stopped) and vary how he behaves while doing each of those things.
in the example which is given in the book "Computer Graphics for Java Programmers, Second Edition"
there is transformation with view vector
private void shiftToOrigin()
{ float xwC = 0.5F * (xMin + xMax),
ywC = 0.5F * (yMin + yMax),
zwC = 0.5F * (zMin + zMax);
int n = w.size();
for (int i=1; i<n; i++)
if (w.elementAt(i) != null)
{ ((Point3D)w.elementAt(i)).x -= xwC;
((Point3D)w.elementAt(i)).y -= ywC;
((Point3D)w.elementAt(i)).z -= zwC;
}
float dx = xMax - xMin, dy = yMax - yMin, dz = zMax - zMin;
rhoMin = 0.6F * (float) Math.sqrt(dx * dx + dy * dy + dz * dz);
rhoMax = 1000 * rhoMin;
rho = 3 * rhoMin;
}
private void initPersp()
{
float costh = (float)Math.cos(theta),
sinth = (float)Math.sin(theta),
cosph = (float)Math.cos(phi),
sinph = (float)Math.sin(phi);
v11 = -sinth; v12 = -cosph * costh; v13 = sinph * costh;
v21 = costh; v22 = -cosph * sinth; v23 = sinph * sinth;
v32 = sinph; v33 = cosph;
v43 = -rho;
}
float eyeAndScreen(Dimension dim)
// Called in paint method of Canvas class
{ initPersp();
int n = w.size();
e = new Point3D[n];
vScr = new Point2D[n];
float xScrMin=1e30F, xScrMax=-1e30F,
yScrMin=1e30F, yScrMax=-1e30F;
for (int i=1; i<n; i++)
{
Point3D P = (Point3D)(w.elementAt(i));
if (P == null)
{ e[i] = null; vScr[i] = null;
}
else
{ float x = v11 * P.x + v21 * P.y;
float y = v12 * P.x + v22 * P.y + v32 * P.z;
float z = v13 * P.x + v23 * P.y + v33 * P.z + v43;
Point3D Pe = e[i] = new Point3D(x, y, z);
float xScr = -Pe.x/Pe.z, yScr = -Pe.y/Pe.z;
vScr[i] = new Point2D(xScr, yScr);
if (xScr < xScrMin) xScrMin = xScr;
if (xScr > xScrMax) xScrMax = xScr;
if (yScr < yScrMin) yScrMin = yScr;
if (yScr > yScrMax) yScrMax = yScr;
}
}
float rangeX = xScrMax - xScrMin, rangeY = yScrMax - yScrMin;
d = 0.95F * Math.min(dim.width/rangeX, dim.height/rangeY); //d burada
imgCenter = new Point2D(d * (xScrMin + xScrMax)/2,
d * (yScrMin + yScrMax)/2);
for (int i=1; i<n; i++)
{
if (vScr[i] != null){vScr[i].x *= d; vScr[i].y *= d;}
}
return d * Math.max(rangeX, rangeY);
// Maximum screen-coordinate range used in CvHLines for HP-GL
}
here float xScr = -Pe.x/Pe.z, yScr = -Pe.y/Pe.z; when we divide x and y with z that give as a perspective view if we don't divide it with z the view will be parallel(orthogonal)
this is OK but if we want to this parallel view coordinates with hidden line algorithm in same book it calculates lines wrongly. I couldn't find where problem is. What can cause this problem?
here hidden line algorithm:
private void lineSegment(Graphics g, Point3D Pe, Point3D Qe,
Point2D PScr, Point2D QScr, int iP, int iQ, int iStart)
{
double u1 = QScr.x - PScr.x; //t
double u2 = QScr.y - PScr.y; //t
double minPQx = Math.min(PScr.x, QScr.x);//t
double maxPQx = Math.max(PScr.x, QScr.x);//t
double minPQy = Math.min(PScr.y, QScr.y);//t
double maxPQy = Math.max(PScr.y, QScr.y);//t
double zP = Pe.z; //t
double zQ = Qe.z; //t
double minPQz = Math.min(zP, zQ);//t
Point3D[] e = obj.getE();//e eye
Point2D[] vScr = obj.getVScr(); //vscr screen
for (int i=iStart; i<nTria; i++)//t
{
Tria t = tr[i];
int iA = t.iA, iB = t.iB, iC = t.iC;
Point2D AScr = vScr[iA], BScr = vScr[iB], CScr = vScr[iC];
// 1. Minimax test for x and y screen coordinates: //t
if (maxPQx <= AScr.x && maxPQx <= BScr.x && maxPQx <= CScr.x
|| minPQx >= AScr.x && minPQx >= BScr.x && minPQx >= CScr.x
|| maxPQy <= AScr.y && maxPQy <= BScr.y && maxPQy <= CScr.y
|| minPQy >= AScr.y && minPQy >= BScr.y && minPQy >= CScr.y)
continue;
// 2. Test if PQ is an edge of ABC: //t
if ((iP == iA || iP == iB || iP == iC) &&
(iQ == iA || iQ == iB || iQ == iC))
continue;
// 3. Test if PQ is clearly nearer than ABC://t
Point3D Ae = e[iA], Be = e[iB], Ce = e[iC];
double zA = Ae.z, zB = Be.z, zC = Ce.z;
if (minPQz >= zA && minPQz >= zB && minPQz >= zC)
continue;
// 4. Do P and Q (in 2D) lie in a half plane defined
// by line AB, on the side other than that of C?
// Similar for the edges BC and CA.
double eps = 0.1; // Relative to numbers of pixels //t
if (Tools2D.area2(AScr, BScr, PScr) < eps &&
Tools2D.area2(AScr, BScr, QScr) < eps ||
Tools2D.area2(BScr, CScr, PScr) < eps &&
Tools2D.area2(BScr, CScr, QScr) < eps ||
Tools2D.area2(CScr, AScr, PScr) < eps &&
Tools2D.area2(CScr, AScr, QScr) < eps)
continue;
// 5. Test (2D) if A, B and C lie on the same side
// of the infinite line through P and Q://t
double PQA = Tools2D.area2(PScr, QScr, AScr);
double PQB = Tools2D.area2(PScr, QScr, BScr);
double PQC = Tools2D.area2(PScr, QScr, CScr);
if (PQA < +eps && PQB < +eps && PQC < +eps ||
PQA > -eps && PQB > -eps && PQC > -eps)
continue;
// 6. Test if neither P nor Q lies behind the
// infinite plane through A, B and C://t
int iPol = refPol[i];
Polygon3D pol = (Polygon3D)polyList.elementAt(iPol);
double a = pol.getA(), b = pol.getB(), c = pol.getC(),
h = pol.getH(), eps1 = 1e-5 * Math.abs(h),
hP = a * Pe.x + b * Pe.y + c * Pe.z,
hQ = a * Qe.x + b * Qe.y + c * Qe.z;
if (hP > h - eps1 && hQ > h - eps1)
continue;
// 7. Test if both P and Q behind triangle ABC://t
boolean PInside =
Tools2D.insideTriangle(AScr, BScr, CScr, PScr);
boolean QInside =
Tools2D.insideTriangle(AScr, BScr, CScr, QScr);
if (PInside && QInside)
return;
// 8. If P nearer than ABC and inside, PQ visible;//t
// the same for Q:
double h1 = h + eps1;
boolean PNear = hP > h1, QNear = hQ > h1;
if (PNear && PInside || QNear && QInside)
continue;
// 9. Compute the intersections I and J of PQ
// with ABC in 2D.
// If, in 3D, such an intersection lies in front of
// ABC, this triangle does not obscure PQ.
// Otherwise, the intersections lie behind ABC and
// this triangle obscures part of PQ:
double lambdaMin = 1.0, lambdaMax = 0.0;
for (int ii=0; ii<3; ii++)
{ double v1 = BScr.x - AScr.x, v2 = BScr.y - AScr.y,
w1 = AScr.x - PScr.x, w2 = AScr.y - PScr.y,
denom = u2 * v1 - u1 * v2;
if (denom != 0)
{ double mu = (u1 * w2 - u2 * w1)/denom;
// mu = 0 gives A and mu = 1 gives B.
if (mu > -0.0001 && mu < 1.0001)
{ double lambda = (v1 * w2 - v2 * w1)/denom;
// lambda = PI/PQ
// (I is point of intersection)
if (lambda > -0.0001 && lambda < 1.0001)
{ if (PInside != QInside &&
lambda > 0.0001 && lambda < 0.9999)
{ lambdaMin = lambdaMax = lambda;
break;
// Only one point of intersection
}
if (lambda < lambdaMin) lambdaMin = lambda;
if (lambda > lambdaMax) lambdaMax = lambda;
}
}
}
Point2D temp = AScr; AScr = BScr;
BScr = CScr; CScr = temp;
}
float d = obj.getD();
if (!PInside && lambdaMin > 0.001)
{ double IScrx = PScr.x + lambdaMin * u1,
IScry = PScr.y + lambdaMin * u2;
// Back from screen to eye coordinates:
double zI = 1/(lambdaMin/zQ + (1 - lambdaMin)/zP),
xI = -zI * IScrx / d, yI = -zI * IScry / d;
if (a * xI + b * yI + c * zI > h1) continue;
Point2D IScr = new Point2D((float)IScrx, (float)IScry);
if (Tools2D.distance2(IScr, PScr) >= 1.0)
lineSegment(g, Pe, new Point3D(xI, yI, zI), PScr,
IScr, iP, -1, i + 1);
}
if (!QInside && lambdaMax < 0.999)
{ double JScrx = PScr.x + lambdaMax * u1,
JScry = PScr.y + lambdaMax * u2;
double zJ =
1/(lambdaMax/zQ + (1 - lambdaMax)/zP),
xJ = -zJ * JScrx / d, yJ = -zJ * JScry / d;
if (a * xJ + b * yJ + c * zJ > h1) continue;
Point2D JScr = new Point2D((float)JScrx, (float)JScry);
if (Tools2D.distance2(JScr, QScr) >= 1.0)
lineSegment(g, Qe, new Point3D(xJ, yJ, zJ),
QScr, JScr, iQ, -1, i + 1);
}
return;
// if no continue-statement has been executed
}
drawLine(g, PScr.x, PScr.y, QScr.x, QScr.y);
}
}
private void gotoPos()
{
spaceX = x2 - x;
spaceY = y2 - y;
if (Math.abs(spaceX) >= Math.abs(spaceY)) {
xSpeed = Math.round(spaceX * (3/Math.abs(spaceX)));
ySpeed = Math.round(spaceY * (3/Math.abs(spaceX)));
}
With this code I want to move an object to the position x2 and y2. x and y is the current position of the object. spaceX is the space that is between the object and the x position it should go to. The same for spaceY.
But I don't want the object to move more than 3 Pixels per draw.
Example: object position: x = 35, y = 22
Point it should go to: x2 = 79, y2 = 46
space between them: spaceX = 79-35 = 44, spaceY = 46-22 = 24
spaceX is bigger then spaceY so:
xSpeed = 44 * (3/44) = 3, ySpeed = 24 * (3/44) = 1.63 = 2
But it does not work like this. When I start the app the object does not go to x2 and y2.
If I change
xSpeed = spaceX;
ySpeed = spaceY;
The object moves to the position but I do not want it to go there instantly
Complete Code:
public class Sprite
{
private boolean walking = true;
private int actionWalk = 0;
private Random rnd;
private int checkIfAction;
private int nextAction = 0;
static final private int BMP_COLUMNS = 4;
static final private int BMP_ROWS = 4;
private int[] DIRECTION_TO_SPRITE_SHEET = { 1, 0, 3, 2 };
public int x=-1;
private int y=-1;
public int xSpeed;
private int ySpeed;
private int width;
private int height;
private int bottomSpace;
private Bitmap bmp;
private GameView theGameView;
private int currentFrame=0;
private int x2, y2;
private boolean isTouched;
private int spaceX, spaceY;
D
public Sprite(GameView theGameView, Bitmap bmp)
{
this.theGameView = theGameView;
this.bmp = bmp;
this.width = bmp.getWidth() / BMP_COLUMNS;
this.height = bmp.getHeight() / BMP_ROWS;
rnd = new Random();
xSpeed = 0;
ySpeed = 0;
}
public void shareTouch(float xTouch, float yTouch)
{
x2 = (int) xTouch;
y2 = (int) yTouch;
isTouched = true;
}
private void gotoPos()
{
spaceX = x2 - x;
spaceY = y2 - y;
if (Math.abs(spaceX) >= Math.abs(spaceY)) {
xSpeed = Math.round(spaceX * (3/Math.abs(spaceX)));
ySpeed = Math.round(spaceY * (3/Math.abs(spaceX)));
}
else {
xSpeed = spaceX;
ySpeed = spaceY;
}
}
D
private void bounceOff()
{
bottomSpace = theGameView.getHeight() - y;
if (x > theGameView.getWidth() - (width * theGameView.getDensity()) - xSpeed - bottomSpace / 2 || x + xSpeed < bottomSpace / 2)
{
xSpeed = -xSpeed;
}
x = x + xSpeed;
if (y > theGameView.getHeight() - (height * theGameView.getDensity()) - ySpeed || y + ySpeed < theGameView.getHeight() / 2)
{
ySpeed = -ySpeed;
}
y = y + ySpeed;
currentFrame = ++currentFrame % BMP_COLUMNS;
}
d
public void onDraw(Canvas canvas)
{
if (x == -1)
{
x = (theGameView.getWidth() / 2);
y = (theGameView.getHeight() / 2 + theGameView.getHeight() / 4);
}
if (isTouched == true)
{
gotoPos();
}
/* if (nextAction == 100)
{
action();
nextAction = 0;
}
nextAction += 1;*/
bounceOff();
int sourceX, sourceY;
if (walking == true)
{
sourceX = currentFrame * width;
}
else
{
sourceX = 0;
}
sourceY = getAnimationRow() * height;
Rect source = new Rect(sourceX, sourceY, sourceX + width, sourceY + height);
Rect destine = new Rect(x, y, (int) (x + (width * theGameView.getDensity())), (int) (y + (height * theGameView.getDensity())));
canvas.drawBitmap(bmp, source, destine, null);
}
d
private int getAnimationRow()
{
double directionDouble = (Math.atan2(xSpeed, ySpeed) / (Math.PI / 2) + 2);
int spriteDir = (int) Math.round(directionDouble) % BMP_ROWS;
return DIRECTION_TO_SPRITE_SHEET[spriteDir];
}
}
Simple problem: you use integer arithmetic and don't understand this:
spaceX * (3/Math.abs(spaceX))
The result will be 0 in nearly all cases as 3/x with x > 3 is 0 all the time.
To make your program working use either floating point arithmetic or rewrite your formulas to work as expected.
To use floating point arithetic you have to change to
spaceX * (3.0/Math.abs(spaceX))
assuming that you variable spaceX is also floating point.
Also you can use
(spaceX * 3) / Math.abs(spaceX)
if you want to stay with integers (what I suppose).
Given points a Vector2d(x, y) and b Vector2d(x2, y2)-
Create a vector V from a to b by subtracting b from a as you did. Normalize vector V into a unit vector and multiply it with the distance you want. Then add the resulting vector to point a.
On update:
a.add(b.subtract(a).norm().multiply(d));
Depending on your vector implementation, modify properly the above pseudo code.
There is a logical fallacy in your code: what if Math.abs(spaceX) < Math.abs(spaceY))? Then your object would not move at all.
What you calculate, 'x-distance / y-distance', is usually considered angle, not speed. Speed is 'distance / time'. You can calculate the distance, and you should decide on a reasonable speed for your object. Since you know your fps -- 20 --, you can then calculate how many pixels your object needs to move in each frame.
how do I calculate the font size of a TextView so that always occupy a certain percentage of the screen?
now I spit it out:
.....
densityNormal = Float.parseFloat("1.0");
densitySub = Float.parseFloat("0.75");
densityIper = Float.parseFloat("1.5");
densityExtra = Float.parseFloat("2.0");
.....
textviewSample.setTextSize(getHeightPercentage(context,30));
.....
private float getHeightPercentage(Context context, int percentage) {
if (percentage > 0 && percentage < 100) {
float appHeight = context.getApplicationContext().getResources()
.getDisplayMetrics().heightPixels;
float appSPDensity = context.getApplicationContext().getResources()
.getDisplayMetrics().scaledDensity;
if (Float.compare(appSPDensity, densitySub) == 0) {
appHeight = appHeight + ((appHeight * 25) / 100);
} else if (Float.compare(appSPDensity, densityIper) == 0) {
appHeight = ((appHeight * 50) / 100) - appHeight;
} else if (Float.compare(appSPDensity, densityExtra) == 0) {
appHeight = ((appHeight * 200) / 100) - appHeight;
}
return new Float((appHeight * percentage) / 100);
} else
return -1;
}
but I can not integrate the different density of the screen,have you any suggestions?8y3