Generate a image with custom text in Android - java

I'm trying to make an app for create custom cards. I'd like to add some text over a custom background (a jpg image).
What is the best way of doing it? I'd need to show the user a preview of the card before send it to the server.
Thanks

Use below code to achieve your requirement
Bitmap src = BitmapFactory.decodeResource(getResources(), R.drawable.yourimage); // the original file yourimage.jpg i added in resources
Bitmap dest = Bitmap.createBitmap(src.getWidth(), src.getHeight(), Bitmap.Config.ARGB_8888);
String yourText = "My custom Text adding to Image";
Canvas cs = new Canvas(dest);
Paint tPaint = new Paint();
tPaint.setTextSize(35);
tPaint.setColor(Color.BLUE);
tPaint.setStyle(Style.FILL);
cs.drawBitmap(src, 0f, 0f, null);
float height = tPaint.measureText("yY");
float width = tPaint.measureText(yourText);
float x_coord = (src.getWidth() - width)/2;
cs.drawText(yourText, x_coord, height+15f, tPaint); // 15f is to put space between top edge and the text, if you want to change it, you can
try {
dest.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(new File("/sdcard/ImageAfterAddingText.jpg")));
// dest is Bitmap, if you want to preview the final image, you can display it on screen also before saving
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
You have to use below permission in manifest file.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
For my device the path is /sdcard to access external SD card, it may vary for other devices. Some devices may have /mnt/sdcard may be it is for internal sd cards. Just check it while before using this code.
Actually I wrote the above code for some other question, which required time stamp on photo after captured from camera. I gave you the same solution with a little modifications for your specific requirement.
I hope you can understand this. If you have any doubts regarding code feel free to ask.

I am not sure this is the best solution, but it might help you.
Step1: Create a relative layout (or any other layout) and set your image as its background.
Step2: Now add a TextView with width and height as match_parent and gravity set as top|center_horizontal.
Step3: Now add another button or any other layout control which will trigger the user confirmation. (You should place this control outside the Relative layout).
Step4: If user has confirmed the image then you can take screenshot of your relative layout via following code:
v1.setDrawingCacheEnabled(true); //v1 is the object of your Relative layout
Bitmap bm = v1.getDrawingCache();
if (bm != null) {
//TODO: write the code for saving the image.
Toast toast = Toast.makeText(YourActivity.this, "image saved",
Toast.LENGTH_LONG);
toast.show();
} else {
Toast toast = Toast.makeText(YourActivity.this,
"No image saved.", Toast.LENGTH_LONG);
toast.show();
}

Related

Loading a bitmap with ImageDecoder from URI and adding text

In my activity, I want to modify an image to add a text on it.
The image is selected in the galery or taken with the camera and then stored in a file in a previous activity. Then the uri of that file is passed through extras.
Now I try to add a string on top of the image like so:
try {
modifyThePic(imageUri);
} catch (IOException e) {
e.printStackTrace();
}
here is the function's body:
public void modifyThePic(Uri imageUri) throws IOException {
ImageDecoder.Source source = ImageDecoder.createSource(this.getContentResolver(), imageUri);
Bitmap bitmap = ImageDecoder.decodeBitmap(source);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setTextSize(10);
canvas.drawText("Some Text here", 0, 0, paint);
image.setImageBitmap(bitmap); //image is the imageView to control the result
}
The expected behaviour would be to display the image with "Some Text here" on top of it. But instead there is nothing displayed, however the app doesn't crash.
While debugging, I come across an error that appears between the
Bitmap bitmap = ImageDecoder.decodeBitmap(source);
and the
Canvas canvas = new Canvas(bitmap);
here is the error:
java.io.FileNotFoundException: No content provider: /storage/emulated/0/Android/data/com.emergence.pantherapp/files/Pictures/JPEG_20200829_181926_7510981182141824841.jpg
I suspect that I missuse the "ImageDecoder" as it's my first time using it. More precisely, I was not able to let the "decodeBitmap" method in onCreate, Android Studio was telling me that it could not be in the "main thread", I am not familiar at all with threading. Moving it in a dedicaded function fixed this but maybe am I supposed to do something else and it's the root of the problem.
My questions:
Am I using the right tools to modify the file and add the text on it ?
If yes, what do I do wrong ?
If no, what library/tools should I look into to do this task ?
Thank you,
EDIT: ADDITONAL ANSWER ELEMENTS
As both #blackapps and #rmunge pointed out, I was not getting a legit URI but instead a file path. The easy fix for my problem was to get the URI from the path using this code:
Uri realuri = Uri.fromFile(new File("insert path here")));
Additionaly to edit the bitmap, it must be made mutable which is covered here for example.
The final function to extract the bitmap from the URI and adding text on top of it is this one:
public void modifyThePic(Uri imageUri) throws IOException {
ContentResolver cr = this.getContentResolver();
InputStream input = cr.openInputStream(imageUri);
Bitmap bitmap = BitmapFactory.decodeStream(input).copy(Bitmap.Config.ARGB_8888,true);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setTextSize(300);
int xPos = (canvas.getWidth() / 2); //just some operations to center the text
int yPos = (int) ((canvas.getHeight() / 2) - ((paint.descent() + paint.ascent()) / 2)) ;
canvas.drawText("SOME TEXT TO TRY IT OUT", xPos, yPos, paint);
image.setImageBitmap(bitmap);
}
Seems your URI is wrong. It has to start with file:///

Android Opencv Why HOG descriptors are always zero?

I am stack with this problem for a couple of days. I want to make an android app that takes a picture and extracts HOG features of that image for future processing. The problem is that the code below always returns the HOG descriptors with rezo values.
#Override
public void onPictureTaken(byte[] data, Camera camera) {
Log.i(TAG, "Saving a bitmap to file");
// The camera preview was automatically stopped. Start it again.
mCamera.startPreview();
mCamera.setPreviewCallback(this);
this.disableView();
Bitmap bitmapPicture = BitmapFactory.decodeByteArray(data, 0, data.length);
myImage = new Mat(bitmapPicture.getWidth(), bitmapPicture.getHeight(), CvType.CV_8UC1);
Utils.bitmapToMat(bitmapPicture, myImage);
Bitmap bm = Bitmap.createBitmap(myImage.cols(), myImage.rows(),Bitmap.Config.ARGB_8888);
Utils.matToBitmap(myImage.clone(), bm);
// find the imageview and draw it!
ImageView iv = (ImageView) getRootView().findViewById(R.id.imageView);
this.setVisibility(SurfaceView.GONE);
iv.setVisibility(ImageView.VISIBLE);
Mat forHOGim = new Mat();
org.opencv.core.Size sz = new org.opencv.core.Size(64,128);
Imgproc.resize( myImage, myImage, sz );
Imgproc.cvtColor(myImage,forHOGim,Imgproc.COLOR_RGB2GRAY);
//forHOGim = myImage.clone();
MatOfFloat descriptors = new MatOfFloat(); //an empty vector of descriptors
org.opencv.core.Size winStride = new org.opencv.core.Size(64/2,128/2); //50% overlap in the sliding window
org.opencv.core.Size padding = new org.opencv.core.Size(0,0); //no padding around the image
MatOfPoint locations = new MatOfPoint(); ////an empty vector of locations, so perform full search
//HOGDescriptor hog = new HOGDescriptor();
HOGDescriptor hog = new HOGDescriptor(sz,new org.opencv.core.Size(16,16),new org.opencv.core.Size(8,8),new org.opencv.core.Size(8,8),9);
Log.i(TAG,"Constructed");
hog.compute(forHOGim , descriptors, new org.opencv.core.Size(16,16), padding, locations);
Log.i(TAG,"Computed");
Log.i(TAG,String.valueOf(hog.getDescriptorSize())+" "+descriptors.size());
Log.i(TAG,String.valueOf(descriptors.get(12,0)[0]));
double dd=0.0;
for (int i=0;i<3780;i++){
if (descriptors.get(i,0)[0]!=dd) Log.i(TAG,"NOT ZERO");
}
Bitmap bm2 = Bitmap.createBitmap(forHOGim.cols(), forHOGim.rows(),Bitmap.Config.ARGB_8888);
Utils.matToBitmap(forHOGim,bm2);
iv.setImageBitmap(bm2);
}
So in the logcat I never get the NOT ZERO message. The problem is that whatever changes I do to this code I always have zeros in the descriptors MatOfFloat... And the strange part is, if I uncomment the HOGDescriptor hog = new HOGDescriptor(); and use that one instead of the one I am using now, my application crashes...
The rest of the code runs fine, the picture is always taken and displayed on my image view as I expect.
Any help will be appreciated.
Thanks in advance.
The problem was inside the library. When I executed the same code with OpenCV 2.4.13 for Linux and not for Android, the code worked great as expected. So I hope they will fix any problems with the HOGDescriptor for OpenCV4Android.

Cropping BufferedImage For Use in Xuggle encodeVideo

I have an application to capture video of the screen and save to a file. I give the user the ability to pick between 480, 720, and "Full Screen" video sizes. A 480 will record in a small box on the screen, 720 will record in a larger box, and of course, "Full Screen" will record in an even larger box. However, this full screen box is NOT the actual screen resolution. It is the app window size, which happens to be around 1700x800. The Video Tool works perfectly for the 480 and 720 options, and will also work if "Full Screen" is overwridden to be the entire screen of 1920x1080.
My question: Are only certain sizes allowed? Does it have to fit a certain aspect ratio, or be an "acceptable" resolution? My code, below, is modified from the xuggle CaptureScreenToFile.java file (the location of the problem is noted by comments):
public void run() {
try {
String parent = "Videos";
String outFile = parent + "example" + ".mp4";
file = new File(outFile);
// This is the robot for taking a snapshot of the screen. It's part of Java AWT
final Robot robot = new Robot();
final Rectangle customResolution = where; //defined resolution (custom record size - in this case, 1696x813)
final Toolkit toolkit = Toolkit.getDefaultToolkit();
final Rectangle fullResolution = new Rectangle(toolkit.getScreenSize()); //full resolution (1920x1080)
// First, let's make a IMediaWriter to write the file.
final IMediaWriter writer = ToolFactory.makeWriter(outFile);
writer.setForceInterleave(false);
// We tell it we're going to add one video stream, with id 0,
// at position 0, and that it will have a fixed frame rate of
// FRAME_RATE.
writer.addVideoStream(0, 0, FRAME_RATE, customResolution.width, customResolution.height); //if I use fullResolution, it works just fine - but captures more of the screen than I want.
// Now, we're going to loop
long startTime = System.nanoTime();
while (recording) {
// take the screen shot
BufferedImage screen = robot.createScreenCapture(fullResolution); //tried capturing using customResolution, but did not work. Instead, this captures full screen, then tries to trim it below (also does not work).
// convert to the right image type
BufferedImage bgrScreen = convertToType(screen, BufferedImage.TYPE_3BYTE_BGR); //Do I need to convert after trimming?
BufferedImage trimmedScreen = bgrScreen.getSubimage((int)customResolution.getX(), (int)customResolution.getY(), (int)customResolution.getWidth(), (int)customResolution.getHeight());
// encode the image
try{
//~~~~Problem is this line of code!~~~~ Error noted below.
writer.encodeVideo(0, trimmedScreen, System.nanoTime() - startTime, TimeUnit.NANOSECONDS); //tried using trimmedScreen and bgrScreen
} catch (Exception e) {
e.printStackTrace();
}
// sleep for framerate milliseconds
Thread.sleep((long) (1000 / FRAME_RATE.getDouble()));
}
// Finally we tell the writer to close and write the trailer if
// needed
writer.close();
} catch (Throwable e) {
System.err.println("an error occurred: " + e.getMessage());
}
}
public static BufferedImage convertToType(BufferedImage sourceImage, int targetType) {
BufferedImage image;
// if the source image is already the target type, return the source image
if (sourceImage.getType() == targetType)
image = sourceImage;
// otherwise create a new image of the target type and draw the new image
else {
image = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), targetType);
image.getGraphics().drawImage(sourceImage, 0, 0, null);
}
return image;
}
Error:
java.lang.RuntimeException: could not open stream com.xuggle.xuggler.IStream#2834912[index:0;id:0;streamcoder:com.xuggle.xuggler.IStreamCoder#2992432[codec=com.xuggle.xuggler.ICodec#2930320[type=CODEC_TYPE_VIDEO;id=CODEC_ID_H264;name=libx264;];time base=1/50;frame rate=0/0;pixel type=YUV420P;width=1696;height=813;];framerate:0/0;timebase:1/90000;direction:OUTBOUND;]: Operation not permitted
Note: The file is successfully created, but has size of zero, and cannot be opened by Windows Media Player, with the following error text:
Windows Media Player cannot play the file. The Player might not support the file type or might not support the codec that was used to compress the file.
Sorry for the wordy question. I'm interested in learning WHAT and WHY, not just a solution. So if anyone can explain why it isn't working, or point me towards material to help, I'd appreciate it. Thanks!
Try to have the dimension even numbers 1696x812

how to change the size of Bitmap?

I make a picture and save it in the pre 'ArrayList Bitmap' and before saving them to a card I bring them in 'GridView'. But due to the fact that the picture 'Bitmap' in the large 'GridView' they are not displayed correctly. I have tried to do so before saving
bitmap.setHeight();
bitmap.setWidth();
But Android Studio underlines and says that I can not use these methods. If I understand correctly that this is connected with the API.
Advise how to make a picture 50 by 50 pixels?
If you already have a bitmap and want to resize it..
Bitmap bMap = BitmapFactory.decodeByteArray(bMapArray, 0, bMapArray.length); //Original Initialization
try {
resizedBitmap = Bitmap.createScaledBitmap(bMap, 240, 320, false);// Here I have set it To 240 width and 320 Height
}
catch (Exception e){
}

how to detect the number of face in an image picture

I am creating an Android face detection app and when I run it on my device it always says:
"Sorry TakePic has suddenly stopped"
Here is my code for face detection and I believe that this is the source of the error:
bitmap = MediaStore.Images.Media.getBitmap(cr, selectedImage);
TextView detect = (TextView)findViewById(R.id.detect);
Bitmap maskBitmap = Bitmap.createBitmap( bitmap.getWidth(),bitmap.getHeight(), Bitmap.Config.RGB_565 );
Canvas c = new Canvas();
c.setBitmap(maskBitmap);
Paint p = new Paint();
p.setFilterBitmap(true); // possibly not nessecary as there is no scaling
c.drawBitmap(bitmap,0,0,p);
bitmap.recycle();
detectedFaces=new FaceDetector.Face[NUMBER_OF_FACES];
faceDetector=new FaceDetector(maskBitmap.getWidth(),maskBitmap.getHeight(),NUMBER_OF_FACES);
NUMBER_OF_FACE_DETECTED=faceDetector.findFaces(maskBitmap, detectedFaces);
k.setImageBitmap(bitmap);
detect.setText(NUMBER_OF_FACE_DETECTED);
Toast.makeText(MainActivity.this, selectedImage.toString(), Toast.LENGTH_LONG).show();
What would the mistake be with this code?
The best practice in such cases is to inspect LogCat view and look for exception messages to locate where your code is breaking.

Categories