Mat from camera jpg callback byte array

3,951 views
Skip to first unread message

Jonathan Wilson

unread,
Aug 11, 2011, 6:54:11 PM8/11/11
to android...@googlegroups.com
I was wondering if anyone has figured out how to convert java byte array passed to the Camera.PictureCallback jpegCallback. I've tried doing the same as the samples, but that byte array isn't jpeg compressed. They way I save the byte array out is

f = new FileOutputStream("/mnt/sdcard/image.jpg");
f.write(data[0]);
f.close();

So basically, is there a way to pass a memory address to imread instead of a file location to have it read from?

Aaron Brown

unread,
Aug 11, 2011, 7:12:39 PM8/11/11
to android-opencv
Caveat: I don't know much about OpenCV, but I have a bit of an Android
background.

Is there a reason why you couldn't just read the bytestream into a
Bitmap object and then convert it to a Mat? Something like:

Bitmap bmp=BitmapFactory.decodeByteArray(_data,0,_data.length);
Mat m = android.BitmapToMat(bmp);

-AMB

Jonathan Wilson

unread,
Aug 11, 2011, 8:11:07 PM8/11/11
to android...@googlegroups.com
m.size() is 0x0 if you do that, unfortunately.

Aaron Brown

unread,
Aug 11, 2011, 11:43:16 PM8/11/11
to android-opencv
Strange. Sounds like that might be a bug in the BitmapToMat method.

I re-read your original post and it seems like the problem you're
running into is that the byte array isn't JPEG compressed. Have you
tried compressing it when you write it to disk? E.g.:

Bitmap bmp=BitmapFactory.decodeByteArray(_data,0,_data.length);
f = new FileOutputStream("/mnt/sdcard/image.jpg");
bmp.compress(Bitmap.CompressFormat.JPEG,0,f);
f.close();

Jonathan Wilson

unread,
Aug 12, 2011, 2:35:01 AM8/12/11
to android...@googlegroups.com
I can write the data out directly without creating a bitmap from it. Currently I write out the jpeg data then imread it, but that is doing some /mnt/sdcard disk caching which I'd rather avoid.

Andrey Kamaev

unread,
Aug 12, 2011, 3:03:20 AM8/12/11
to android-opencv
Hi,

imdecode function should be able to decode jpeg in memory:
http://opencv.itseez.com/trunk/modules/highgui/doc/reading_and_writing_images_and_video.html#imdecode

BitmapToMat does not convert from jpeg because only
ANDROID_BITMAP_FORMAT_RGBA_8888 is supported in current
implementation.

/Andrey

Aaron Brown

unread,
Aug 21, 2011, 6:28:35 PM8/21/11
to android-opencv
Jonathan,

I now understand your issue, mostly because I just ran smack into
it myself. I got around it by creating a new Mat with size equal to
the captured image. (Decode to Bitmap, then use
Mat(bmp.getWidth(),bmp.getHeight(),1)). I then used
Mat.put(0,0,_data) to stuff the captured data into the Mat.

I then used imdecode(Mat, 1) to decode this Mat to RGB and
imdecode(Mat, 0) to decode it to grayscale. This got me past the data
type issues, but I seriously doubt the the validity of the underlying
Mats, since they get mangled going through the CascadeClassifier code
stolen from the face detection sample. (They come out the other end
with bad striping in the top three quarters and a bunch of tiled
copies of the original image running along the bottom. Also, if I
take these Mats and try to convert them right back to a bitmap using
MatToBitmap, the conversion fails.

So in summation, you get get around the datatyping issue, but I
don't know if my imdecode calls are having the intended effect of
converting my JPEG camera capture into valid Mat objects.

Heres' the code I'm using:

Bitmap bmp=BitmapFactory.decodeByteArray(_data,0,_data.length);
Mat raw = new Mat(bmp.getWidth(),bmp.getHeight(),1);
raw.put(0,0, _data);
Log.i(TAG,"raw: " + raw.rows() + " x " + raw.cols());
Mat colorMat = Highgui.imdecode(raw, 1);
Mat grayMat = Highgui.imdecode(raw, 0);

Hope this helps.

-AMB

On Aug 12, 12:03 am, Andrey Kamaev <andrey.kam...@itseez.com> wrote:
> Hi,
>
> imdecode function should be able to decodejpegin memory:http://opencv.itseez.com/trunk/modules/highgui/doc/reading_and_writin...
>
> BitmapToMat does not convert fromjpegbecause only
> ANDROID_BITMAP_FORMAT_RGBA_8888 is supported in current
> implementation.
>
> /Andrey
>
> On Aug 12, 10:35 am, Jonathan Wilson <j...@pandorica.net> wrote:
>
>
>
>
>
>
>
> > I can write the data out directly without creating a bitmap from it.
> > Currently I write out thejpegdata then imread it, but that is doing some
> > /mnt/sdcard disk caching which I'd rather avoid.
>
> > On Thu, Aug 11, 2011 at 8:43 PM, Aaron Brown <the.tarq...@gmail.com> wrote:
> > > Strange.  Sounds like that might be a bug in the BitmapToMat method.
>
> > > I re-read your original post and it seems like the problem you're
> > > running into is that the byte array isn'tJPEGcompressed.  Have you
> > > tried compressing it when you write it to disk?  E.g.:
>
> > > Bitmap bmp=BitmapFactory.decodeByteArray(_data,0,_data.length);
> > > f = new FileOutputStream("/mnt/sdcard/image.jpg");
> > > bmp.compress(Bitmap.CompressFormat.JPEG,0,f);
> > > f.close();
>
> > > On Aug 11, 5:11 pm, Jonathan Wilson <j...@pandorica.net> wrote:
> > > > m.size() is 0x0 if you do that, unfortunately.
>
> > > > On Thu, Aug 11, 2011 at 4:12 PM, Aaron Brown <the.tarq...@gmail.com>
> > > wrote:
> > > > > Caveat: I don't know much about OpenCV, but I have a bit of an Android
> > > > > background.
>
> > > > > Is there a reason why you couldn't just read the bytestream into a
> > > > > Bitmap object and then convert it to a Mat?  Something like:
>
> > > > > Bitmap bmp=BitmapFactory.decodeByteArray(_data,0,_data.length);
> > > > > Mat m = android.BitmapToMat(bmp);
>
> > > > > -AMB
>
> > > > > On Aug 11, 3:54 pm, Jonathan Wilson <j...@pandorica.net> wrote:
> > > > > > I was wondering if anyone has figured out how to convert java byte
> > > array
> > > > > > passed to the Camera.PictureCallback jpegCallback. I've tried doing
> > > the
> > > > > same
> > > > > > as the samples, but that byte array isn'tjpegcompressed. They way I

Andrey Kamaev

unread,
Aug 22, 2011, 4:09:29 AM8/22/11
to android-opencv
Hi Aaron,

As I see you don't understand the issue:

1) imdecode returns BGR (not RGB) image if you are asking for color
version.
2) you are passing wrong Mat to imdecode. Here is a correct way to
create mat:
Mat raw = new Mat(1, _data.length, CvType.CV_8U);
3) Your code is full of magic numbers. OpenCV provides constants for
all flags you need.

/Andrey

Aaron Brown

unread,
Aug 22, 2011, 9:30:30 PM8/22/11
to android-opencv
Andrey,

Thanks so much! Can you tell that I'm totally new to OpenCV? :-P

I'll change my Mat creation and go back over the documentation.

Thanks for your help!

-Aaron
Reply all
Reply to author
Forward
0 new messages