1package eu.siacs.conversations.persistance;
2
3import java.io.BufferedInputStream;
4import java.io.File;
5import java.io.FileInputStream;
6import java.io.FileNotFoundException;
7import java.io.FileOutputStream;
8import java.io.IOException;
9import java.io.InputStream;
10import java.io.OutputStream;
11import java.security.MessageDigest;
12import java.security.NoSuchAlgorithmException;
13
14import android.content.Context;
15import android.graphics.Bitmap;
16import android.graphics.BitmapFactory;
17import android.net.Uri;
18import android.util.Log;
19import android.util.LruCache;
20
21import eu.siacs.conversations.entities.Conversation;
22import eu.siacs.conversations.entities.Message;
23import eu.siacs.conversations.utils.CryptoHelper;
24
25public class FileBackend {
26
27 private static int IMAGE_SIZE = 1920;
28
29 private Context context;
30 private LruCache<String, Bitmap> thumbnailCache;
31
32 public FileBackend(Context context) {
33 this.context = context;
34
35 int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
36 int cacheSize = maxMemory / 8;
37 thumbnailCache = new LruCache<String, Bitmap>(cacheSize) {
38 @Override
39 protected int sizeOf(String key, Bitmap bitmap) {
40 return bitmap.getByteCount() / 1024;
41 }
42 };
43
44 }
45
46 public File getImageFile(Message message) {
47 Conversation conversation = message.getConversation();
48 String prefix = context.getFilesDir().getAbsolutePath();
49 String path = prefix + "/" + conversation.getAccount().getJid() + "/"
50 + conversation.getContactJid();
51 String filename = message.getUuid() + ".webp";
52 return new File(path + "/" + filename);
53 }
54
55 private Bitmap resize(Bitmap originalBitmap, int size) {
56 int w = originalBitmap.getWidth();
57 int h = originalBitmap.getHeight();
58 if (Math.max(w, h) > size) {
59 int scalledW;
60 int scalledH;
61 if (w <= h) {
62 scalledW = (int) (w / ((double) h / size));
63 scalledH = size;
64 } else {
65 scalledW = size;
66 scalledH = (int) (h / ((double) w / size));
67 }
68 Bitmap scalledBitmap = Bitmap.createScaledBitmap(
69 originalBitmap, scalledW, scalledH, true);
70 return scalledBitmap;
71 } else {
72 return originalBitmap;
73 }
74 }
75
76 public File copyImageToPrivateStorage(Message message, Uri image) {
77 try {
78 InputStream is = context.getContentResolver()
79 .openInputStream(image);
80 File file = getImageFile(message);
81 file.getParentFile().mkdirs();
82 file.createNewFile();
83 OutputStream os = new FileOutputStream(file);
84 Bitmap originalBitmap = BitmapFactory.decodeStream(is);
85 is.close();
86 Bitmap scalledBitmap = resize(originalBitmap, IMAGE_SIZE);
87 boolean success = scalledBitmap.compress(Bitmap.CompressFormat.WEBP,75,os);
88 if (!success) {
89 Log.d("xmppService", "couldnt compress");
90 }
91 os.close();
92 message.setBody(this.createSha1(file));
93 return file;
94 } catch (FileNotFoundException e) {
95 // TODO Auto-generated catch block
96 e.printStackTrace();
97 } catch (IOException e) {
98 // TODO Auto-generated catch block
99 e.printStackTrace();
100 }
101
102 return null;
103 }
104
105 public Bitmap getImageFromMessage(Message message) {
106 return BitmapFactory
107 .decodeFile(getImageFile(message).getAbsolutePath());
108 }
109
110 public Bitmap getThumbnailFromMessage(Message message, int size) {
111 Bitmap thumbnail = thumbnailCache.get(message.getUuid());
112 if (thumbnail==null) {
113 Log.d("xmppService","creating new thumbnail" + message.getUuid());
114 Bitmap fullsize = BitmapFactory.decodeFile(getImageFile(message)
115 .getAbsolutePath());
116 thumbnail = resize(fullsize, size);
117 this.thumbnailCache.put(message.getUuid(), thumbnail);
118 }
119 return thumbnail;
120 }
121
122 private String createSha1(final File file) {
123 InputStream fis = null;
124 try {
125 MessageDigest digest = MessageDigest.getInstance("SHA-1");
126 fis = new FileInputStream(file);
127 int n = 0;
128 byte[] buffer = new byte[8192];
129 while (n != -1) {
130 n = fis.read(buffer);
131 if (n > 0) {
132 digest.update(buffer, 0, n);
133 }
134 }
135 fis.close();
136 return CryptoHelper.bytesToHex(digest.digest());
137 } catch (NoSuchAlgorithmException e) {
138 return null;
139 } catch (FileNotFoundException e) {
140 if (fis!=null) {
141 try {
142 fis.close();
143 return null;
144 } catch (IOException e1) {
145 return null;
146 }
147 }
148 } catch (IOException e) {
149 if (fis!=null) {
150 try {
151 fis.close();
152 return null;
153 } catch (IOException e1) {
154 return null;
155 }
156 }
157 }
158 return null;
159 }
160}