When I am using webp files for animated sticker packs it get rejected but if use same files for static stickers it get excepted. After looking all the codes I came to know that this is the last point where those files becomes problematic. But don not know how to identify if webp files stays as animated webp after saving. Please share your thought.
ps: I am using these webp files for whatsapp sticker packs. there is flag "animated_sticker_pack". we have to tell whatsapp that this pack contains only animated webp with proper fomrat. If I set it false then sticker pack get added (let it be static or animated webp). But if I set that flag true then those animated webp get rejected for pack showing error that There's problem with this pack.... So it might be that frames are lesser then it required. It get accepted as static means it might have single frame only.
To avoid issues regarding file type,format,size and all I am using the sample files from WhatsApp sample app
Code:
public static void SaveImage(Bitmap finalBitmap, String name, String identifier) {
String root = path + "/" + identifier;
File myDir = new File(root);
myDir.mkdirs();
String fname = name;
File file = new File(myDir, fname);
if (file.exists()){
file.delete();
}
try {
// FileOutputStream
FileOutputStream out = new FileOutputStream(file);
// Bitmap.compress
finalBitmap.compress(Bitmap.CompressFormat.WEBP, 100, out);
// close
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
////////////////////Other methods before saving images
private Bitmap downloadImageBitmap(String sUrl, String sIdentifier, String sName) {
imageFileName = getLastBitFromUrl(sUrl).replace(".png", ".webp");
identifier = sIdentifier;
name = sName;
Bitmap bitmap = null;
try {
InputStream inputStream = new URL(sUrl).openStream(); // Download Image from URL
bitmap = BitmapFactory.decodeStream(inputStream); // Decode Bitmap
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
#Override
protected Bitmap doInBackground(String... params) {
return downloadImageBitmap(params[0], params[1], params[2]);
}
protected void onPostExecute(Bitmap result) {
SaveImage(result, imageFileName, identifier);
}
You can download and save in doInBackground()
InputStream inputStream = new URL(sUrl).openStream(); // Download Image from URL
FileOutputStream out = new FileOutputStream(file);
Then make a loop where you read bytes in a buffer from input stream and write to output stream.
Don't forget to close all streams when done.
Related
I am getting this error, as if the directory was not being found. I had this code working before
and I simply just changed the path where I want to be created the file.
My app also has all the needed priviledge, as stated, it worked perfectly.
Before is was:
String path = STORAGE_PATH + "/DCMI" + "/Appdnp";
I simply changed to:
String path = STORAGE_PATH + "/.vilarica" + "/Appdnp";
And it started giving me java.io.FileNotFoundException: /storage/emulated/0/.vilarica/Appdnp/5WmK6658f9eKcp2h0QghGToCKOi2.jpg: open failed: ENOENT (No such file or directory)
I also tried changing the folder names, nothing worked,also making the first folder not hidden,etc.
I searched all around, found many resolutions of wrong paths, wrong names etc, but since it was working before I can't really see how that helps me here.
Storage path is:
public static final String STORAGE_PATH = Environment.getExternalStorageDirectory().toString();
But I don't think it's this since it was working before, and it gets the path correctly.
This is the part of the code from the class that represents these methods:
private Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
#Override
public void onPictureTaken(final byte[] data, Camera camera) {
new Thread(new Runnable() {
#Override
public void run() {
String path = STORAGE_PATH + "/.vilarica" + "/Appdnp";
writeFile(path, data);
}
}, "captureThread").start();
startPreview();
}
};
public void writeFile(String path, byte[] data) {
Bitmap bitmap = null;
if (data != null){
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
}
if (bitmap != null){
Matrix matrix = new Matrix();
if (mCameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
matrix.postRotate(90);
}else if (mCameraId == Camera.CameraInfo.CAMERA_FACING_FRONT){
matrix.postRotate(90);
matrix.postScale(1, -1);
}
Bitmap rotateBmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), matrix,false);
saveBmp2SD(path, rotateBmp);
rotateBmp.recycle();
}
}
private void saveBmp2SD(String path, Bitmap bitmap){
File file = new File(path);
if (!file.exists()){
file.mkdir();
}
String uid = user.getUid();
//String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String fileName = path + "/" + uid + ".jpg";
try {
FileOutputStream fos = new FileOutputStream(fileName);
BufferedOutputStream bos = new BufferedOutputStream(fos);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
bos.flush();
bos.close();
Log.i("TAG", "Take picture success!");
Intent i = new Intent(this, DPCalc.class);
i.putExtra("filename", fileName);
i.putExtra("path", path);
startActivity(i);
} catch (FileNotFoundException e) {
e.printStackTrace();
Log.e("TAG", "The save file for take picture does not exists!");
} catch (IOException e) {
e.printStackTrace();
Log.e("TAG", "Take picture fail!");
}
}
.mkdir() only makes one directory, AND if it fails, you don't get an exception, it returns 'false'. Real java has a proper API but I don't think android gets the benefit of this nicer API, it's too far behind on libraries. So:
Don't call file.mkdir(); it's file.getParent().mkdirs().
Check the return value of mkdirs().
Note that 'false' on mkdirs() means either that the dir is already there and nothing was done, or that the operation failed; it is not possible to determine why it failed.
I mentioned this API sucks, right? I guess... you could in theory write your own mkdirs which walks up the tree 'manually'. Alternatively, use if (!path.isDirectory()) to check if it already exists, and fail (without being capable of telling the user why) if .mkdirs() returns false.
I am trying to write and read a bitmap following the suggestions on other topics about this, the thing is i never get the bitmap when i try to read on the path where i saved the image:
So i have this to write the bitmap:
private String saveToInternalStorage(Bitmap bitmapImage){
ContextWrapper cw = new ContextWrapper(getApplicationContext());
// path to /data/data/yourapp/app_data/imageDir
File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
// Create imageDir
File mypath=new File(directory,"captured");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(mypath);
// Use the compress method on the BitMap object to write image to the OutputStream
bitmapImage.compress(Bitmap.CompressFormat.JPEG, 100, fos);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return directory.getAbsolutePath();
}
}
i pass the returned path to another activity and then i pass it as parameter to get the bitmap like this:
private void loadImageFromStorage(String path)
{
try {
File f=new File(path, "captured.jpg");
Log.d("filehe",f.toString());
b = BitmapFactory.decodeStream(new FileInputStream(f));
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
}
i feel i am doing something wrong here, but can't figure out what, the b variavel has no value :/.
Any help?
Thanks
So i have this to write the bitmap:
The file that you save is named captured.
i pass the returned path to another activity and then i pass it as parameter to get the bitmap like this
Here, you are trying to load captured.jpg, which is not captured.
You could avoid this sort of problem by having the first method return the File that the second method then uses.
Also:
Use an image-loading library (e.g., Picasso, Glide) that has an in-memory cache, so you do not waste the user's time re-loading the same bitmap from disk
Get rid of ContextWrapper from the first method, as you do not need it
I'm making an Android application that captures images and stores them in the internal memory, but to save the images are compressed and I want to be saved in its original size without any compression.
This is the code I am using to store images, as I do so not me compress ??
ContextWrapper cw = new ContextWrapper(context);
File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
File mypath = new File(directory, "TheChat" + (System.currentTimeMillis()/1000) + "Avatar.jpg");
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(mypath);
bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
}
catch (Exception e) {
e.printStackTrace();
}
finally {
try {
if (fileOutputStream != null) {
fileOutputStream.flush();
fileOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
Save it as a BLOB (bytearray), then reconvert it to a bitmap upon loading it. If it's for internal use only it should work fine. If you're not compressing it at all you might as well save it in a straight-forward format.
I have a Parse Android app for which I am implementing Facebook sign up. Currently I am stuck on grabbing images to set as profile pictures of new ParseUser's. I have successfully used the Facebook Graph API to retrieve the correct URL (I have checked this by plugging it into a browser, where I am shown the right profile picture), but I now need a way to turn that URL into a byte array (byte[]) so that I can save the ParseFile field of our ParseUser's profile picture. I have already looked at all these SO questions:
• java.net.URL read stream to byte[]
• Efficiently read file from URL into byte[] in Java
• Get image with given url and convert it to byte array
None of these have worked. I am currently trying to use the Apache IOutils, like in the solution from the second link. Here is my current code for the AsyncTask:
private class SetProfPicWithURL extends AsyncTask<URL, Integer, byte[]> {
#Override
protected byte[] doInBackground(URL... imageURL) {
Log.i("SetProfPicWithURL", "invocation, URL: " + imageURL[0]);
InputStream is = null;
byte[] bytes = null;
try {
is = imageURL[0].openStream();
bytes = IOUtils.toByteArray(is);
} catch (IOException e) {
e.printStackTrace();
}
finally {
if (is != null) try {
is.close();
if(bytes == null){Log.e("LoginActivity", "bytes is null int SetProfPicWithURL");}
final ParseFile imageFile = new ParseFile("image.jpg", bytes);
imageFile.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Log.i("LoginActivity", "getCurrentUser.put");
ParseUser.getCurrentUser().put(ParseUtils.PARSE_PROFILE_IMAGE, imageFile);
ParseUser.getCurrentUser().saveInBackground();
} else {
e.printStackTrace();
}
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
return bytes;
}
}
Now when this code executes, I get no error logs, and a ParseFile is created. However, no profile pictures load within the app, and when I click to examine the file in the dashboard, I get this error message:
The file “tfss-0280f98d-7180-4528-9d24-3ec47d3b25d4-image.jpg” could
not be opened because it is empty.
Honestly, I'm at a loss. I've spent significantly more time on this one photo issue than any other part of implementing the Facebook login. And the way our database is set up, it is really not ideal to create another field to save the URL and load with Picasso. Any help with this issue is truly appreciated!
Directly save your imagefile as profile picture like this :
final ParseFile imageFile = new ParseFile("image.jpg", bytes);
ParseUser.getCurrentUser().put(ParseUtils.PARSE_PROFILE_IMAGE, imageFile);
ParseUser.getCurrentUser().saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Log.i("LoginActivity", "Profile saved succesfully");
} else {
e.printStackTrace();
}
}
});
EDIT :
Use this to get image byte array from url.
try {
java.net.URL img_value = new java.net.URL(imageURL);
Bitmap mIcon = BitmapFactory
.decodeStream(img_value.openConnection()
.getInputStream());
if (mIcon != null)
imgByteArray = encodeToByteArray(mIcon);
} catch (Exception e) {
e.printStackTrace();
}
public byte[] encodeToByteArray(Bitmap image) {
Log.d(TAG, "encodeToByteArray");
Bitmap b= image;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
b.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] imgByteArray = baos.toByteArray();
return imgByteArray ;
}
Here is my code i have written to get images from assets folder by passing imagename from database.But when passedImage name is not found in assets folder then i want to show some dummy images my code is throwing only catch block when no image is found but its not showing default image and no log is print in case of image not found .....
private Bitmap getBitmapFromAsset(String strName) {
AssetManager assetManager = getAssets();
InputStream istr = null;
Bitmap bitmap = null;
try {
istr = assetManager.open(strName);
if(istr.equals("null"))
{
Log.i("getBitmapFromAsset isStr",""+istr);
bitmap = BitmapFactory.decodeStream(assetManager.open("save_fatwa.jpg"));
}
else
{
bitmap = BitmapFactory.decodeStream(istr);
}
} catch (Exception e) {
Log.i("getBitmapFromAsset",""+bitmap);
e.printStackTrace();
}
return bitmap;
}
AssetManager.open returns an InputStream, not a string. If should be if(istr==null) not if it equals the string "null".