I want to show the value of the current progress point in the thumb of an Android SeekBar. This is what I have tried so far:
SeekBar progBar = (SeekBar)FindViewById(Resource.Id.seekBar1);
progBar.ProgressChanged += (object sender, SeekBar.ProgressChangedEventArgs e) =>
{
if (e.FromUser)
{
Drawable d = ContextCompat.GetDrawable(this, Resource.Drawable.thumb);
Bitmap bitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.thumb);
Bitmap bmp = bitmap.Copy(Bitmap.Config.Argb8888, true);// this line gives me a System.NullReferenceException: Object reference not set to an instance of an object. error
Canvas c = new Canvas(bmp);
Canvas c = new Canvas(bmp);
string text = Integer.ToString(progBar.Progress);
Paint p = new Paint();
p.SetTypeface(Typeface.DefaultBold);
p.TextSize = 14;
p.Color = Color.White;
int width = (int)p.MeasureText(text);
int yPos = (int)((c.Height / 2) - ((p.Descent() + p.Ascent()) / 2));
c.DrawText(text, (bmp.Width - width) / 2, yPos, p);
progBar.SetThumb(new BitmapDrawable(Resources, bmp));
}
};
Then when I got the type of Drawable d, it's a Gradient Drawable. I researched but I couldn't find a way to convert a gradient Drawable to bitmap.
Drawable d = ContextCompat.GetDrawable(this, Resource.Drawable.thumb);
Canvas c = new Canvas();
Bitmap bitmap = Bitmap.CreateBitmap(d.IntrinsicWidth, d.IntrinsicHeight, Bitmap.Config.Argb8888);
c.SetBitmap(bitmap);
d.SetBounds(0, 0, d.IntrinsicWidth, d.IntrinsicHeight);
d.Draw(c);
//Bitmap bmp = bitmap.Copy(Bitmap.Config.Argb8888, true);
string text = Integer.ToString(progress) + "%";
Paint p = new Paint();
p.SetTypeface(Typeface.CreateFromAsset(Assets, "fonts/Brandon_bld.otf"));
p.TextSize = 18;
p.Color = Color.White;
int width = (int)p.MeasureText(text);
int yPos = (int)((c.Height / 2) - ((p.Descent() + p.Ascent()) / 2));
c.DrawText(text, (bitmap.Width - width) / 2, yPos, p);
progBar.SetThumb(new BitmapDrawable(Resources, bitmap));
using the canvas to create the bitmap worked
Related
How can we check selected language support on the Android device? or How to get currently supported language in Android device
I have created one method for checking particular language supported or not.
public static boolean isLanSupported(Context context, String text) {
final int WIDTH_PX = 200;
final int HEIGHT_PX = 80;
int w = WIDTH_PX, h = HEIGHT_PX;
Resources resources = context.getResources();
float scale = resources.getDisplayMetrics().density;
Bitmap.Config conf = Bitmap.Config.ARGB_8888;
Bitmap bitmap = Bitmap.createBitmap(w, h, conf);
Bitmap orig = bitmap.copy(conf, false);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.rgb(0, 0, 0));
paint.setTextSize((int) (14 * scale));
// draw text to the Canvas
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
int x = (bitmap.getWidth() - bounds.width()) / 2;
int y = (bitmap.getHeight() + bounds.height()) / 2;
canvas.drawText(text, x, y, paint);
boolean res = !orig.sameAs(bitmap);
orig.recycle();
bitmap.recycle();
return res;
}
following way to call a method
isLanSupported(getActivity(),"ગુજરાતી")
isLanSupported(getActivity(),"हिंदी")
isLanSupported(getActivity(),"English")
You can get the default language with de Locale object
Locale.getDefault() for the default, and Locale.getAvailableLocales() for available langages.
(See this other post)
I am trying to set up a segmented circle inside another segmented circle using a Canavs in Android. I orginaly was using draw.Arc() but I need to use a lower API. I am using an ArchShape to create an arc, for the most part it works but when setting padding on the second circle, the padding isn't taking effect.
This is the first circle, works as expected.
When drawing the second circle it overrides the first, even with padding on.
I tried offsetting the padding on the re-size for the second one and the padding isn't working. But you can see both are drawn.
This is my code with the offset padding on the re-size.
Bitmap b;
Canvas c;
#Override
protected void onStart() {
super.onStart();
b = Bitmap.createBitmap(SIZE, SIZE, Bitmap.Config.ARGB_8888);
c = new Canvas(b);
Paint p1 = new Paint();
Paint p2 = new Paint();
p1.setFlags(Paint.ANTI_ALIAS_FLAG);
p2.setFlags(Paint.ANTI_ALIAS_FLAG);
p1.setColor(Color.BLACK);
p2.setColor(Color.RED);
SegmentCircle(0, p1, p2);
p1.setColor(Color.GREEN);
p2.setColor(Color.BLUE);
SegmentCircle(50, p1, p2);
ImageView imageView = (ImageView) findViewById(R.id.imageView);
imageView.setImageBitmap(b);
}
private final static int SIZE = 500;
private void SegmentCircle(int padding, Paint p1, Paint p2){
for (int i = 0; i < 20; i++) {
if ((i % 2) == 0){
ArcShape shape = new ArcShape(i * 18, 18);
ShapeDrawable d = new ShapeDrawable(shape);
shape.resize(SIZE - (padding / 2), SIZE - (padding / 2));
d.setPadding(padding,padding,padding,padding);
shape.draw(c, p1);
}else{
ArcShape shape = new ArcShape(i * 18, 18);
ShapeDrawable d = new ShapeDrawable(shape);
shape.resize(SIZE - (padding / 2), SIZE - (padding / 2));
d.setPadding(padding, padding, padding, padding);
shape.draw(c, p2);
}
}
}
I think it might be to do with the the fact I'm drawing the shape and not the ShapeDrawable but the ShapeDrawable.Draw() doesn't accept a Paint in the parameters, so I thought the shape would reference the ShapeDrawable.
I managed to fix it, I didn't need to the ShapeDrawable or padding. I used translate to offset the canvas position.
Bitmap b;
Canvas c;
#Override
protected void onStart() {
super.onStart();
b = Bitmap.createBitmap(SIZE, SIZE, Bitmap.Config.ARGB_8888);
c = new Canvas(b);
Paint p1 = new Paint();
Paint p2 = new Paint();
p1.setFlags(Paint.ANTI_ALIAS_FLAG);
p2.setFlags(Paint.ANTI_ALIAS_FLAG);
p1.setColor(Color.BLACK);
p2.setColor(Color.RED);
SegmentCircle(0, p1, p2);
p1.setColor(Color.GREEN);
p2.setColor(Color.BLUE);
SegmentCircle(50, p1, p2);
ImageView imageView = (ImageView) findViewById(R.id.imageView);
imageView.setImageBitmap(b);
}
private final static int SIZE = 500;
private void SegmentCircle(int padding, Paint p1, Paint p2){
for (int i = 0; i < 20; i++) {
ArcShape shape = new ArcShape(i * 18, 18);
shape.resize(SIZE - padding, SIZE - padding );
c.translate(padding / 2, padding / 2);
if ((i % 2) == 0){
shape.draw(c, p1);
}else{
shape.draw(c, p2);
}
c.translate(-(padding / 2), -(padding / 2));
}
}
In my Business Card Reader android application, I need to convert color image bitmap to black & white image bitmap (not gray scale image) for OCR text reading. so please help me to to convert color image bitmap to black & white image bitmap in android.
This question is long ago, but probably I could help other users.
I also had a long search for creating (fast)a pure Black and White bitmap.
My first methode used bitmap.getPixel() and bitmap.setPixel()
This took about 8s (832 x 1532)
New Method took 0.4s! Thanks factor 20!
Now I load all Pixels in an int array and go so through all pixels with getPixels(..) and setPixels(..):
Here my method:
public static Bitmap createBlackAndWhite(Bitmap src) {
int width = src.getWidth();
int height = src.getHeight();
Bitmap bmOut = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
final float factor = 255f;
final float redBri = 0.2126f;
final float greenBri = 0.2126f;
final float blueBri = 0.0722f;
int length = width * height;
int[] inpixels = new int[length];
int[] oupixels = new int[length];
src.getPixels(inpixels, 0, width, 0, 0, width, height);
int point = 0;
for(int pix: inpixels){
int R = (pix >> 16) & 0xFF;
int G = (pix >> 8) & 0xFF;
int B = pix & 0xFF;
float lum = (redBri * R / factor) + (greenBri * G / factor) + (blueBri * B / factor);
if (lum > 0.4) {
oupixels[point] = 0xFFFFFFFF;
}else{
oupixels[point] = 0xFF000000;
}
point++;
}
bmOut.setPixels(oupixels, 0, width, 0, 0, width, height);
return bmOut;
}
You could convert the image applying a color filter in this way:
Bitmap bwBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bwBitmap );
//set contrast
ColorMatrix contrastMatrix = new ColorMatrix();
//change contrast
float contrast = 50.f;
float shift = (-.5f * contrast + .5f) * 255.f;
contrastMatrix .set(new float[] {
contrast , 0, 0, 0, shift ,
0, contrast , 0, 0, shift ,
0, 0, contrast , 0, shift ,
0, 0, 0, 1, 0 });
//apply contrast
Paint contrastPaint = new Paint();
contrastPaint.setColorFilter(new ColorMatrixColorFilter(contrastMatrix ));
canvas.drawBitmap(colorBitmap, 0, 0, contrastPaint);
//set saturation
ColorMatrix saturationMatrix = new ColorMatrix();
saturationMatrix.setSaturation(0); //you set color saturation to 0 for b/w
//apply new saturation
Paint saturationPaint = new Paint();
saturationPaint.setColorFilter(new ColorMatrixColorFilter(saturationPaint));
canvas.drawBitmap(colorBitmap, 0, 0, saturationPaint);
You need to use ColorMatrix and ColorFilterclass in android to convert to Black and White.
Use this ColorMatrix - ColorMatrix cm1 = new ColorMatrix(new float[]{0.5f,0.5f,0.5f,0,0,
0.5f,0.5f,0.5f,0,0,
0.5f,0.5f,0.5f,0,0,
0,0,0,1,0,0,
0,0,0,0,1,0
});
I need to create a completely round image in Android. I've got the following code which works in newer version of Android, but in older versions (2.3), it is just a black circle:
Bitmap avatar = null;
if (avatarUrl == null || avatarUrl.equals("")) {
avatar = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon_no_avatar);
} else {
avatar = HttpClientHelper.downloadImage(avatarUrl);
}
if (avatar == null) {
// No avatar? Load the default one and use it instead
avatar = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon_no_avatar);
}
float width = 50; // avatar.getWidth();
float height = 50; // avatar.getHeight();
float ratio = (float)avatar.getWidth() / (float)avatar.getHeight();
// Scale the avatar to the area that it needs to fit into
avatar = Bitmap.createScaledBitmap(avatar, (int)(width * ratio), (int)height, true);
// Turn the avatar into a round image
Bitmap circleBitmap = Bitmap.createBitmap((int)width, (int)height, Bitmap.Config.ARGB_8888);
BitmapShader shader = new BitmapShader(avatar, TileMode.CLAMP, TileMode.CLAMP);
Paint paint = new Paint();
paint.setShader(shader);
RectF rect = new RectF(0.0f, 0.0f, width, height);
Canvas c = new Canvas(circleBitmap);
c.drawCircle(width / 2, height / 2, (width / 2) - 1, paint);
Is there something different I should do with 2.3 to make this work?
Use this
float width = 50; // avatar.getWidth();
float height = 50; // avatar.getHeight();
float radius = 45;
Bitmap bmpBG = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bmpBG);
//YOU CAN ADD SHADER FOR EFFECTS
Paint p = new Paint();
p.setAntiAlias(true);
p.setDither(true);
p.setColor(Color.RED);//SET YOUR COLOR HERE
c.drawCircle(width/ 2, height/ 2,
radius , p);
//NOW USE bmpBG
This must be a bug in 2.3. I was previously setting the round bitmap as the ImageView background which caused the black circle. When I set it as the foreground, the problem went away.
Again, this only happens with 2.3. After 3.0 this problem no longer exists.
I want to make an application just like opening screen of android.I am dynamically adding images to the rows of tableLayout. I have only defined tableLayout in xml file and remaining code is in java. I have added images successfully but i am not getting any help with setting text of that image (I want to display a text under image) and image to be a specific padding.How to do it?Thanks in advance.
Use the following function to write Text on Images:
private BitmapDrawable writeTextOnDrawable(int drawableId, String text) {
Bitmap bm = BitmapFactory.decodeResource(getResources(), drawableId)
.copy(Bitmap.Config.ARGB_8888, true);
Typeface tf = Typeface.create("Helvetica", Typeface.BOLD);
Paint paint = new Paint();
paint.setStyle(Style.FILL);
paint.setColor(Color.WHITE);
paint.setTypeface(tf);
paint.setTextAlign(Align.CENTER);
paint.setTextSize(convertToPixels(mContext, 11));
Rect textRect = new Rect();
paint.getTextBounds(text, 0, text.length(), textRect);
Canvas canvas = new Canvas(bm);
//If the text is bigger than the canvas , reduce the font size
if(textRect.width() >= (canvas.getWidth() - 4)) //the padding on either sides is considered as 4, so as to appropriately fit in the text
paint.setTextSize(convertToPixels(mContext, 7)); //Scaling needs to be used for different dpi's
//Calculate the positions
int xPos = (canvas.getWidth() / 2) - 2; //-2 is for regulating the x position offset
//"- ((paint.descent() + paint.ascent()) / 2)" is the distance from the baseline to the center.
int yPos = (int) ((canvas.getHeight() / 2) - ((paint.descent() + paint.ascent()) / 2)) ;
canvas.drawText(text, xPos, yPos, paint);
return new BitmapDrawable(getResources(), bm);
}
public static int convertToPixels(Context context, int nDP)
{
final float conversionScale = context.getResources().getDisplayMetrics().density;
return (int) ((nDP * conversionScale) + 0.5f) ;
}
What you can instead do is to put a TextView in overlay to a ImageView using a RelativeLayout :)
Here's Kotlin version Arun's solution:
import org.jetbrains.anko.dip
fun Context.writeTextOnDrawable(drawableId: Int, text: String) =
DrawableUtil.writeTextOnDrawableInternal(this, drawableId, text, 25, -2, 0)
object DrawableUtil {
fun writeTextOnDrawableInternal(context: Context, drawableId: Int, text: String,
textSizeDp: Int, horizontalOffset: Int, verticalOffset: Int): BitmapDrawable {
val bm = BitmapFactory.decodeResource(context.resources, drawableId)
.copy(Bitmap.Config.ARGB_8888, true)
val tf = Typeface.create("Helvetica", Typeface.BOLD)
val paint = Paint()
paint.style = Paint.Style.FILL
paint.color = Color.WHITE
paint.typeface = tf
paint.textAlign = Paint.Align.LEFT
paint.textSize = context.dip(textSizeDp).toFloat()
val textRect = Rect()
paint.getTextBounds(text, 0, text.length, textRect)
val canvas = Canvas(bm)
//If the text is bigger than the canvas , reduce the font size
if (textRect.width() >= canvas.getWidth() - 4)
//the padding on either sides is considered as 4, so as to appropriately fit in the text
paint.textSize = context.dip(12).toFloat()
//Calculate the positions
val xPos = canvas.width.toFloat()/2 + horizontalOffset
//"- ((paint.descent() + paint.ascent()) / 2)" is the distance from the baseline to the center.
val yPos = (canvas.height / 2 - (paint.descent() + paint.ascent()) / 2) + verticalOffset
canvas.drawText(text, xPos, yPos, paint)
return BitmapDrawable(context.resources, bm)
}
}
I m successfully implemented such problem of adding text on image. Just look at following code. First of take one view as Relative layout in that layout take ImageView after that EditText and after that button. Give each of a id. Write a loadBitmapFromView function below.
public Bitmap loadBitmapFromView(View v) {
Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Config.ARGB_8888);
Canvas c = new Canvas(b);
v.layout(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
v.draw(c);
return b;
}
and on click of button.
Bitmap bitmap = loadBitmapFromView(relativeLayout);
File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), "folderName");
if (!dir.exists())
dir.mkdirs();
File file = new File(dir, "capture.jpg");
try {
FileOutputStream fos = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
imageView.setImageBitmap(bitmap);
} catch (Exception e) {
Log.e("ExpressionEditImageActivity", "Error, " + e);
}
Enjoy...
For more reference, refer below screenshot: