See all 3 edits below
Update: Changed 'read()' to 'readFully()' and got some things working. 'decodeByteArray()' no longer returns null. The jpeg written to the card is actually a full image. The image is still not being drawn to my view. I will keep working and post another question if need be.
I am writing a video streaming client program that takes in images from a DataInputStream.
Because the server calls compressToJpeg() on these images, I figured I could simply take the byte array from my DataInputStream, decode it, and draw the Bitmap from decodeByteArray() to my SurfaceView. Unfortunately, that method only leaves me with decodeByteArray() returning null.
So I added an intermediate step. I created a compressFrame() method which simply takes the byte array from the stream, creates a new YuvImage instance, and uses that to call compressToJpeg(). When run, however, this method hangs on compressToJpeg and closes my client activity. There is no FC popup, and I get no errors in my log.
I have provided the run() of the thread calling the problem method, the method itself, and the log printed before the app closes.
EDIT: I've also added the ReceiverUtils.getFrame() just in case.
#Override
public void run() {
String fromServer = null;
int jpgSize;
byte[] buffer;
byte[] jpgData;
Bitmap image;
ByteArrayOutputStream jpgBaos = null;
while(isItOK && (receiver.textIn != null)){
if(!holder.getSurface().isValid()){
continue;
}
ReceiverUtils.init(holder);
//Receive 'ready' flag from camcorder
fromServer = ReceiverUtils.receiveText(receiver);
while((fromServer != null)){
Log.e("From server: ", fromServer); //logging here because of null pointers when done in Utils
if(fromServer.startsWith("ANDROID_JPG_READY")){
//Obtain size for byte array
jpgSize = Integer.parseInt(fromServer.substring(18));
Log.e("JPG SIZE", String.valueOf(jpgSize));
//Create byte array of size jpgSize
buffer = new byte[jpgSize];
Log.e("BUFFER SIZE", String.valueOf(buffer.length));
//Send flag and receive image data from camcorder
ReceiverUtils.sendText(receiver, "ANDROID_JPG_SEND");
jpgData = ReceiverUtils.receiveData(receiver, buffer);
//Compress jpgData and write result to jpgBaos
jpgBaos = ReceiverUtils.compressFrame(imgRect, jpgData);
//Decode jpgData into Bitmap
image = ReceiverUtils.getFrame(jpgBaos.toByteArray(), jpgSize);
//image = ReceiverUtils.getFrame(jpgData, jpgSize);
//Set buffer and jpgData to null since we aren't using them
buffer = null;
jpgData = null;
//Draw Bitmap to canvas
ReceiverUtils.draw(image, holder, imgRect);
//break; (testing one run-through)
}
//Receive 'ready' flag from camcorder
fromServer = ReceiverUtils.receiveText(receiver);
if(isItOK == false){
break;
}
}
//break; (testing one run-through)
}
}
This is the ReceiverUtils.compressFrame() called in the previous snippet.
/*----------------------------------------
* compressFrame(Rect imgRect, byte[] input): Creates new instance of YuvImage used to compress ARGB
* byte array data to jpeg. Returns ByteArrayOutputStream with data.
*/
public static ByteArrayOutputStream compressFrame(Rect imgRect, byte[] input){
boolean success = false;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
YuvImage yuvImage = new YuvImage(input, ImageFormat.NV21,
imgRect.width(), imgRect.height(), null);
Log.e("HEY", "HEY");
success = yuvImage.compressToJpeg(imgRect, 80, baos);
Log.e("Compression Success:", String.valueOf(success));
return baos;
}
Finally, this is the output I'm getting from my LogCat. (Beware some obviously hastily written debug logs.)
07-03 15:01:19.754: E/From server:(1634): ANDROID_JPG_READY_26907
07-03 15:01:19.754: E/JPG SIZE(1634): 26907
07-03 15:01:19.764: E/BUFFER SIZE(1634): 26907
07-03 15:01:19.764: E/To server:(1634): ANDROID_JPG_SEND
07-03 15:01:19.834: E/jpgIn(1634): Data received successfully.
07-03 15:01:19.834: E/HEY(1634): HEY
07-03 15:01:19.844: D/skia(1634): onFlyCompress
EDIT: ReceiverUtils.getFrame()
/*---------------------------------------
* getFrame(byte[] jpgData, int jpgSize): Decodes a byte array into a Bitmap and
* returns the Bitmap.
*/
public static Bitmap getFrame(byte[] jpgData, int jpgSize){
Bitmap res = null;
res = BitmapFactory.decodeByteArray(jpgData, 0, jpgSize);
Log.e("Decode success", String.valueOf(!(res == null)));
return res;
}
EDIT 2: Code before adding compression
//Compress jpgData and write result to jpgBaos
//jpgBaos = ReceiverUtils.compressFrame(imgRect, jpgData);
//Decode jpgData into Bitmap
//image = ReceiverUtils.getFrame(jpgBaos.toByteArray(), jpgSize);
image = ReceiverUtils.getFrame(jpgData, jpgSize);
EDIT 3: Image after saved to SD Card
The image that Android holds in 'jpgData' in the first code snippet is not the entire image. I can't post it due to being a new user. I added a 'writeToSD' method to test. I assume that the reason it cannot be decoded is because the majority of the image is just blank space, and only a portion of the image is there.
Related
I'm using CameraView library to preview camera in my app. I want to scan the images from camera preview. But when I'm receiving camera preview images in the byte array, I'm unable to convert the byte array into Bitmap. Please assist.
Here is the method. This method executes asynchronously. Here byte has values but bitmap is null.
private void processFrame(Frame frame) {
if (frame.getDataClass() == byte[].class) {
byte[] data = frame.getData();
Log.d("OnFrame", "bytes " + data.length);
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);
Log.d("OnFrameSize", bitmap == null ? "null" : "non-null");
}
}
Here is the log
2020-07-22 00:00:00.051 17521-18409/com.shabdkosh.android D/OnFrame: bytes 1382400
2020-07-22 00:00:00.184 17521-18409/com.shabdkosh.android D/skia: --- **Failed to create image decoder with message 'unimplemented'**
2020-07-22 00:00:00.184 17521-18409/com.shabdkosh.android D/OnFrameSize: null
Please help.
I have used this function for encoding the image.
private String encodeImage(Bitmap bm)
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG,100,baos);
byte[] b = baos.toByteArray();
String encImage = Base64.encodeToString(b, Base64.DEFAULT);
Log.d(TAG, "encodeImage: " + encImage);
return encImage;
}
This is how I created the bitmap image
setContentView(R.layout.camera);
cameraView = (CameraView) findViewById(cameras);
cameraView.setJpegQuality(2);
cameraView.setCameraListener(new CameraListener() {
#Override
public void onPictureTaken(byte[] jpeg) {
super.onPictureTaken(jpeg);
Bitmap bitmap = BitmapFactory.decodeByteArray(jpeg, 0, jpeg.length);
encodeImage(bitmap);
}
});
While decoding the byte64 string generated by this using online tools i am getting a completely black image.
this is my byte64 string
/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEB
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCBIACiADASIA
AhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA
AAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3
ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWm
p6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEA
AwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSEx
BhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElK
U1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3
uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD8GJbi
TYY/tPp+455wX/l1685HJIJNCWOO4jaSKTzR/wDXOD19icfTnK0NcRyXVtJF5pimx58GOOr+/bA6
8de61KPNijI8vrxz3+Yjpk8c9D74yDX5OfUCqsMgjkjgi83z+J57c+rn2yDz7A8c5zUUatHMfKSK
L18gNnq/t34x6c8knJe0eIDJG3lf9PHpy3oT6fnnnrVVfLzex+R/y3E59+ZB/eyP5++ax9hDvL71
/wDImVofzP7v+AXoPtEUZkj9v9eB1y3PU9sfTJweWqgJPPeaOT/VeQP0LDpz2Pr+IJzV+PzI4z5v
t/N8nqfY45xnAPJNVY444g0VzHzgf9fnVv8AAfz4P3uUgfZW8clsbiOPzfOg/f8AH+03t7D268gk
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
5A/4E+e59vfr68lWUot6K15W9FKXn5/l2dzneu
Your encode code is OK, just checked it. There is a big possibility you made mistake trying to copy your encoded string from logcat. Just place breakpoint on Log.d(), copy encoded string value and check it out again via online tools. I used this to test the result.
I don't code in Android but I think you're mixing your data up. For example the manual says decodeByteArray will "Decode an immutable bitmap from the specified byte array." so this line :
Bitmap bitmap = BitmapFactory.decodeByteArray(jpeg, 0, jpeg.length);
Would only work if jpeg array contains raw RGB colour values not actual JPEG values (since JPEG is compression math not a colour array).
Try this and see if String encImage can be displayed by some online tool. No usage of that other function private String encodeImage(Bitmap bm) since I suspect it's part of the problem...
setContentView(R.layout.camera);
cameraView = (CameraView) findViewById(cameras);
cameraView.setPictureFormat(ImageFormat.JPEG);
cameraView.setJpegQuality(2);
cameraView.setCameraListener(new CameraListener() {
#Override
public void onPictureTaken(byte[] jpeg)
{
super.onPictureTaken(jpeg);
String encImage = Base64.encodeToString(jpeg, Base64.DEFAULT); //print and test this string in some B64-to-JPEG decoder/viewer
//Bitmap bitmap = BitmapFactory.decodeByteArray(jpeg, 0, jpeg.length);
//encodeImage(bitmap);
}
});
I'm trying to transport the image-info from Android Camera to ROS in real-time. However, I got a OOM problem. I'm new to Android-ROS, nearly have no experiences of dealing with such problem.
Here're some information of my demo: (if you guys need more, pls comment)
1.
public class MainActivity extends RosActivity implements NodeMain, SurfaceHolder.Callback, Camera.PreviewCallback
2.Dependencies Opencv-for-Android(3.2.0).
3.ROS messages type: android_cv_bridge.
I'm trying to publish the image-messages in onPreviewFrame() function. Code like this:
#Override
public void onPreviewFrame(byte[] data, Camera camera) {
Camera.Size size = camera.getParameters().getPreviewSize();
YuvImage yuvImage = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null);
Bitmap bmp = null;
if(yuvImage != null){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
yuvImage.compressToJpeg(new Rect(0, 0, size.width, size.height), 80, baos);
bmp = BitmapFactory.decodeByteArray(baos.toByteArray(), 0, baos.size());
try{
baos.flush();
baos.close();
}
catch(IOException e){
e.printStackTrace();
}
image = imagePublisher.newMessage();
Time curTime = connectedNode.getCurrentTime();
image.setEncoding("rgba8");
image.getHeader().setStamp(curTime);
image.getHeader().setFrameId("camera");
curTime = null;
if(isOpenCVInit){
Mat mat_image = new Mat(bmp.getHeight(), bmp.getWidth(), CvType.CV_8UC4, new Scalar(0));
Bitmap copyBmp = bmp.copy(Bitmap.Config.ARGB_8888, true);
// bitmap to mat
Utils.bitmapToMat(copyBmp, mat_image);
// mat to cvImage
CvImage cvImage = new CvImage(image.getHeader(), "rgba8", mat_image);
try {
imagePublisher.publish(cvImage.toImageMsg(image));
} catch (IOException e) {
e.printStackTrace();
}
mat_image.release();
mat_image = null;
if(!bmp.isRecycled()) {
bmp.recycle();
bmp = null;
}
if(!copyBmp.isRecycled()) {
copyBmp.recycle();
copyBmp = null;
}
cvImage =null;
image = null;
}
}
yuvImage = null;
System.gc();
}
The imagePublisher are initialized here:
#Override
public void onStart(ConnectedNode connectedNode) {
this.connectedNode = connectedNode;
imagePublisher = connectedNode.newPublisher(topic_name, sensor_msgs.Image._TYPE);
}
Well, I had try my best to avoid the OOM problem. I had also trying to not apply the OpenCV, and just dealing with the bitmap like this:
ChannelBufferOutputStream cbos = new ChannelBufferOutputStream(MessageBuffers.dynamicBuffer());
bmp.compress(Bitmap.CompressFormat.JPEG, 80, baos);
cbos.buffer().writeBytes(baos.toByteArray());
image.setData(cbos.buffer().copy());
cbos.buffer().clear();
imagePublisher.publish(image);
Unfortunately, it's get worse. I'm doubt the way I'm trying to achieve this target. Or is there a better way to do?
I think your problem might be that your network can't transfer this amount of image data and the OOM is caused by the data stuck in buffers that is not yet transferred.
I had similar issues when I wanted to transfer image from my android device. If your problem is the same, you could solve it in several ways:
transfer data via usb tethering, it's generally much faster than wifi or cellular and can transfer even raw image stream without compression with 30 fps 640x480. For Jpeg I think you will be able to stream FullHD at 30 fps.
save data on the phone to a ROS Bag http://wiki.ros.org/rosbag and then work with the data. Here you miss realtime, but sometimes it's not needed. To make it I actually wrote an application for android https://github.com/lamerman/ros_android_bag and you can also download it directly from Google Play https://play.google.com/store/apps/details?id=org.lamerman.rosandroidbag&hl=en
try to decrease the bandwidth even further (decrease image size, fps) or increase the network quality
About your second attempt with transferring JPEG instead of RAW data, have a look at this source code, here it's implemented correctly https://github.com/rosjava/android_core/blob/kinetic/android_10/src/org/ros/android/view/camera/CompressedImagePublisher.java#L80
The problem of transferring via network is for sure actual for raw images, but may also be for compressed ones if the size of image is big and the frame rate is high.
What I wanted to achieve is being able to calculate the height and width of a Bitmap from an inputstream without actually changing BitmapFactory.Options
This is what I did:
private Boolean testSize(InputStream inputStream){
BitmapFactory.Options Bitmp_Options = new BitmapFactory.Options();
Bitmp_Options.inJustDecodeBounds = true;
BitmapFactory.decodeResourceStream(getResources(), new TypedValue(), inputStream, new Rect(), Bitmp_Options);
int currentImageHeight = Bitmp_Options.outHeight;
int currentImageWidth = Bitmp_Options.outWidth;
if(currentImageHeight > 200 || currentImageWidth > 200){
Object obj = map.remove(pageCounter);
Log.i("Page recycled", obj.toString());
return true;
}
return false;
}
Now the main problem here is that it changes the BitmapFactory.Options to a state that can't decodeStream properly.
My question is there another way of resetting BitmapFactory.Options? or another possible solution?
Another method: (Note* that originalBitmap is null when the top method is applied)
This is was my original code:
Bitmap originalBitmap = BitmapFactory.decodeStream(InpStream);
Applying Deev's and Nobu Game's suggestion: (no change)
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = false;
Bitmap originalBitmap = BitmapFactory.decodeStream(InpStream,null,options);
You are attempting to read from the same stream twice. A stream doesn't work as a byte array. Once you've read data from it, you cannot read it again unless you reset the stream position. You can try to call InputStream.reset() after your first call to decodeStream() but not all InputStreams support this method.
If you are trying to reuse your Options object (which is not the case in your code sample by the way), then how are you trying to reuse it? What is the error message, what goes wrong?
Are you trying to reuse the Options object for actually decoding the Bitmap? Then just set inJustDecodeBounds to false.
A simple class to copy InputStream when inputStream.Mark and inputStream.Reset doesn't work.
To call:
CopyInputStream copyStream = new CopyInputStream(zip);
InputStream inputStream = copyStream.getIS();
I hope this helps someone. Here is the code.
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
public class CopyInputStream {
private InputStream inputStream;
private ByteArrayOutputStream byteOutPutStream;
/*
* Copies the InputStream to be reused
*/
public CopyInputStream(InputStream is){
this.inputStream = is;
try{
int chunk = 0;
byte[] data = new byte[256];
while(-1 != (chunk = inputStream.read(data)))
{
byteOutPutStream.write(data, 0, chunk);
}
}catch (Exception e) {
// TODO: handle exception
}
}
/*
* Calls the finished inputStream
*/
public InputStream getIS(){
return (InputStream)new ByteArrayInputStream(byteOutPutStream.toByteArray());
}
}
I'm developing an Android App that should send an image to my ASP.NET Web Service where the image will be saved as a file. I've seen a couple of ways to do this and I went for this one: convert the image to a byte array -> convert the byte array to a string -> send the string to the web service using KSOAP2 -> receive the String at the Web Service -> convert it to a byte array ->
Save it as an image:
IVtest = (ImageView)findViewById(R.id.carticon);
BitmapDrawable drawable = (BitmapDrawable) IVtest.getDrawable();
Bitmap bitmap = drawable.getBitmap();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] data = baos.toByteArray();
ImageView image=new ImageView(this);
image.setImageBitmap(bmp);
String strBase64 = Base64.encode(data);
Then I send strBase64 to the web service.
In the Web Service I have this:
public Image ConvertToImage(byte[] image)
{
MemoryStream ms = new MemoryStream(image);
Image returnImage = Image.FromStream(ms);
return returnImage;
}
[WebMethod]
public String UploadImage(String image, String name)
{
byte[] image_byte = Encoding.Unicode.GetBytes(image);
Image convertedImage = ConvertToImage(image_byte);
try {
convertedImage.Save(Server.MapPath("generated_image.jpg"), System.Drawing.Imaging.ImageFormat.Jpeg);
} catch (Exception e) {
return e.Message;
}
return "Success";
}
I get an error at this line: Image returnImage = Image.FromStream(ms);
This is the error I get:
SoapFault - faultcode: 'soap:Server' faultstring: 'System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.ArgumentException: Parameter is not valid.
at System.Drawing.Image.FromStream(Stream stream, Boolean useEmbeddedColorManagement, Boolean validateImageData)
at System.Drawing.Image.FromStream(Stream stream)
at Service.ConvertToImage(Byte[] image) in e:\FTP\nvm\Service.asmx:line 1366
at Service.UploadImage(String image, String name) in e:\FTP\nvm\Service.asmx:line 1374
--- End of inner exception stack trace ---' faultactor: 'null' detail: org.kxml2.kdom.Node#437bf7b0
Thanks
Seems like there is something iffy with your conversion from string to image. Also you are not disposing your stream which will leak memory.
Try this instead:
private Image Base64ToImage(string base64String)
{
// Convert Base64 String to byte[]
byte[] imageBytes = Convert.FromBase64String(base64String);
using (var ms = new MemoryStream(imageBytes, 0,
imageBytes.Length))
{
// Convert byte[] to Image
ms.Write(imageBytes, 0, imageBytes.Length);
Image image = Image.FromStream(ms, true);
return image;
}
}