I have created a camera app where I want to send the frames I receive in onCameraFrame of OpenCV library to server in real-time or say with minimum delay. I was able to achieve map to string conversation in real-time but facing two problems in sending the string to the server.
The string is too large and few Connections like httpUrlConnection in android is not able to send this.
I want to send this big string to the server on one short as quick as possible to achieve the real-time effect.
private Bitmap convertMatToBitMap(Mat input) {
Bitmap bmp = null;
Mat rgb = new Mat();
Imgproc.cvtColor(input, rgb, Imgproc.COLOR_mRGBA2RGBA);
try {
bmp = Bitmap.createBitmap(rgb.cols(), rgb.rows(),Bitmap.Config.ARGB_8888);
Utils.matToBitmap(rgb, bmp);
}
catch (CvException e){
Log.d("Exception",e.getMessage());
}
String bmpStringObj = BitMapToString(bmp);
sendRequest(bmpStringObj); // This is be super fast
return StringToBitMap(bmpStringObj);
}
The above code converts map to bit map and I need to send the string format of this bitmap to server.
Related
I would like to send, from my android app to my backend API an image.
So in my android app I convert an image in base64 string. That part works perfectly.
Android Code:
Bitmap resized = Bitmap.createScaledBitmap(AccueilActivity.photo, 720, 1280, true);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
resized.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] byteArray = baos.toByteArray();
String encodedImage = new String(""+Base64.encodeBase64URLSafeString(byteArray));
When I want to execute the endpoint https request, it fails !
Campagneendpoint endpoint = endpointBuilder.build();
try {
result=endpoint.sendCampagne(encodedImage).execute();
} catch (IOException e) {
e.printStackTrace();
}
And I've got this error:
javax.net.ssl.SSLException: Write error: ssl=0x78edde30: I/O error during system call, Broken pipe
But If I pass directly the base64 string, It works !
Campagneendpoint endpoint = endpointBuilder.build();
try {
result=endpoint.sendCampagne("_9j_4AAQSkZJRgABAQAAAQABAAD_2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH_2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH_wAARCAUAAtADASIAAhEBAxEB_8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL_8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4-Tl5ufo6erx8vP09fb3-Pn6_8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL_8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3-Pn6_9oADAMBAAIRAxEAPwD7T-H1zNcRW0NpvF0zqpvXk82MwyLKr-UgVSXMEyw3BlMkhCq-Y44pJH7Txd4Tu4bRdVtVl1N7iF40aCQYgt_OvZGRWWMpGRK0kYVBvkljJkUHyWHg3wg8TSTQWxt0WM2U7uk0il7e4tWjCuggMk8yPiCViC3kidBBlJFct91x3WneINKYsomQovlxRlcRCTLGZ4x5ojcTqjBAsZYusJZ1QAfnUI06cIwpSVOnSknTkoq6UW-Rxh765oLVuTdnJNas-RxEJNyvCpFJLWblf4oy97eSXu2Xk4t6uz_I342eEtUudO1po1NjBGtrLN5ywYe5jurowRZVCxdFhjnk3xMy3E8UyTGNXU_k18WvCbz3275PtkkTgzi6hnilF3byyxWcqSCCW3L3MG-aR1EU90EluAYhPLH_AES_GTwULbS9Xu7GKGeyng3GWSLzpo51WWa5TUY4C2-OFseVOQA6oYfLicxu34wftAeBRosZlKQPbahNFMkzXICxSrNMsivHOyTKZpoJI7d2SNJRvVAPLuBXq4erSjVV6rqSlCKmqkpNpuaa5E37t7cya15rSam1d5WurTUZW5XrHtfmTV73fNayV3zK8rJ2_Inxb4ZtLiW50zUrOUveK8dndrPHBAPneG7uZrbdPdNDLaRyeQ7TqFuxbcOZnQeUahZySTQLcSRS3NmstirQSQtYtFZPLIksMEyl47d5CZXkuIVEs0zyxqsgdj9P-LNHihubyK7R2NpdbEVlElvc2NwUe3uoyCJIp7O4ZIJleQvL56vaxiJLgx_PfibTLa1ubu7MiyWsCMbYRxg_ZgDM0VtvkuPuPO8kSSrEVXzY4gGIGfTpSao8sVJ35W73jyxlKUownZtXSvyt2k21z1JO0X106UJJyvBpWWkVJNQbjH3bJ2WrXK9XJp3cVJ-fXVmdUs7mV4AtoqmSTyobiezUokcVpdTpIZhbqtyBNPZLGsUjG5UShVmu2yDZaXLA_ny75fMtljdoCG8uPe0kkTFZVlaHdJL5G6QohuXZsb_O0bh7v7DPYQKLZ5_s5vHRZoil1Yz3qW21YkRDafZ47GYTTboh9pMZWOIPGufO3mRrJOp82MM1u0TxRp5DbwsEcZWZSu4Mkc-VmjV549pWOUN0RqyTdk4q0XHV3nzSaTs1o2qemjbsrNysz0oRtzJSi7-yWq1UUlBxUo83K_ier92LV9FrXuLbS9UuHQPGwt1jkijlKvLP9mlbP2YzNvjKMLgJE8oaaQtaK7SsIFt5sRBJPGiW89zLLNPcSXEu24uPtUtq0qrMsLwyXEK2kMSqkUahNwcJFk5VyzrJFbyyKksQt5IQiSCMJBqTSJGkzIFnk8-MmbyZCIJJvLVirxgusIFjlt_MkklljhmicHLNl5bkO-zJkzEsfmJDMRKWQoF3sHqKOLlCqnB29lO8eflau7NcsZe607P3m3O7TSV5TNoq_PFRUk0k9I-9eTSXvK9215JpRS5lFp044rSa2uLZQyy7muVdfswli8iO4jt48s0bZjlVbdE-0qhw22ISiSWSylncNfm51AtdeZ5zyrbxtDdLJBFGIgd8jwgRR28VtbB5IMQQO4dxCxq_JdQX-pzAW4i8uW0RorpmlijWC6nvECSy3Eio53RPcQRsiyI8Vt9midJhJnecbadpInAhHl-RgEMv3LmSRXYSiE-ZHLLcxBmiuNgSPyopZRWMVBTdS2vNJaK15LlfvtSakm3zJtrVyu2mxOnFJpKPIlGNmlyaSVuitsm1y2WsWk7SGR2sAiEZuBOkTIpKSCQkkO1mrSqnFwJQGhME6xK20LHCiqKzZRZweWGhmwWQJIZnfj7TcyEyOvlK0Zmd5Y1VWfbiOaJ5lEraViJFP21PKNtBK1u82HAW6At1iSC3ZZJJI5UYNCIVOQ8shWUNkJJHFIsSEKI0gjjIi3xFGSS5miUJFJIGDPOS0m5Wc7W2vMwek4OUb-zteLellLdpK8m2leSbak9EtWrXnlfO3BpctOmuVt6-80rWV9oK8r6XdoKXNKUcttLI4u3KyPIskjMWYO7xJC3zbQyxgxwxuwjiZUiIeJwyuGdFDF5uYLdlneK23RRyrtzCjIFZVD4QYmRHRlEkZjO2JEK1dhLtNPbLGyF4pEZJ2kt0CwRvHcrK6oHMJiJikERGwTRSEIzLuSaO3tlkjLK5ktpHg8iWAc-ZbNJLHMgEwBkVxiJgV2o8qNI0NwmEnytfE3GWzXvJR50kle8do83bmjbmamawcrJKMbKMIq891ZaNJaPzTbd47_E47vzpwLi6V7p_NidSsvluX23NuAkZ6edEoVGkURLsVQWdWxcKCLUApWRN1rfRzTb98sGI5k8ueJJflHkSMiYZwzqnmRMC8NQW1xqNxPKxDC0xEXeeb92Jm8yCGVJJhJIlqgtFV1k8yGZo7VFiyBvnM6ywyrdmSNrZZZLtjNabZLpZLvykYNJHKFjhVI7kwyMUXb5GQi5zi4qyStH2kWlJNrSLUW4305tdVfTdNyuaQejTurrl5veu3zwbbsrRjJKyacpSjrzWabdb6e1_cPMpS1lt_JZ0mmPlxokDT20xmWCWVDHDFb5idCsrSSxTRAE10cdx5kTC3ZkV5WjtWVoRLFLBKht2YyIFQSyi4splZQYHUS-XgRha1lZyaesyElblZwHd3lmEzRyNsETLcTx2SIlsoVwqANFJGWdBHueljOgguZ7i5juBe_bp5lvbl5be5uWAylzYSNLCwNrATCiSz_ZI3iW3kKxwFKfLz8sIp-0TSSja6sm-VK1uflk3e6bdpNuSKin7ic4XktG1G8XeKSbblyqySXuqz5dY81yWxsbsvOMB1hvoo7iUeVJm4nn3bYik7h2m3IkLQRxEyDzgqOZCl6ITxsJL2fNssyb2Mq2iPJNcON4S6kSPCtM0cc0BkjixerKWid5HrPq-n6TFd3U0Ux8tGCQpPullvpEljiUyraRj_RhHFcb7neixeUI1MjTQ1wcMmpePbuexs1aa1ijjiuY44LgwxpK0sO55LuOBUN4ZGhtbcZupCDczW4iaVkzxmIpQo1MROUoOCtN1YSVOFOCUYSjLmUpN2s_dfvRgr3i2_RwlOdSKjBN6LmaTjFLa8nytRtyQevSTim2pyNnV_iJPZahBbeHYo9QD3BNzLPdyxw3Lq90LcpH5vmhoTMonjX_XxXFypuH3slel_Bv9mnxz8UdctfN0y-tmlaWT7DPb-a0cNtdQygziJ41tp").execute();
} catch (IOException e) {
e.printStackTrace();
}
I tried that but same problem:
String encodedImage = new String(Base64.encodeBase64URLSafeString(byteArray));
String encodedImage = Base64.encodeBase64URLSafeString(byteArray);
Only hard instanciation seems to work :
String encodedImage = "_9j_4AAQSkZJRgABAQAAAQABAAD_2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH_2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH_wAARCAUAAtADASIAAhEBAxEB_8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL_8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4-Tl5ufo6erx8vP09fb3-Pn6_8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL_8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3-Pn6_9oADAMBAAIRAxEAPwD7T-H1zNcRW0NpvF0zqpvXk82MwyLKr-UgVSXMEyw3BlMkhCq-Y44pJH7Txd4Tu4bRdVtVl1N7iF40aCQYgt_OvZGRWWMpGRK0kYVBvkljJkUHyWHg3wg8TSTQWxt0WM2U7uk0il7e4tWjCuggMk8yPiCViC3kidBBlJFct91x3WneINKYsomQovlxRlcRCTLGZ4x5ojcTqjBAsZYusJZ1QAfnUI06cIwpSVOnSknTkoq6UW-Rxh765oLVuTdnJNas-RxEJNyvCpFJLWblf4oy97eSXu2Xk4t6uz_I342eEtUudO1po1NjBGtrLN5ywYe5jurowRZVCxdFhjnk3xMy3E8UyTGNXU_k18WvCbz3275PtkkTgzi6hnilF3byyxWcqSCCW3L3MG-aR1EU90EluAYhPLH_AES_GTwULbS9Xu7GKGeyng3GWSLzpo51WWa5TUY4C2-OFseVOQA6oYfLicxu34wftAeBRosZlKQPbahNFMkzXICxSrNMsivHOyTKZpoJI7d2SNJRvVAPLuBXq4erSjVV6rqSlCKmqkpNpuaa5E37t7cya15rSam1d5WurTUZW5XrHtfmTV73fNayV3zK8rJ2_Inxb4ZtLiW50zUrOUveK8dndrPHBAPneG7uZrbdPdNDLaRyeQ7TqFuxbcOZnQeUahZySTQLcSRS3NmstirQSQtYtFZPLIksMEyl47d5CZXkuIVEs0zyxqsgdj9P-LNHihubyK7R2NpdbEVlElvc2NwUe3uoyCJIp7O4ZIJleQvL56vaxiJLgx_PfibTLa1ubu7MiyWsCMbYRxg_ZgDM0VtvkuPuPO8kSSrEVXzY4gGIGfTpSao8sVJ35W73jyxlKUownZtXSvyt2k21z1JO0X106UJJyvBpWWkVJNQbjH3bJ2WrXK9XJp3cVJ-fXVmdUs7mV4AtoqmSTyobiezUokcVpdTpIZhbqtyBNPZLGsUjG5UShVmu2yDZaXLA_ny75fMtljdoCG8uPe0kkTFZVlaHdJL5G6QohuXZsb_O0bh7v7DPYQKLZ5_s5vHRZoil1Yz3qW21YkRDafZ47GYTTboh9pMZWOIPGufO3mRrJOp82MM1u0TxRp5DbwsEcZWZSu4Mkc-VmjV549pWOUN0RqyTdk4q0XHV3nzSaTs1o2qemjbsrNysz0oRtzJSi7-yWq1UUlBxUo83K_ier92LV9FrXuLbS9UuHQPGwt1jkijlKvLP9mlbP2YzNvjKMLgJE8oaaQtaK7SsIFt5sRBJPGiW89zLLNPcSXEu24uPtUtq0qrMsLwyXEK2kMSqkUahNwcJFk5VyzrJFbyyKksQt5IQiSCMJBqTSJGkzIFnk8-MmbyZCIJJvLVirxgusIFjlt_MkklljhmicHLNl5bkO-zJkzEsfmJDMRKWQoF3sHqKOLlCqnB29lO8eflau7NcsZe607P3m3O7TSV5TNoq_PFRUk0k9I-9eTSXvK9215JpRS5lFp044rSa2uLZQyy7muVdfswli8iO4jt48s0bZjlVbdE-0qhw22ISiSWSylncNfm51AtdeZ5zyrbxtDdLJBFGIgd8jwgRR28VtbB5IMQQO4dxCxq_JdQX-pzAW4i8uW0RorpmlijWC6nvECSy3Eio53RPcQRsiyI8Vt9midJhJnecbadpInAhHl-RgEMv3LmSRXYSiE-ZHLLcxBmiuNgSPyopZRWMVBTdS2vNJaK15LlfvtSakm3zJtrVyu2mxOnFJpKPIlGNmlyaSVuitsm1y2WsWk7SGR2sAiEZuBOkTIpKSCQkkO1mrSqnFwJQGhME6xK20LHCiqKzZRZweWGhmwWQJIZnfj7TcyEyOvlK0Zmd5Y1VWfbiOaJ5lEraViJFP21PKNtBK1u82HAW6At1iSC3ZZJJI5UYNCIVOQ8shWUNkJJHFIsSEKI0gjjIi3xFGSS5miUJFJIGDPOS0m5Wc7W2vMwek4OUb-zteLellLdpK8m2leSbak9EtWrXnlfO3BpctOmuVt6-80rWV9oK8r6XdoKXNKUcttLI4u3KyPIskjMWYO7xJC3zbQyxgxwxuwjiZUiIeJwyuGdFDF5uYLdlneK23RRyrtzCjIFZVD4QYmRHRlEkZjO2JEK1dhLtNPbLGyF4pEZJ2kt0CwRvHcrK6oHMJiJikERGwTRSEIzLuSaO3tlkjLK5ktpHg8iWAc-ZbNJLHMgEwBkVxiJgV2o8qNI0NwmEnytfE3GWzXvJR50kle8do83bmjbmamawcrJKMbKMIq891ZaNJaPzTbd47_E47vzpwLi6V7p_NidSsvluX23NuAkZ6edEoVGkURLsVQWdWxcKCLUApWRN1rfRzTb98sGI5k8ueJJflHkSMiYZwzqnmRMC8NQW1xqNxPKxDC0xEXeeb92Jm8yCGVJJhJIlqgtFV1k8yGZo7VFiyBvnM6ywyrdmSNrZZZLtjNabZLpZLvykYNJHKFjhVI7kwyMUXb5GQi5zi4qyStH2kWlJNrSLUW4305tdVfTdNyuaQejTurrl5veu3zwbbsrRjJKyacpSjrzWabdb6e1_cPMpS1lt_JZ0mmPlxokDT20xmWCWVDHDFb5idCsrSSxTRAE10cdx5kTC3ZkV5WjtWVoRLFLBKht2YyIFQSyi4splZQYHUS-XgRha1lZyaesyElblZwHd3lmEzRyNsETLcTx2SIlsoVwqANFJGWdBHueljOgguZ7i5juBe_bp5lvbl5be5uWAylzYSNLCwNrATCiSz_ZI3iW3kKxwFKfLz8sIp-0TSSja6sm-VK1uflk3e6bdpNuSKin7ic4XktG1G8XeKSbblyqySXuqz5dY81yWxsbsvOMB1hvoo7iUeVJm4nn3bYik7h2m3IkLQRxEyDzgqOZCl6ITxsJL2fNssyb2Mq2iPJNcON4S6kSPCtM0cc0BkjixerKWid5HrPq-n6TFd3U0Ux8tGCQpPullvpEljiUyraRj_RhHFcb7neixeUI1MjTQ1wcMmpePbuexs1aa1ijjiuY44LgwxpK0sO55LuOBUN4ZGhtbcZupCDczW4iaVkzxmIpQo1MROUoOCtN1YSVOFOCUYSjLmUpN2s_dfvRgr3i2_RwlOdSKjBN6LmaTjFLa8nytRtyQevSTim2pyNnV_iJPZahBbeHYo9QD3BNzLPdyxw3Lq90LcpH5vmhoTMonjX_XxXFypuH3slel_Bv9mnxz8UdctfN0y-tmlaWT7DPb-a0cNtdQygziJ41tp";
For the moment I can't send image to my backend API because there is a bug I don't know where... Anyone had already get this error ?
The problem was I had a heap size overflow, so convert image in base64 was not a good idea..
You can only send messages no longer than 1MB. If you want to store larger files (including images) you should use Blobstore. Here is a good explanation how to use Blobstore for Java with examples.
Then you just store blobKey in your Datastore and serve it from Blobstore using servlets if needed.
Here's another question for you :)
Basically i made a realtime streaming service, sending multiple jpegs to my android app, that decodes them as soon as he receives them.
// dIn is DataInputStream
// videoFeed is an ImageView
// bitmap is Bitmap
// hand is an Handler of the main thread
//CODE EXECUTED IN ANOTHER THERAD
byte[] inBuff = new byte[8];
byte[] imgBuff;
String inMsg;
while(socket.isConnected()) {
dIn.readFully(inBuff);
inMsg = new String(inBuff, "ASCII").trim();
int size = Integer.parseInt(inMsg);
imgBuff = new byte[size];
dIn.readFully(imgBuff);
out.write("SEND-NEXT-JPEG".getBytes("ASCII"));
bitmap = BitmapFactory.decodeByteArray(imgBuff, 0, size);
hand.post(setImage);
}
}
private Runnable setImage = new Runnable() {
#Override
public void run() {
videoFeed.setImageBitmap(bitmap);
}
};
The problem is that after about 10 or 20 jpegs are perfectly decoded in realtime, the app freezes for 400ms or so and then it continues to decode other 10/20 jpegs before another freeze...
I know that sending multiple jpegs it's not a good way for streaming video but i can only change the client (android app), not the server.
Do you have any idea for get a fluid video and avoid freezes? thanks!
Right now, you are using the three-parameter version of decodeByteArray(). Instead, switch to the four-parameter version, passing in a BitmapFactory.Options as the last value. On there, set inBitmap to be a Bitmap object that can be reused.
This requires you to maintain a small Bitmap object pool. It could be as simple as two Bitmap instances: the one that is presently being displayed and the one that you are preparing for the next "frame" of the video.
The catch is that, for API Level 18 and below, the Bitmap needs to be the same resolution (height and width in pixels). In your case, that's probably not a problem, as I would imagine that each of your bitmaps have the same resolution.
Does anyone know how to compress Ti.Utils.base64encode??
for example i have this code :
uploadFile = Ti.Filesystem.getFile(pathFile, listing[_fileCtr].toString());
uploadFileName = listing[_fileCtr].toString();
encodedFile = Ti.Utils.base64encode(uploadFile.read()).toString();
//Send Image to .NET web service
And this is the method in my web services for decompressing image from titanium (if i can compress my image before):
static byte[] Decompress(byte[] input)
{
using (MemoryStream output = new MemoryStream(input))
{
using (GZipStream zip = new GZipStream(output, CompressionMode.Decompress))
{
List<byte> bytes = new List<byte>();
int b = zip.ReadByte();
while (b != -1)
{
bytes.Add((byte)b);
b = zip.ReadByte();
}
return bytes.ToArray();
}
}
Until now, i can't find some method for compressing my byte array so i can decompress them using my .NET method..
If u guys have any information about my problem, please tell me..
Many thanks.. :)
In .Net you can use System.Convert.FromBase64String to converts the specified string, which encodes binary data as base-64 digits, to an equivalent 8-bit unsigned integer array.
System.Convert.FromBase64String(encodedString);
From my android app I am sending an image to C# server converting it to Base64
#Override
public void onPictureTaken(byte[] data, Camera camera)
{
String image = Base64.encodeToString(data, Base64.DEFAULT);
sendtoserver(image);
}
from the server side I received a string but don't know how to convert it and save it.For help I am getting this string tell me how to convert it and save it in C#
/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ
Did you try using Convert.FromBase64String(string s) ?
Source: http://msdn.microsoft.com/en-us/library/system.convert.frombase64string.aspx
UPDATE (posted here instead of in the comments, since the code would display better)
Your Base64 representation is incorrect. For the image you gave in the comments, the Base64 representation is 339801 characters long.
I used the following code to generate a Base64 representation:
string path = #"C:\1XlqZF2.jpg";
Image img = Image.FromFile(path);
byte[] arr;
using (MemoryStream ms = new MemoryStream())
{
img.Save(ms, ImageFormat.Jpeg);
arr = ms.ToArray();
}
String b64 = Convert.ToBase64String(arr);
What is the Base64 class you are using ? I couldn't find it on MSDN.
My current android applications main functionality is to pull the frames (10fps) from a recorded video using the built in camera. Whenever the user selects the video I call my class "FrameCollector" which loops through the video and pulls the frames out and stores them into an ArrayList of Bitmaps. Having this work well for a number of days had me thinking that I was on the right track, but now I'm getting the dreaded "java.lang.OutofMemoryError"
My code is as follows:
Here it is setting the MediaMetaDataRetriever to select 10 frames per second from the video path which was passed from the main class
public class FrameCollector {
MediaMetadataRetriever _mmr;
double _fps;
double _duration;
long _counter = 0;
long _incrementer;
public FrameCollector(String path, Context context)
{
try
{
_mmr = new MediaMetadataRetriever();
_mmr.setDataSource(path);
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
String fpsString = pref.getString("prefFPS", "10");
_fps = Double.parseDouble(fpsString);
_incrementer = (long) (1000000 / _fps);
String stringDuration = _mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
_duration = Double.parseDouble(stringDuration) * 1000;
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
The below method is then adding the frame at that time to a bitmap and adding the bitmap to an arraylist of bitmaps "bitFrames"
public ArrayList<Bitmap> getBitmaps()
{
try
{
ArrayList<Bitmap> bitFrames = new ArrayList<Bitmap>();
Bitmap b = _mmr.getFrameAtTime(_counter);
while (_counter < _duration && b != null)
{
bitFrames.add(b);
_counter += _incrementer;
b = _mmr.getFrameAtTime(_counter);
}
return bitFrames;
}
catch (Exception ex)
{
ex.printStackTrace();
return null;
}
}
I'm thinking my issue lies with in this method. I believe I need to decode the bitmaps before I store them into the ArrayList but I'm unsure how as
Bitmap b = BitmapFactory.decode____(_mmr.getFrameAtTime(_counter));
-- Whether it be decodeStream, decodeResource, decodeFile all bring errors.
Any help would be much appreciated
Many Thanks,
Never store Bitmaps in an ArrayList unless the number of bitmaps are very small. Bitmaps take up large amounts of memory.
I've not worked with video recording before, but I would suggest you try to get a native codec library like ffmpeg to do it for you.
If you have to grab the frames yourself, however, I suggest storing them in a fixed size buffer in memory from the camera and have a background thread which pulls bitmaps from the buffer and stores it to the disk in parallel.
It's not good to store ArrayList of Bitmaps in RAM.
Anyway if you need more than default heap size to store bitmaps in ArrayList, you can try this hack.
http://habrahabr.ru/post/139717/
It's in Russian, but I guess code is quite clear to understand.