I have an app that calculate time of phone usage and you can share it on social networks, instead of normal gettext() I want to put the results on an image and save it to phone. How can I create an image that I can save to the phone that includes custom text?
What you want to do is to paint to a Canvas that's linked to a Bitmap, and save the bitmap. Here's a few bits of code that you should be able to string together to make it work. Note that you'll have to still add the paining to the canvas, in the getBitmap() function.
private Bitmap getBitmap() {
Bitmap bitmap = Bitmap.createBitmap(mPieToss.getWidth(),
mPieToss.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
// Draw things to your canvas. They will be included as your BitMap, which is saved later on
return bitmap;
}
public void save() {
Bitmap bitmap = getBitmap();
File path = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
.format(new Date());
String filename = "Imagen_" + timestamp + ".jpg";
File file = new File(path, filename);
FileOutputStream stream;
// This can fail if the external storage is mounted via USB
try {
stream = new FileOutputStream(file);
bitmap.compress(CompressFormat.PNG, 100, stream);
stream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
mUri = Uri.fromFile(file);
bitmap.recycle();
}
First of all convert your layout to bitmap:
View contentLayout; // your layout with bavkground image and TextView
Bitmap bitmap = Bitmap.createBitmap(screenWidth, screenHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
content.draw(canvas);
Now you can save it to the file:
FileOutputStream fos = new FileOutputStream(fileName, false);
bitmap.compress(Bitmap.CompressFormat.PNG, 75, fos);
fos.flush();
fos.close();
Related
I have an XR app, where display shows the camera (rear) feed. As such, capturing the screen is pretty much the same as capturing the camera feed...
As such, I take screenshots (Bitmaps) and then try to detect faces within them using Googles MLKit.
I'm following the official guide to detect faces.
To do this, I first init my face detector:
FaceDetector detector;
public MyFaceDetector(){
FaceDetectorOptions realTimeOpts =
new FaceDetectorOptions.Builder()
.setContourMode(FaceDetectorOptions.CONTOUR_MODE_ALL)
.build();
detector = FaceDetection.getClient(realTimeOpts);
}
I then have a function which passes in a bitmap. I first convert the bitmap to a byte array. I do this because InputImage.fromBitmap is very slow, and MLKit actually tells me that I should use a byte array:
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 85, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream .toByteArray();
Next I make a mutable copy of the Bitmap (so that I can draw onto it), and set up a Canvas object, along with a color that will be used when drawing on to the Bitmap:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inMutable = true;
Bitmap bmp = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length, options);
Canvas canvas = new Canvas(bmp);
Paint p = new Paint();
p.setColor(Color.RED);
After all is set up, I create an InputImage (used by the FaceDetector), using the byte array:
InputImage image = InputImage.fromByteArray(byteArray, bmp.getWidth(), bmp.getHeight(),0, InputImage.IMAGE_FORMAT_NV21);
Note the image format... There is a InputImage.IMAGE_FORMAT_BITMAP, but using this throws an IllegalArgumentException. Anyway, I next try to process the Bitmap, detect faces, fill each detected face with the color defined earlier, and then save the Bitmap to disk:
Task<List<Face>> result = detector.process(image).addOnSuccessListener(
new OnSuccessListener<List<Face>>() {
#Override
public void onSuccess(List<Face> faces) {
Log.e("FACE DETECTION APP", "NUMBER OF FACES: " + faces.size());
Thread processor = new Thread(new Runnable() {
#Override
public void run() {
for (Face face : faces) {
Rect destinationRect = face.getBoundingBox();
canvas.drawRect(destinationRect, p);
canvas.save();
Log.e("FACE DETECTION APP", "WE GOT SOME FACCES!!!");
}
File file = new File(someFilePath);
try {
FileOutputStream fOut = new FileOutputStream(file);
bmp.compress(Bitmap.CompressFormat.JPEG, 85, fOut);
fOut.flush();
fOut.close();
} catch (Exception e) {
e.printStackTrace();
}
}
});
processor.start();
}
})
.addOnFailureListener(
new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
// Task failed with an exception
// ...
}
});
}
While this code runs (i.e. no exceptions) and the bitmap is correctly written to disk, no faces are ever detected (faces.size() is always 0). I've tried rotating the image. I've tried changing the quality of the Bitmap. I've tried with and without the thread to process any detected faces. I've tried everything I can think of.
Anyone have any ideas?
ML Kit InputImage. fromByteArray only support yv12 and nv21 formats. You will need to convert the bitmap to one of these formats in order for ML kit pipeline to process. Also, if the original image you have is a bitmap, you can probably just use InputImage.fromBitmap to construct an InputImage. It shouldn't be slower than your current approach.
I was having the same issue use ImageInput.fromMediaImage(..., ...)
override fun analyze(image: ImageProxy) {
val mediaImage: Image = image.image.takeIf { it != null } ?: run {
image.close()
return
}
val inputImage = InputImage.fromMediaImage(mediaImage, image.imageInfo.rotationDegrees)
// TODO: Your ML Code
}
Check here for more details
https://developers.google.com/ml-kit/vision/image-labeling/android
I have an activity for add new post, in each post user can select picture from gallery or take picture with camera. My save image method is ok for picture from camera but when I choose a picture from gallery, in my folder just save name of picture with a black picture.
public void saveImage(Bitmap myBitmap) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
File wallpaperDirectory = new File(
Environment.getExternalStorageDirectory() + IMAGE_DIRECTORY);
if (!wallpaperDirectory.exists()) {
wallpaperDirectory.mkdirs();
}
try {
File f = new File(wallpaperDirectory, Calendar.getInstance()
.getTimeInMillis() + ".jpg");
img_name = f.getAbsolutePath();
f.createNewFile();
FileOutputStream fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
MediaScannerConnection.scanFile(this,
new String[]{f.getPath()},
new String[]{"image/jpeg"}, null);
fo.close();
Log.d("TAG", "File Saved::--->" + f.getAbsolutePath());
return f.getAbsolutePath();
} catch (IOException e1) {
e1.printStackTrace();
}
return "";
And in my RecyclerView shows nothing.
You are just creating a new image file and not saving anything in it .
use following
FileOutputStream fo = new FileOutputStream(f);
myBitmap.compress(Bitmap.CompressFormat.PNG, 100, fo); // bmp is your Bitmap instance
fo.write(bytes.toByteArray());
you are missing this myBitmap.compress(Bitmap.CompressFormat.PNG, 100, fo); so add it.
I have a sm-t300i and im trying to figure out how to print a image from a database. I have the image data but not sure how to plug it in. I have successfuly added a image from the assets but not sure how to from raw image data. Code below is from assets. Also for some reason the image in the code below will not center is there something else i need to do to center the image. Thank you.
AssetManager assetManager = mContext.getAssets();
InputStream istr = null;
try {
istr = assetManager.open("www/img/logo.bmp");
} catch (IOException e) {
e.printStackTrace();
}
Bitmap bm = BitmapFactory.decodeStream(istr);
StarBitmap starbitmap = new StarBitmap(bm, false, 200);
commands.add(new byte[] { 0x1b, 0x61, 0x01 }); //align center
commands.add(starbitmap.getImageEscPosDataForPrinting(false,false));
Looks like you can just convert the base64 and make it a bitmap
String imagex = "iVBORw0KGgoAAAANS etc";
Bitmap bm = StringToBitMap(imagex);
StarBitmap starbitmap = new StarBitmap(bm, true, 600);
commands.add(starbitmap.getImageEscPosDataForPrinting(false,true));
public Bitmap StringToBitMap(String encodedString){
try {
byte [] encodeByte=Base64.decode(encodedString, Base64.DEFAULT);
Bitmap bitmap=BitmapFactory.decodeByteArray(encodeByte, 0, encodeByte.length);
return bitmap;
} catch(Exception e) {
e.getMessage();
return null;
}
}
Sometimes it works, sometimes it doesn't. I am sharing this picture on Facebook, and sometimes it is ok:
And sometimes it is partial black (only the Google map!):
I have a separate thread doing this screenshot:
new Thread() {
#Override
public void run() {
// Get root view
View view = mapView.getRootView();
view.setDrawingCacheEnabled(true);
// Create the bitmap to use to draw the screenshot
final Bitmap bitmap = Bitmap.createBitmap(
getWindowManager().getDefaultDisplay().getWidth(), getWindowManager().getDefaultDisplay().getHeight(), Bitmap.Config.ARGB_4444);
final Canvas canvas = new Canvas(bitmap);
// Get current theme to know which background to use
final Theme theme = activity.getTheme();
final TypedArray ta = theme
.obtainStyledAttributes(new int[] { android.R.attr.windowBackground });
final int res = ta.getResourceId(0, 0);
final Drawable background = activity.getResources().getDrawable(res);
// Draw background
background.draw(canvas);
// Draw views
view.draw(canvas);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 90, baos); //bm is the bitmap object
byte[] b = baos.toByteArray();
Bundle params = new Bundle();
params.putByteArray("source", b);
params.putString("message", "genie in a bottle");
try {
//String resp =
facebook.request("me/photos", params, "POST");
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}.start();
You can create the Bitmap object directly from the screen using:
bitmap = Bitmap.createBitmap(view.getDrawingCache());
Regards.
I had created an image by the following code:
Bitmap bmp = Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bmp);
try {
int tile1ResID = getResources().getIdentifier("drawable/m" + String.valueOf(tileOfPoint.x) + "_" + String.valueOf(tileOfPoint.y), "drawable", "com.example.sabtt1");
canvas.drawBitmap(Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), tile1ResID), 256, 256, true), 0, 0, null);
canvas.save();
}
catch (Exception e) {
}
canvas.save();
ImageView imgMap1 = (ImageView) findViewById(R.id.imgMap1);
imgMap1.setImageDrawable(new BitmapDrawable(Bitmap.createBitmap(bmp, 0, 0, 500, 500)));
now I want to make it as background. So that the user can add an image or draw on it.
How can I set it as background?
Is it possible to add the image and draw by finger at the same time?
I use this code for draw:
#Override
public void onClick(View arg0) {
try {
Bitmap gestureImg = gesture.getGesture().toBitmap(100, 100, 8, Color.BLACK);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
gestureImg.compress(Bitmap.CompressFormat.PNG, 100, bos);
byte[] bArray = bos.toByteArray();
Intent intent = new Intent(Activity1.this, Activity2.class);
intent.putExtra("draw", bArray);
startActivity(intent);
}
catch (Exception e) {
e.printStackTrace();
Toast.makeText(Activity1.this, "No draw on the string", 3000).show();
}
}
and OnDragListener for add and move images.
I know that I should use the folowing code for background:
LinearLayout ll = new LinearLayout(this);
ll.setBackgroundResource(R.drawable.nn);
this.setContentView(ll);
but by using this code, I can't see other images.
Thanks in advance.
You can just draw on the main bitmap the other bitmaps:
Bitmap bmp = Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888);
bmp = <load from resource>
Canvas canvas = new Canvas(bmp);
Bitmap gestureImg = <get bitmap from gesture or loading>
canvas.drawBitmap(gestureImg);
then load the final bitmap:
ImageView imgMap1 = (ImageView) findViewById(R.id.imgMap1);
imgMap1.setImageDrawable(new BitmapDrawable(Bitmap.createBitmap(bmp, 0, 0, 500, 500)));
Or you can store the main bitmap and all other gesture/loaded bitmaps in separate objects and when you want to update the imgMap1 you make your combined bitmap;
Also to use as background the new bitmap use:
ll.setBackgroundDrawable( new BitmapDrawable( bmp ) );