Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Native Development

Reply
Highlighted
Developer
Posts: 121
Registered: ‎02-08-2013
My Device: 9900
My Carrier: verizon
Accepted Solution

Dumping screen to jpeg

Hi,

 

I am able to capture a screenshot of my application screen using code from sample in docs (see below). My question is how can I get the data from screenshot to jpeg data ready to post to server - I prefer not to have to save to bmp file and then open the file for encoding to jpeg if possible.

 

screen_read_window(window, screenshot_buf, 0, NULL ,0);
fd = creat(fname, S_IRUSR | S_IWUSR);

nbytes = size[0] * size[1] * 4;
write_bitmap_header(nbytes, fd, size);

for (i = 0; i < size[1]; i++) {
write(fd, screenshot_ptr + i * screenshot_stride, size[0] * 4);
}

close(fd);
screen_destroy_pixmap(screen_pix);

 

Developer
Posts: 1,523
Registered: ‎12-18-2012
My Device: Z30, Z10 LE, DevAlpha C, PlayBook

Re: Dumping screen to jpeg

[ Edited ]

Hi,

 

I haven't tried to do this, but I think QPixmap can be used for conversion. Try storing the image in QByteArray and loading it into QPixmap, then saving it using .save("filename.jpg") method. It's also possible to save the result into a buffer.

 

Also there are bundled libpng & libjpeg libs. Take a look at write_JPEG_file function in this example:

http://code.google.com/p/sumatrapdf/source/browse/trunk/ext/libjpeg-turbo/example.c?r=2397

 


Andrey Fidrya, @zmeyc on twitter
Developer
Posts: 121
Registered: ‎02-08-2013
My Device: 9900
My Carrier: verizon

Re: Dumping screen to jpeg

Thank you very much for your reply, I am still new coming from Java and can't work out how to get a QByteArray from the data that is currently being written directly to fd. Would you mind giving me a hint please?

Developer
Posts: 1,523
Registered: ‎12-18-2012
My Device: Z30, Z10 LE, DevAlpha C, PlayBook

Re: Dumping screen to jpeg

If you're following this tutorial

http://developer.blackberry.com/native/documentation/bb10/com.qnx.doc.screen/topic/manual/tscreen_wi...

 

there is write_bitmap_header() implementation which will be also needed:

http://www.qnx.com/developers/docs/qnxcar2/index.jsp?topic=%2Fcom.qnx.doc.qnxcar2.screen%2Ftopic%2Fm...

 

I think fully-constructed bitmap (with the header) should be passed to QPixmap so it can recognize it as bitmap.

 

QByteArray docs:

http://qt-project.org/doc/qt-4.8/qbytearray.html

 

Basically just construct the bytearray (as a member variable or on stack):

#include <QByteArray>
...
QByteArray array;

 

Then append header and data to it instead of writing to a file:

array.append(data, dataSize);
...
QPixmap pixmap;
pixmap.loadFromData(array, "BMP");
QByteArray out;
QBuffer buffer(&out);
pixmap.save(buffer, "JPG");

 

Please tell if it works.

 


Andrey Fidrya, @zmeyc on twitter
Developer
Posts: 121
Registered: ‎02-08-2013
My Device: 9900
My Carrier: verizon

Re: Dumping screen to jpeg

[ Edited ]

Thanks for your reply - The code helps a lot. Could you have a look at my way of appending data to array as there is no "data" at first in the sample. I am writing bitmap gheader by the way and have been able to view the bmp when just saving to fd (file).

 

Also, including pixmap.save(buffer, "JPG") gives compiler error and I got a seg fault at loadFromData() when trying first couple of times with pixmap.save(buffer, "JPG") commented out.

 

for (i = 0; i < size[1]; i++) {

ba.append(screenshot_ptr + i * screenshot_stride);
}

close(fd);
screen_destroy_pixmap(screen_pix);
QPixmap pixmap;
pixmap.loadFromData(ba, "BMP");
QByteArray out;
QBuffer buffer(&out);
pixmap.save(buffer, "JPG");

 

Thanks again.

Developer
Posts: 1,523
Registered: ‎12-18-2012
My Device: Z30, Z10 LE, DevAlpha C, PlayBook

Re: Dumping screen to jpeg

[ Edited ]

The correct code would be:

 

ba.append(screenshot_ptr + i * screenshot_stride, size[0] * 4);

 

Saving to the buffer:

 

QByteArray out;
QBuffer buffer(&out);
buffer.open(QIODevice::WriteOnly); 
pixmap.save(&buffer, "JPEG");

 

If it won't compile please paste the error message.

 

UPD:

It seems QImage is a better choice as QPixmap is optimized for showing images on screen.

http://qt-project.org/doc/qt-4.8/qimage.html

 

QImage even has a constructor for initializing the instance with raw data-

 

QImage ( uchar * data, int width, int height, Format format )

 

Something like this should work (if ba is raw pixel data without header):

 

QImage image(ba.data(), imageWidth, imageHeight, QImage::Format_ARGB32);

 

Formats available:

http://qt-project.org/doc/qt-4.8/qimage.html#Format-enum

 


Andrey Fidrya, @zmeyc on twitter
Developer
Posts: 121
Registered: ‎02-08-2013
My Device: 9900
My Carrier: verizon

Re: Dumping screen to jpeg

It compiles now but I can't get past loadFromData() because it throws seg fault with crash being at..

QGraphicsSystem::createDefaultPixmapData() at 0x79ed5d86 I will post my code in case I haven't followed you properly.

 

QByteArray ba;
	nbytes = size[0] * size[1] * 4;
	write_bitmap_header(nbytes, ba, size);

	for (i = 0; i < size[1]; i++) {

		ba.append(screenshot_ptr + i * screenshot_stride, size[0] * 4);
	}

	
	screen_destroy_pixmap(screen_pix);
	QPixmap pixmap;
	pixmap.loadFromData(ba, "BMP");
	QByteArray out;
	QBuffer buffer(&out);
	pixmap.save(&buffer, "JPEG");

void App::write_bitmap_header(int nbytes, QByteArray ba, const int size[])
{
	char header[54];

	/* Set standard bitmap header */
	header[0] = 'B';
	header[1] = 'M';
	header[2] = nbytes & 0xff;
	header[3] = (nbytes >> 8) & 0xff;
	header[4] = (nbytes >> 16) & 0xff;
	header[5] = (nbytes >> 24) & 0xff;
	header[6] = 0;
	header[7] = 0;
	header[8] = 0;
	header[9] = 0;
	header[10] = 54;
	header[11] = 0;
	header[12] = 0;
	header[13] = 0;
	header[14] = 40;
	header[15] = 0;
	header[16] = 0;
	header[17] = 0;
	header[18] = size[0] & 0xff;
	header[19] = (size[0] >> 8) & 0xff;
	header[20] = (size[0] >> 16) & 0xff;
	header[21] = (size[0] >> 24) & 0xff;
	header[22] = -size[1] & 0xff;
	header[23] = (-size[1] >> 8) & 0xff;
	header[24] = (-size[1] >> 16) & 0xff;
	header[25] = (-size[1] >> 24) & 0xff;
	header[26] = 1;
	header[27] = 0;
	header[28] = 32;
	header[29] = 0;
	header[30] = 0;
	header[31] = 0;
	header[32] = 0;
	header[33] = 0;
	header[34] = 0; /* image size*/
	header[35] = 0;
	header[36] = 0;
	header[37] = 0;
	header[38] = 0x9;
	header[39] = 0x88;
	header[40] = 0;
	header[41] = 0;
	header[42] = 0x9l;
	header[43] = 0x88;
	header[44] = 0;
	header[45] = 0;
	header[46] = 0;
	header[47] = 0;
	header[48] = 0;
	header[49] = 0;
	header[50] = 0;
	header[51] = 0;
	header[52] = 0;
	header[53] = 0;

	/* Write bitmap header to file */
	ba.append(header);//write(fd, header, sizeof(header));
}

 

Developer
Posts: 1,523
Registered: ‎12-18-2012
My Device: Z30, Z10 LE, DevAlpha C, PlayBook

Re: Dumping screen to jpeg

[ Edited ]
void App::write_bitmap_header(int nbytes, QByteArray ba, const int size[])

 This will make a copy of bytearray. Pass it by reference instead:

 

void App::write_bitmap_header(int nbytes, QByteArray &ba, const int size[])

 

 

Always specify the size in .append otherwise it will treat the buffer as zero-terminated string. For plain C arrays size in bytes can be obtained using sizeof():

 

ba.append(header, sizeof(header));

 I'll PM my email, please send me a test project.

 

I've updated my previous post with details on using QImage instead of QPixmap, please take a look.

 


Andrey Fidrya, @zmeyc on twitter
Developer
Posts: 121
Registered: ‎02-08-2013
My Device: 9900
My Carrier: verizon

Re: Dumping screen to jpeg

Thanks ZMey,

 

I seen your suggestion to use QImage after posting last message so been working with that for 5 mins and got past the seg fault by changing to QByteArray &ba and by using sizeof() in writeHeader(). I just checked the size of the array before and after save() and it is 0 after and same with buffer - both return 0 for size() when I'm hoping for jpeg dta in the array.

 

Can see anything before I send the project to you as requested?

 

 QByteArray ba;
	nbytes = size[0] * size[1] * 4;
	write_bitmap_header(nbytes, ba, size);

	for (i = 0; i < size[1]; i++) {

		ba.append(screenshot_ptr + i * screenshot_stride, size[0] * 4);
	}

	//close(fd);
	cout << "sizeof array=" << ba.size();
		cout.flush();
	screen_destroy_pixmap(screen_pix);
	QImage image(ba.data());//, 200, 200, QImage::Format_ARGB32);
	QByteArray out;
	QBuffer buffer(&out);
	image.save(&buffer, "JPEG");
	cout << "sizeof array=" << out.size();
	cout.flush();

 

Developer
Posts: 1,523
Registered: ‎12-18-2012
My Device: Z30, Z10 LE, DevAlpha C, PlayBook

Re: Dumping screen to jpeg

QImage image(ba.data());//, 200, 200, QImage::Format_ARGB32);

This resolves to wrong constructor (the one taking a string).

 

Could you try:

QImage image = QImage::fromData(ba, "BMP");
or
QImage image = QImage::fromData(ba);

 


Andrey Fidrya, @zmeyc on twitter