I had written method to get the pixels from dip but it is not working. It give me runtime error.
Actually I was running this method in separate class and initialized in my Activity class
Board board = new Board(this);
board.execute(URL);
This code runs asynchronously. Please help me.
public float getpixels(int dp){
//Resources r = boardContext.getResources();
//float px = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpis, r.getDisplayMetrics());
final float scale = this.boardContext.getResources().getDisplayMetrics().density;
int px = (int) (dp * scale + 0.5f);
return px;
}
Try this:
Java
public static float dipToPixels(Context context, float dipValue) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dipValue, metrics);
}
Kotlin
fun Context.dipToPixels(dipValue: Float) =
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dipValue, resources.displayMetrics)
You can add the dp value in dimen.xml and use
int pixels = getResources().getDimensionPixelSize(R.dimen.idDimension);
It's easier...
The formula is: px = dp * (dpi / 160), for having on a 160 dpi screen. See Convert dp units to pixel units for more information.
You could try:
public static int convertDipToPixels(float dips) {
return (int) (dips * appContext.getResources().getDisplayMetrics().density + 0.5f);
}
Hope this helps...
Try this for without passing context:
public static float dipToPixels(float dipValue) {
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dipValue,
Resources.getSystem().getDisplayMetrics()
);
}
Related
When I run the following code, my sketch draws as expected:
void draw() {
int[] nextColor = getNextColor();
stroke(nextColor[0], nextColor[1], nextColor[2]);
float[] nextPoint = getNextLocation();
point(nextPoint[0], nextPoint[1]);
}
However, if I add the fourth argument for the alpha transparency value to stroke(), nothing is drawn to the canvas at all:
float alpha = 0.8;
void draw() {
int[] nextColor = getNextColor();
stroke(nextColor[0], nextColor[1], nextColor[2], alpha);
float[] nextPoint = getNextLocation();
point(nextPoint[0], nextPoint[1]);
}
So far I have tried setting the alpha value to 1.0 directly in the argument (rather than using a variable) to be sure that I wasn't accidentally setting it to 0 somewhere. I have also double checked the documentation for stroke() and there is indeed an overridden version matching my arguments.
What am I doing incorrectly?
Here is all of my code in case there is something elsewhere that should be considered. Thank you.
import java.util.Random;
Random generator;
int meanX, stdevX, meanY, stdevY;
int meanR, meanG, meanB, stdevR, stdevG, stdevB;
float alpha = 0.8;
// returns two random numbers (for x, y, coordinates)
float[] getNextLocation() {
float[] retArr = new float[2];
retArr[0] = (float) (generator.nextGaussian() * stdevX + meanX);
retArr[1] = (float) (generator.nextGaussian() * stdevY + meanY);
return retArr;
}
int[] getNextColor() {
int[] retArr = new int[3];
retArr[0] = (int) (generator.nextGaussian() * stdevR + meanR);
retArr[1] = (int) (generator.nextGaussian() * stdevG + meanG);
retArr[2] = (int) (generator.nextGaussian() * stdevB + meanB);
return retArr;
}
void setup() {
background(255);
size(500, 500);
generator = new Random();
strokeWeight(10);
// play around with these
meanX = width/6;
stdevX = width/8;
meanY = height/2;
stdevY = height/30;
meanR = 224;
stdevR = 20;
meanG = 169;
stdevG = 60;
meanB = 20;
stdevB = 5;
}
void draw() {
int[] nextColor = getNextColor();
stroke(nextColor[0], nextColor[1], nextColor[2]);
float[] nextPoint = getNextLocation();
point(nextPoint[0], nextPoint[1]);
}
You are misunderstanding what the value of alpha is.
Alpha means transparency.
Alpha values range from 0 to 255, with 0 being completely transparent (i.e., 0% opaque) and 255 completely opaque (i.e., 100% opaque).
So in your case, when you set your alpha to 0.8, you don't see anything because it's very close to transparent. When you do not set the alpha, it is by default 100% opaque, so you see the drawing.
Take a look here if interested to know more.
Good day, I am beginning to learn Java and one of the first projects that I thought might help me to begin learning is by designing a watch face for WearOS, I am an artist/illustrator (currently going back to school to learn computer programming) by birth and school, so I am currently attempting work that I have some idea about.
My question is this. I have designed and implemented bitmaps that are rotating for the watch's hands, and have tried to center them with "mCenterX and Y" and have even manually tried to center them with canvas.translate, and entering in coordinates. Sorry if this is an absolute newbie question, but I have been Googling and attempting for at least a week. (Would include image of floating hands, but can't embed.)
The "Hour Hand" is the only one that I have currently working, and I only was able to do that with manually entering the coordinates with canvas.translate. The other hands will come into frame every-once-in-a-while then float out of frame, rotating around some "unknown" center point.
Code is below: (I have included all code pertaining to the bitmaps for the hour/minute/second hands, to see if I have something that is conflicting. I am using bits of code from various projects, which probably explains the off-centeredness, but I don't have the knowledge yet to grasp why, which is my ultimate goal here.)
Thank you for looking and replying! If you need additional information, let me know.
private class Engine extends CanvasWatchFaceService.Engine {
private static final float HOUR_STROKE_WIDTH = 5f;
private static final float MINUTE_STROKE_WIDTH = 3f;
private static final float SECOND_TICK_STROKE_WIDTH = 2f;
private static final float CENTER_GAP_AND_CIRCLE_RADIUS = 4f;
private static final int SHADOW_RADIUS = 6;
/* Handler to update the time once a second in interactive mode. */
private final Handler mUpdateTimeHandler = new EngineHandler(this);
private Calendar mCalendar;
private final BroadcastReceiver mTimeZoneReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
mCalendar.setTimeZone(TimeZone.getDefault());
invalidate();
}
};
private boolean mRegisteredTimeZoneReceiver = false;
private boolean mMuteMode;
private float mCenterX;
private float mCenterY;
private int mWatchHandColor;
private int mWatchHandHighlightColor;
private int mWatchHandShadowColor;
private Paint mHourPaint;
private Paint mMinutePaint;
private Paint mSecondPaint;
private Paint mTickAndCirclePaint;
private Paint mBackgroundPaint;
private Bitmap mHourBitmap;
private Bitmap mMinuteBitmap;
private Bitmap mSecondBitmap;
private Bitmap mBackgroundBitmap;
private Bitmap mGrayBackgroundBitmap;
private void initializeWatchFace() {
/* Set defaults for colors */
mWatchHandColor = Color.WHITE;
mWatchHandHighlightColor = Color.RED;
mWatchHandShadowColor = Color.BLACK;
mHourPaint = new Paint();
mHourPaint.setColor(mWatchHandColor);
mHourPaint.setStrokeWidth(HOUR_STROKE_WIDTH);
mHourPaint.setAntiAlias(true);
mHourPaint.setStrokeCap(Paint.Cap.ROUND);
mHourPaint.setShadowLayer(SHADOW_RADIUS, 0, 0, mWatchHandShadowColor);
mMinutePaint = new Paint();
mMinutePaint.setColor(mWatchHandColor);
mMinutePaint.setStrokeWidth(MINUTE_STROKE_WIDTH);
mMinutePaint.setAntiAlias(true);
mMinutePaint.setStrokeCap(Paint.Cap.ROUND);
mMinutePaint.setShadowLayer(SHADOW_RADIUS, 0, 0, mWatchHandShadowColor);
mSecondPaint = new Paint();
mSecondPaint.setColor(mWatchHandHighlightColor);
mSecondPaint.setStrokeWidth(SECOND_TICK_STROKE_WIDTH);
mSecondPaint.setAntiAlias(true);
mSecondPaint.setStrokeCap(Paint.Cap.ROUND);
mSecondPaint.setShadowLayer(SHADOW_RADIUS, 0, 0, mWatchHandShadowColor);
mTickAndCirclePaint = new Paint();
mTickAndCirclePaint.setColor(mWatchHandColor);
mTickAndCirclePaint.setStrokeWidth(SECOND_TICK_STROKE_WIDTH);
mTickAndCirclePaint.setAntiAlias(true);
mTickAndCirclePaint.setStyle(Paint.Style.STROKE);
mTickAndCirclePaint.setShadowLayer(SHADOW_RADIUS, 0, 0, mWatchHandShadowColor);
}
private void updateWatchHandStyle() {
if (mAmbient) {
mHourPaint.setColor(Color.WHITE);
mMinutePaint.setColor(Color.WHITE);
mSecondPaint.setColor(Color.WHITE);
mTickAndCirclePaint.setColor(Color.WHITE);
mHourPaint.setAntiAlias(false);
mMinutePaint.setAntiAlias(false);
mSecondPaint.setAntiAlias(false);
mTickAndCirclePaint.setAntiAlias(false);
mHourPaint.clearShadowLayer();
mMinutePaint.clearShadowLayer();
mSecondPaint.clearShadowLayer();
mTickAndCirclePaint.clearShadowLayer();
} else {
mHourPaint.setColor(mWatchHandColor);
mMinutePaint.setColor(mWatchHandColor);
mSecondPaint.setColor(mWatchHandHighlightColor);
mTickAndCirclePaint.setColor(mWatchHandColor);
mHourPaint.setAntiAlias(true);
mMinutePaint.setAntiAlias(true);
mSecondPaint.setAntiAlias(true);
mTickAndCirclePaint.setAntiAlias(true);
mHourPaint.setShadowLayer(SHADOW_RADIUS, 0, 0, mWatchHandShadowColor);
mMinutePaint.setShadowLayer(SHADOW_RADIUS, 0, 0, mWatchHandShadowColor);
mSecondPaint.setShadowLayer(SHADOW_RADIUS, 0, 0, mWatchHandShadowColor);
mTickAndCirclePaint.setShadowLayer(SHADOW_RADIUS, 0, 0, mWatchHandShadowColor);
}
#Override
public void onInterruptionFilterChanged(int interruptionFilter) {
super.onInterruptionFilterChanged(interruptionFilter);
boolean inMuteMode = (interruptionFilter == WatchFaceService.INTERRUPTION_FILTER_NONE);
/* Dim display in mute mode. */
if (mMuteMode != inMuteMode) {
mMuteMode = inMuteMode;
mHourPaint.setAlpha(inMuteMode ? 100 : 255);
mMinutePaint.setAlpha(inMuteMode ? 100 : 255);
mSecondPaint.setAlpha(inMuteMode ? 80 : 255);
invalidate();
}
}
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
super.onSurfaceChanged(holder, format, width, height);
/*
* Find the coordinates of the center point on the screen, and ignore the window
* insets, so that, on round watches with a "chin", the watch face is centered on the
* entire screen, not just the usable portion.
*/
mCenterX = width / 2f;
mCenterY = height / 2f;
/*
* Calculate lengths of different hands based on watch screen size.
*/
mSecondHandLength = (float) (mCenterX * 0.875);
sMinuteHandLength = (float) (mCenterX * 0.75);
sHourHandLength = (float) (mCenterX * 0.5);
/* Scale loaded background image (more efficient) if surface dimensions change. */
float scale = ((float) width) / (float) mBackgroundBitmap.getWidth();
mBackgroundBitmap = Bitmap.createScaledBitmap(mBackgroundBitmap,
(int) (mBackgroundBitmap.getWidth() * scale),
(int) (mBackgroundBitmap.getHeight() * scale), false);
float scale2 = ((float) width) / (float) mSecondBitmap.getWidth();
mSecondBitmap = Bitmap.createScaledBitmap(mSecondBitmap,
12,
222, false);
float scale3 = ((float) width) / (float) mHourBitmap.getWidth();
mHourBitmap = Bitmap.createScaledBitmap(mHourBitmap,
12,139,false);
float scale4 = ((float) width) / (float) mMinuteBitmap.getWidth();
mMinuteBitmap = Bitmap.createScaledBitmap(mMinuteBitmap,
12,
162, false);
private void drawWatchFace(Canvas canvas) {
/*
* Draw ticks. Usually you will want to bake this directly into the photo, but in
* cases where you want to allow users to select their own photos, this dynamically
* creates them on top of the photo.
*/
float innerTickRadius = mCenterX - 10;
float outerTickRadius = mCenterX;
for (int tickIndex = 0; tickIndex < 12; tickIndex++) {
float tickRot = (float) (tickIndex * Math.PI * 2 / 12);
float innerX = (float) Math.sin(tickRot) * innerTickRadius;
float innerY = (float) -Math.cos(tickRot) * innerTickRadius;
float outerX = (float) Math.sin(tickRot) * outerTickRadius;
float outerY = (float) -Math.cos(tickRot) * outerTickRadius;
canvas.drawLine(mCenterX + innerX, mCenterY + innerY,
mCenterX + outerX, mCenterY + outerY, mTickAndCirclePaint);
}
/*
* These calculations reflect the rotation in degrees per unit of time, e.g.,
* 360 / 60 = 6 and 360 / 12 = 30.
*/
final float seconds =
(mCalendar.get(Calendar.SECOND) + mCalendar.get(Calendar.MILLISECOND) / 1000f);
final float secondsRotation = seconds * 6f;
final float minutesRotation = mCalendar.get(Calendar.MINUTE) * 6f;
final float hourHandOffset = mCalendar.get(Calendar.MINUTE) / 2f;
final float hoursRotation = (mCalendar.get(Calendar.HOUR) * 30) + hourHandOffset;
/*
* Save the canvas state before we can begin to rotate it.
*/
canvas.save();
canvas.rotate(hoursRotation, mCenterX, mCenterY);
Matrix matrixHour = new Matrix();
matrixHour.setRotate(0, mCenterX, mCenterY);
canvas.translate(175, 68);
canvas.drawBitmap(mHourBitmap, matrixHour, mHourPaint);
canvas.rotate(minutesRotation - hoursRotation, mCenterX, mCenterY);
Matrix matrixMinute = new Matrix();
matrixMinute.setRotate(0, mCenterX, mCenterY);
canvas.translate(175, -60);
canvas.drawBitmap(mMinuteBitmap, matrixMinute, mMinutePaint);
/*
* Ensure the "seconds" hand is drawn only when we are in interactive mode.
* Otherwise, we only update the watch face once a minute.
*/
if (!mAmbient) {
canvas.rotate(secondsRotation - minutesRotation, mCenterX, mCenterY);
Matrix matrix = new Matrix();
matrixHour.setRotate(0, mCenterX, mCenterY);
canvas.translate(-175,35);
canvas.drawBitmap(mSecondBitmap, matrix, mSecondPaint);
}
/* Restore the canvas' original orientation. */
canvas.restore();
}
I am new to LWJGL but am slowly learning. I was wanting to make a square that rotated when you pressed the key. Like d rotates it 90 degrees as you can tell below, but when I use glRotatef(); it gives me an error and I don't know why. There error tells me I need to create a method for it, I know I don't need to though. Anything helps!
public class MainPlayer {
private Draw draw;
private int rotation;
private float WIDTH = (float) (Display.getWidth() * 0.1);
private float HEIGHT = (float) (WIDTH / 2);
private float x = Display.getWidth() / 2 - WIDTH / 2;
private float y = Display.getHeight() / 2 - HEIGHT / 2;
public MainPlayer(){
draw = new Draw(1.0f, 1.0f, 1.0f, WIDTH, HEIGHT);
}
public void update(){
}
public void render(){
glTranslatef(x, y, 0);
glRotatef(rotation,0,0,1);
draw.render();
}
public void getInput(){
if(Keyboard.isKeyDown(Keyboard.KEY_W)){
rotation = 0;
}
if(Keyboard.isKeyDown(Keyboard.KEY_S)){
rotation = 180;
}
if(Keyboard.isKeyDown(Keyboard.KEY_A)){
rotation = 270;
}
if(Keyboard.isKeyDown(Keyboard.KEY_D)){
rotation = 90;
}
}
}
You create an int rotation and I assume your render() loops the whole time, and you only set rotation in getInput().
So I am assuming that you should declare it as int rotation = 0.
glRotatef() is a OpenGL call to rotate objects, just like glTranslatef() moves them. glRotatef() does it in the same way.
glRotatef(AngleOfRotationf, 0, 1, 0) would rotate it horisontally, like in this video i just made: http://www.youtube.com/watch?v=SHsssrj9qr8& uses that line to rotate a ship.
Also in that video i demonstrated moving it with glTranslatef().
To use it you must use GL11.glRotatef(), or import static org.lwjgl.opengl.GL11.*;
That probably means that you haven't statically imported glRotatef
Either use
GL11.glRotatef(rotation, 0, 0, 1);
or import it at the beginning of your program with
import static org.lwjgl.opengl.GL11.glRotatef
Problem: I have limited the maximum and minimum zoom, everything is OK, but:
If I try to zoom less than the minimum, then to zoom+, it is necessary to do the same amount of motion in the opposite direction. The same is with zoom+. And on the technical side, it looks like this:
values[Matrix.MSCALE_X] changes, despite the fact that before this is:
m.reset();
m.setScale(sx1, sx1);
where sx1 is a FIXED value. Here is my code:
public boolean onScale(ScaleGestureDetector detector) {
try{
saved_gest_scale = newScale;
newScale *= detector.getScaleFactor();
scaleFactor = newScale / oldScale;
target_img_width *= 1/scaleFactor;
if (target_img_width > width)//limit max zoom
{
//fit on screen:
m = new Matrix();
m.reset();
float w_coef = img_width / width;
float sx1 = 1/w_coef;
m.setScale(sx1, sx1);
///========
//apply new size
float sx2 = target_img_width/width;
sx2 = 1/sx2;
m.setScale(sx2, sx2);
float[] values = new float[9];
m.getValues(values);
//center image:
float globalX = values[Matrix.MTRANS_X];
float globalY = values[Matrix.MTRANS_Y];
float wid = values[Matrix.MSCALE_X]*img_width;
float heig = values[Matrix.MSCALE_Y]*img_height;
m.postTranslate(width/2 - wid/2, height/2-heig/2);
if (wid <= width)//limit min-zoom
{
newScale = sx1;
m = new Matrix();
m.reset();
m.setScale(sx1, sx1);
wid = sx1*img_width;
heig = sx1*img_height;
debug.setText(wid + "<width" + "mx=" + values[Matrix.MSCALE_X] );
m.postTranslate(width/2 - wid/2, height/2-heig/2);
}
iw.setImageMatrix(m);
}
oldScale = newScale;
}catch (Exception xx)
{
debug.setText("detector "+ xx.toString());
}
return true;
}
Please help.
Use one parameter scale wich is changed in the onScale method. Also use two constants minScale and maxScale. In the onScale method check if new scale fits in the acceptable interval, and if it does - redraw the image with new scale.
Right now your code is in mess. Somehow limit min-zoom check is located inside limit max zoom, but scaling methods are spread all around. Thus it's very unclean when a new scale becomes current and why it is working wrong.
I'm trying to have an image scale to a certain size depending on the horizontal size sent to an update function, but the following code doesnt seem to size the image correctly.
EDIT: The code:
public class GlassesView extends View {
private Paint paint;
private BitmapFactory.Options options;
private Bitmap bitmapOrg;
private Bitmap target;
private Bitmap bitmapRev;
private Bitmap resizedBitmap;
private int currY;
public int glassesX;
public int glassesY;
public float glassesSizeX;
public float glassesSizeY;
private boolean drawGlasses;
private boolean glassesMirrored;
public GlassesView(Context context) {
super(context);
paint = new Paint();
paint.setDither(false);
paint.setAntiAlias(false);
options = new BitmapFactory.Options();
options.inDither = false;
options.inScaled = false;
bitmapOrg = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(),
R.drawable.micro_glasses, options), 32, 5, false);
bitmapRev = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(),
R.drawable.glasses_reverse, options), 32, 5, false);
drawGlasses = false;
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(target, 0, 0, paint);
boolean moving = currY < glassesY;
if (moving) {
currY++;
}
if (drawGlasses) {
int newWidth = resizedBitmap.getWidth();
int newHeight = resizedBitmap.getHeight();
Paint bluey = new Paint();
bluey.setColor(Color.argb(64, 0, 0, 255));
canvas.drawRect(new Rect(glassesX, currY, glassesX + newWidth,
currY + newHeight), bluey);
canvas.drawBitmap(resizedBitmap, glassesX, currY, paint);
}
if (moving) {
invalidate();
}
}
public void drawGlasses(int x1, int x2, int y, boolean mirror) {
drawGlasses = true;
glassesMirrored = mirror;
if (!mirror) {
glassesSizeX = (float) (x2 - x1) / (float) (25 - 16);
glassesSizeY = glassesSizeX;
glassesY = y - (int)(1*glassesSizeX);
glassesX = (int) (x1 - (glassesSizeX * 16));
} else {
glassesSizeX = (float) (x1 - x2) / (float) (25 - 16);
glassesSizeY = glassesSizeX;
glassesY = y - (int)(1*glassesSizeX);
glassesX = (int) (x1 - (glassesSizeX * 16));
}
currY = -1;
if (!glassesMirrored) {
resizedBitmap = Bitmap.createScaledBitmap(bitmapOrg,
(int) (bitmapOrg.getWidth() * glassesSizeX),
(int) (bitmapOrg.getHeight() * glassesSizeY), false);
} else {
resizedBitmap = Bitmap.createScaledBitmap(bitmapRev,
(int) (bitmapRev.getWidth() * glassesSizeX),
(int) (bitmapRev.getHeight() * glassesSizeY), false);
}
}
public void setTargetPic(Bitmap targetPic) {
target = targetPic;
}
}
The result. (The blue rectangle being the bounding box of the image's intended size)
Which part am I going wrong at?
EDIT 2:
Here are the glasses:
EDIT 3:
Out of curiousity, I ran it on my actual phone, and got a much different result, the image was stretched passed the intended blue box.
EDIT 4:
I tried running the app on a few emulators to see if it was an Android version incompatibility thing, but they all seemed to work perfectly. The scaling issue only occurs on my phone (Vibrant, rooted, CM7) and my cousin's (Droid, also rooted). These are the only physical devices I have tested on, but they both seem to have the same issue.
I'd really appreciate if someone could help me out here, this is a huge roadblock in my project and no other forums or message groups are responding.
EDIT 5:
I should mention that in update 4, the code changed a bit, which fixed the problem in the emulators as I stated, but doesn't work on physical devices. Changes are updated in the code above. *desperate for help* :P
EDIT 6:
Yet another update, I tested the same code on my old G1, and it works perfectly as expected. I have absolutely no clue now.
have you been using the /res/drawable-nodpi/ directory to store your images?
Apparently if you use the /drawable-ldpi/, /drawable-mdpi/ or /drawable-hdpi/ folders, Android will apply scaling to the image when you load it depending on the device. The reason your G1 may work is that it may not require any scaling depending on the folder you used.
Also, your IMGUR links are broken... also your code doesn't seem correct... you call DrawGlasses with no arguments.
Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0, glassesWidth,
glassesHeight, matrix, false);
Change the last parameter from false to true.
you can have a try.
The follow is i used zoom in method by scale:
private void small() {
int bmpWidth=bmp.getWidth();
int bmpHeight=bmp.getHeight();
Log.i(TAG, "bmpWidth = " + bmpWidth + ", bmpHeight = " + bmpHeight);
/* 设置图片缩小的比例 */
double scale=0.8;
/* 计算出这次要缩小的比例 */
scaleWidth=(float) (scaleWidth*scale);
scaleHeight=(float) (scaleHeight*scale);
/* 产生reSize后的Bitmap对象 */
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizeBmp = Bitmap.createBitmap(bmp,0,0,bmpWidth,
bmpHeight,matrix,true);
Found what was wrong. The image has to be in a folder called "drawable-nodpi", otherwise it will be scaled depending on DPI.