Improved image handling

pull/147/head
M66B 7 years ago
parent 8492bc0b94
commit 36b4de2c7e

@ -24,9 +24,6 @@ import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.text.TextUtils; import android.text.TextUtils;
@ -81,31 +78,13 @@ public class AdapterImage extends RecyclerView.Adapter<AdapterImage.ViewHolder>
private void bindTo(EntityAttachment attachment) { private void bindTo(EntityAttachment attachment) {
if (attachment.available) { if (attachment.available) {
Drawable d = null; Bitmap bm = Helper.decodeImage(
File file = EntityAttachment.getFile(context, attachment.id); EntityAttachment.getFile(context, attachment.id),
context.getResources().getDisplayMetrics().widthPixels / 2);
if ("image/jpeg".equals(attachment.type) || "image/png".equals(attachment.type)) { if (bm == null)
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(file.getAbsolutePath(), options);
int scaleTo = context.getResources().getDisplayMetrics().widthPixels / 2;
int factor = Math.min(options.outWidth / scaleTo, options.outWidth / scaleTo);
if (factor > 1) {
options.inJustDecodeBounds = false;
options.inSampleSize = factor;
Bitmap scaled = BitmapFactory.decodeFile(file.getAbsolutePath(), options);
d = new BitmapDrawable(scaled);
}
}
if (d == null)
d = BitmapDrawable.createFromPath(file.getAbsolutePath());
if (d == null)
image.setImageResource(R.drawable.baseline_broken_image_24); image.setImageResource(R.drawable.baseline_broken_image_24);
else else
image.setImageDrawable(d); image.setImageBitmap(bm);
} else } else
image.setImageResource(attachment.progress == null image.setImageResource(attachment.progress == null
? R.drawable.baseline_image_24 : R.drawable.baseline_hourglass_empty_24); ? R.drawable.baseline_image_24 : R.drawable.baseline_hourglass_empty_24);

@ -31,6 +31,8 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.Network; import android.net.Network;
import android.net.NetworkCapabilities; import android.net.NetworkCapabilities;
@ -218,6 +220,22 @@ public class Helper {
return color; return color;
} }
static Bitmap decodeImage(File file, int scaleToPixels) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(file.getAbsolutePath(), options);
int factor = Math.min(options.outWidth / scaleToPixels, options.outWidth / scaleToPixels);
if (factor > 1) {
Log.i("Decode image factor=" + factor);
options.inJustDecodeBounds = false;
options.inSampleSize = factor;
return BitmapFactory.decodeFile(file.getAbsolutePath(), options);
}
return BitmapFactory.decodeFile(file.getAbsolutePath());
}
static void setViewsEnabled(ViewGroup view, boolean enabled) { static void setViewsEnabled(ViewGroup view, boolean enabled) {
for (int i = 0; i < view.getChildCount(); i++) { for (int i = 0; i < view.getChildCount(); i++) {
View child = view.getChildAt(i); View child = view.getChildAt(i);

@ -36,10 +36,8 @@ import org.jsoup.safety.Whitelist;
import org.jsoup.select.NodeTraversor; import org.jsoup.select.NodeTraversor;
import org.jsoup.select.NodeVisitor; import org.jsoup.select.NodeVisitor;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
@ -126,9 +124,16 @@ public class HtmlHelper {
boolean embedded = source.startsWith("cid:"); boolean embedded = source.startsWith("cid:");
boolean data = source.startsWith("data:"); boolean data = source.startsWith("data:");
Log.i("Image embedded=" + embedded + " data=" + data + " source=" + source); Log.i("Image show=" + show + " embedded=" + embedded + " data=" + data + " source=" + source);
if (!show) {
// Show placeholder icon
int resid = (embedded || data ? R.drawable.baseline_photo_library_24 : R.drawable.baseline_image_24);
Drawable d = context.getResources().getDrawable(resid, context.getTheme());
d.setBounds(0, 0, px, px);
return d;
}
if (show) {
// Embedded images // Embedded images
if (embedded) { if (embedded) {
String cid = "<" + source.substring(4) + ">"; String cid = "<" + source.substring(4) + ">";
@ -142,14 +147,15 @@ public class HtmlHelper {
d.setBounds(0, 0, px, px); d.setBounds(0, 0, px, px);
return d; return d;
} else { } else {
File file = EntityAttachment.getFile(context, attachment.id); Bitmap bm = Helper.decodeImage(
Drawable d = Drawable.createFromPath(file.getAbsolutePath()); EntityAttachment.getFile(context, attachment.id),
if (d == null) { context.getResources().getDisplayMetrics().widthPixels);
d = context.getResources().getDrawable(R.drawable.baseline_broken_image_24, context.getTheme()); if (bm == null) {
Drawable d = context.getResources().getDrawable(R.drawable.baseline_broken_image_24, context.getTheme());
d.setBounds(0, 0, px, px); d.setBounds(0, 0, px, px);
} else
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
return d; return d;
} else
return new BitmapDrawable(bm);
} }
} }
@ -178,44 +184,62 @@ public class HtmlHelper {
return d; return d;
} }
// Get cache folder // Get cache file name
File dir = new File(context.getCacheDir(), "images"); File dir = new File(context.getCacheDir(), "images");
if (!dir.exists()) if (!dir.exists())
dir.mkdir(); dir.mkdir();
InputStream is = null;
OutputStream os = null;
try {
// Create unique file name
File file = new File(dir, id + "_" + source.hashCode()); File file = new File(dir, id + "_" + source.hashCode());
// Get input stream
if (file.exists()) { if (file.exists()) {
Log.i("Using cached " + file); Log.i("Using cached " + file);
is = new BufferedInputStream(new FileInputStream(file)); return Drawable.createFromPath(file.getAbsolutePath());
} else { }
Log.i("Downloading " + source);
try { try {
is = new URL(source).openStream(); InputStream probe = null;
} catch (FileNotFoundException ex) { BitmapFactory.Options options = new BitmapFactory.Options();
throw ex; try {
} catch (IOException ex) { Log.i("Probe " + source);
Log.w(ex); probe = new URL(source).openStream();
Drawable d = context.getResources().getDrawable(R.drawable.baseline_cloud_off_24, context.getTheme()); options.inJustDecodeBounds = true;
d.setBounds(0, 0, px, px); BitmapFactory.decodeStream(probe, null, options);
return d; } finally {
if (probe != null)
probe.close();
} }
Bitmap bm;
InputStream is = null;
try {
Log.i("Download " + source);
is = new URL(source).openStream();
int scaleTo = context.getResources().getDisplayMetrics().widthPixels;
int factor = Math.min(options.outWidth / scaleTo, options.outWidth / scaleTo);
if (factor > 1) {
Log.i("Download image factor=" + factor);
options.inJustDecodeBounds = false;
options.inSampleSize = factor;
bm = BitmapFactory.decodeStream(is, null, options);
} else
bm = BitmapFactory.decodeStream(is);
} finally {
if (is != null)
is.close();
} }
// Decode image from stream
Bitmap bm = BitmapFactory.decodeStream(is);
if (bm == null) if (bm == null)
throw new IllegalArgumentException("decode stream failed"); throw new FileNotFoundException("Download image failed");
// Cache bitmap Log.i("Downloaded image");
if (!file.exists()) {
OutputStream os = null;
try {
os = new BufferedOutputStream(new FileOutputStream(file)); os = new BufferedOutputStream(new FileOutputStream(file));
bm.compress(Bitmap.CompressFormat.PNG, 100, os); bm.compress(Bitmap.CompressFormat.PNG, 100, os);
} finally {
if (os != null)
os.close();
} }
// Create drawable from bitmap // Create drawable from bitmap
@ -224,31 +248,11 @@ public class HtmlHelper {
return d; return d;
} catch (Throwable ex) { } catch (Throwable ex) {
// Show warning icon // Show warning icon
Log.e(ex); Log.w(ex);
Drawable d = context.getResources().getDrawable(R.drawable.baseline_broken_image_24, context.getTheme()); int res = (ex instanceof IOException && !(ex instanceof FileNotFoundException)
d.setBounds(0, 0, px, px); ? R.drawable.baseline_cloud_off_24
return d; : R.drawable.baseline_broken_image_24);
} finally { Drawable d = context.getResources().getDrawable(res, context.getTheme());
// Close streams
if (is != null) {
try {
is.close();
} catch (IOException e) {
Log.w(e);
}
}
if (os != null) {
try {
os.close();
} catch (IOException e) {
Log.w(e);
}
}
}
} else {
// Show placeholder icon
int resid = (embedded || data ? R.drawable.baseline_photo_library_24 : R.drawable.baseline_image_24);
Drawable d = context.getResources().getDrawable(resid, context.getTheme());
d.setBounds(0, 0, px, px); d.setBounds(0, 0, px, px);
return d; return d;
} }

Loading…
Cancel
Save