wxImage from JPEG memory array Topic is solved

Talk here about issues with one of the components hosted at wxCode, or suggest features for it.
Post Reply
delapol
In need of some credit
In need of some credit
Posts: 2
Joined: Thu Mar 06, 2008 11:23 am

wxImage from JPEG memory array

Post by delapol »

Hi!

I need to display a JPEG image stored as a buffer. So far I used jpeg library (from www.ijg.org) to decompress JPEG to RGB and then I am using WxImage::SetData(unsigned char * ) to render the image. It does not work yet: only the first line is displayed, probably I am reading the data in the wrong way.

The use case is as follows:
1) retreive the content of a whole JPEG file as [unsigned char array]
2) display it on the screen

I don't want to save as jpeg file and then load jpeg from disk.

A) Is there any other way to do this using only wxWidgets components, like wxImage::SetJPEGData(...) or JPEG2RGB ?

B) What exactly is the expected format of data in the wxImage::SetData call ? RGB 24 ?

Thanks!
utelle
Moderator
Moderator
Posts: 1128
Joined: Tue Jul 05, 2005 10:00 pm
Location: Cologne, Germany
Contact:

Re: wxImage from JPEG memory array

Post by utelle »

delapol wrote:The use case is as follows:
1) retreive the content of a whole JPEG file as [unsigned char array]
2) display it on the screen

I don't want to save as jpeg file and then load jpeg from disk.

A) Is there any other way to do this using only wxWidgets components, like wxImage::SetJPEGData(...) or JPEG2RGB ?
The answer is YES:

Code: Select all

unsigned char* jpegData; // JPEG data buffer
size_t jpegLen;          // Length in bytes/chars of the JPEG data buffer
wxMemoryInputStream jpegStream(jpegData, jpegLlen);
wxImage jpegImage;
jpegImage.LoadFile(jpegStream, wxBITMAP_TYPE_JPEG);

// Display jpegImage on screen
delapol wrote:B) What exactly is the expected format of data in the wxImage::SetData call ? RGB 24 ?
The data need to be an array of characters in RGBRGBRGB... format in top-to-bottom, left-to-right order, that is the first RGB triplet corresponds to the first pixel of the first row, the second RGB triple to the second pixel of the first row and so on until the end of the first row, with second row following after it and so on.

Regards,

Ulrich
delapol
In need of some credit
In need of some credit
Posts: 2
Joined: Thu Mar 06, 2008 11:23 am

Re: wxImage from JPEG memory array

Post by delapol »

Much better than my previous attempt to use libjpeg ;-)

If I need to do subsequent updates of the image (3-4 times / second) what would be your recommendation:

1) a new wxMemoryInputStream object every time ?
2) can I "clean" the wxMemoryInputStream object and fill in new data (and data length), refresh graphics, etc. ?
3) any better way ?

Thanks!
utelle
Moderator
Moderator
Posts: 1128
Joined: Tue Jul 05, 2005 10:00 pm
Location: Cologne, Germany
Contact:

Re: wxImage from JPEG memory array

Post by utelle »

delapol wrote:If I need to do subsequent updates of the image (3-4 times / second) what would be your recommendation:

1) a new wxMemoryInputStream object every time ?
2) can I "clean" the wxMemoryInputStream object and fill in new data (and data length), refresh graphics, etc. ?
3) any better way ?
I don't know of a way to "clean" a wxMemoryInputStream object other than to create a new object. If you get your image data always as JPEG I don't see a better way at the moment. If you could change the image data source to deliver raw bitmaps you maybe could gain a bit of performance. But for 3 to 4 updates per second the given solution should be sufficient.

Regards,

Ulrich
xin.songtao
Experienced Solver
Experienced Solver
Posts: 86
Joined: Wed Apr 18, 2007 6:10 am
Location: Shanghai China

Post by xin.songtao »

hi,friend! I met a question as yours.My code is below:

Code: Select all

        wxInitAllImageHandlers();
        wxString str = wxFileSelector(); //Select a jpeg image from the disk
	wxImage image(str);						
	image.SetOption(wxIMAGE_OPTION_QUALITY,10);	

	int w =image.GetWidth();
	int h = image.GetHeight();	
	wxMemoryInputStream jpegStream(image.GetData(), w*h*3);
	wxImage jpegImage;
	jpegImage.LoadFile(jpegStream, wxBITMAP_TYPE_JPEG); 
I also want to decompress JPEG in time, and display it on the screen .
but the code takes no effect,and alert a error "Image file is not of type 17 ",but I have called the

Code: Select all

wxInitAllImageHandlers();
what's wrong ? Could you help me?

Thanks in advance
utelle
Moderator
Moderator
Posts: 1128
Joined: Tue Jul 05, 2005 10:00 pm
Location: Cologne, Germany
Contact:

Post by utelle »

xin.songtao wrote:hi,friend! I met a question as yours.My code is below:

Code: Select all

        wxInitAllImageHandlers();
        wxString str = wxFileSelector(); //Select a jpeg image from the disk
	wxImage image(str);						
	image.SetOption(wxIMAGE_OPTION_QUALITY,10);	

	int w =image.GetWidth();
	int h = image.GetHeight();	
	wxMemoryInputStream jpegStream(image.GetData(), w*h*3);
	wxImage jpegImage;
	jpegImage.LoadFile(jpegStream, wxBITMAP_TYPE_JPEG); 
I also want to decompress JPEG in time, and display it on the screen. but the code takes no effect,and alert a error "Image file is not of type 17 ",but I have called the

Code: Select all

wxInitAllImageHandlers();
what's wrong?
Unfortunately you did not tell at which statement you got the error message. If the statement

Code: Select all

wxImage image(str);
leads to an error, the selected file is not a valid graphics file.

If the statement

Code: Select all

jpegImage.LoadFile(jpegStream, wxBITMAP_TYPE_JPEG);
fails, then the explanation would be simple:

jpegStream definitely does not contain a valid jpeg stream. Instead you have a stream of RGB triples. BTW I really don't understand the purpose of your code, since you already have your graphics file loaded into variable image.

Regards,

Ulrich
xin.songtao
Experienced Solver
Experienced Solver
Posts: 86
Joined: Wed Apr 18, 2007 6:10 am
Location: Shanghai China

Post by xin.songtao »

hi! Thanks for your reply very very quickly! :)

While, I think I have not make clear to you,sorry.

I want to decommpress a jpeg image by the API

Code: Select all

image.SetOption(wxIMAGE_OPTION_QUALITY,10);   
and then display the image which has decompressed on the screen.

I think I have to use the wxInputStream to Create a wxImage Object, and CovertoBitmap to DrawBitmap.

also, this method can achieve.

Code: Select all

image.SetOption(wxIMAGE_OPTION_QUALITY,10);   
image.SaveFile(_T("save.jpeg"));
wxBitmap bitmap(_T("save.jpeg"));
but it will save as jpeg file and then load jpeg from disk.
xin.songtao
Experienced Solver
Experienced Solver
Posts: 86
Joined: Wed Apr 18, 2007 6:10 am
Location: Shanghai China

Post by xin.songtao »

utelle wrote:
xin.songtao wrote:hi,friend! I met a question as yours.My code is below:

Code: Select all

        wxInitAllImageHandlers();
        wxString str = wxFileSelector(); //Select a jpeg image from the disk
	wxImage image(str);						
	image.SetOption(wxIMAGE_OPTION_QUALITY,10);	

	int w =image.GetWidth();
	int h = image.GetHeight();	
	wxMemoryInputStream jpegStream(image.GetData(), w*h*3);
	wxImage jpegImage;
	jpegImage.LoadFile(jpegStream, wxBITMAP_TYPE_JPEG); 
I also want to decompress JPEG in time, and display it on the screen. but the code takes no effect,and alert a error "Image file is not of type 17 ",but I have called the

Code: Select all

wxInitAllImageHandlers();
what's wrong?
Unfortunately you did not tell at which statement you got the error message. If the statement

Code: Select all

wxImage image(str);
leads to an error, the selected file is not a valid graphics file.

If the statement

Code: Select all

jpegImage.LoadFile(jpegStream, wxBITMAP_TYPE_JPEG);
fails, then the explanation would be simple:

jpegStream definitely does not contain a valid jpeg stream. Instead you have a stream of RGB triples. BTW I really don't understand the purpose of your code, since you already have your graphics file loaded into variable image.

Regards,

Ulrich
I have a jpeg file which has not compressed, and I want to show the "Compressed image",so ,I use

Code: Select all

wxMemoryInputStream jpegStream(image.GetData(), w*h*3);
to create a wxImage.
utelle
Moderator
Moderator
Posts: 1128
Joined: Tue Jul 05, 2005 10:00 pm
Location: Cologne, Germany
Contact:

Post by utelle »

xin.songtao wrote:I want to decommpress a jpeg image by the API

Code: Select all

image.SetOption(wxIMAGE_OPTION_QUALITY,10);   
and then display the image which has decompressed on the screen.
I still don't understand what you really want to achieve. Using a wxImage constructor with a file name or using the mathod LoadFile gives you a decompressed image in memory, that is, an wxImage instance allocates internally a buffer for storing all width x height RGB tuples.

The option wxIMAGE_OPTION_QUALITY does not take effect until you save the wxImage instance to a file. And the result will be a JPEG file quite small in file size due to the extremly low quality but still describing an image of width x height pixels.
xin.songtao wrote:I think I have to use the wxInputStream to Create a wxImage Object, and CovertoBitmap to DrawBitmap.
As stated in the wxWidgets manual you should use a wxBitmap constructor to create a bitmap corresponding to your wxImage object:
http://docs.wxwidgets.org/2.8/wx_wximag ... rttobitmap
http://docs.wxwidgets.org/2.8/wx_wxbitm ... bitmapctor
xin.songtao wrote:also, this method can achieve.

Code: Select all

image.SetOption(wxIMAGE_OPTION_QUALITY,10);   
image.SaveFile(_T("save.jpeg"));
wxBitmap bitmap(_T("save.jpeg"));
but it will save as jpeg file and then load jpeg from disk.
The result will be a bitmap of very very low quality.

If you just want to display a JPEG file why not load it directly into a wxBitmap object using an appropriate constructor or method LoadFile?

If you need an image of reduced size load the JPEG file into an wxImage object, use method Scale and convert the result to wxBitmap.

Regards,

Ulrich
xin.songtao
Experienced Solver
Experienced Solver
Posts: 86
Joined: Wed Apr 18, 2007 6:10 am
Location: Shanghai China

Post by xin.songtao »

sorry,maybe I can make clear for you by the screenshot
Attachments
Screenshot.JPG
Screenshot.JPG (30.5 KiB) Viewed 7329 times
utelle
Moderator
Moderator
Posts: 1128
Joined: Tue Jul 05, 2005 10:00 pm
Location: Cologne, Germany
Contact:

Post by utelle »

xin.songtao wrote:sorry,maybe I can make clear for you by the screenshot
I see.

To show the effect of the compression ratio you have to do it similar to the following code:

Code: Select all

  wxInitAllImageHandlers();
  wxString str = wxFileSelector(); //Select a jpeg image from the disk
  wxImage originalImage(str);
  originalImage.SetOption(wxIMAGE_OPTION_QUALITY,10);
  // Save JPEG in reduced quality
  wxMemoryOutputStream compressedJpeg;
  originalImage.SaveFile(compressedJpeg);
  // Load just created JPEG into new image
  wxImage compressedImage(wxMemoryInputStream(compressedJpeg));
  // Convert image to bitmap for displaying
  wxBitmap bitmap(compressedImage);
Since the quality option does not have an effect until the image is saved as JPEG, calling method SaveFile can not be avoided, but using a memory stream makes it faster than creating a file on disk.

Regards,

Ulrich
xin.songtao
Experienced Solver
Experienced Solver
Posts: 86
Joined: Wed Apr 18, 2007 6:10 am
Location: Shanghai China

Post by xin.songtao »

thanks a lot! It works!
:D
Post Reply