We can speed up scaled-down rendering of JPEG images by asking libjpeg
to only decode the image to a fraction of the original size.
---
.../idirectfbimageprovider_jpeg.c | 79 +++++++++++++-------
1 files changed, 52 insertions(+), 27 deletions(-)
diff --git a/interfaces/IDirectFBImageProvider/idirectfbimageprovider_jpeg.c
b/interfaces/IDirectFBImageProvider/idirectfbimageprovider_jpeg.c
index e67da17..6b6aef3 100644
--- a/interfaces/IDirectFBImageProvider/idirectfbimageprovider_jpeg.c
+++ b/interfaces/IDirectFBImageProvider/idirectfbimageprovider_jpeg.c
@@ -83,9 +83,12 @@ typedef struct {
DIRenderCallback render_callback;
void *render_callback_context;
- u32 *image;
- int width;
- int height;
+ int width; /* width of the JPEG image */
+ int height; /* height of the JPEG image */
+
+ u32 *image; /* decoded image data */
+ int image_width; /* width of image data */
+ int image_height; /* height of image data */
CoreDFB *core;
} IDirectFBImageProvider_JPEG_data;
@@ -157,7 +160,7 @@ buffer_fill_input_buffer (j_decompress_ptr cinfo)
else {
ret = buffer->GetData( buffer, JPEG_PROG_BUF_SIZE, src->data,
&nbytes );
}
-
+
if (ret || nbytes <= 0) {
/* Insert a fake EOI marker */
src->data[0] = (JOCTET) 0xFF;
@@ -302,7 +305,7 @@ Construct( IDirectFBImageProvider *thiz,
{
struct jpeg_decompress_struct cinfo;
struct my_error_mgr jerr;
-
+
IDirectFBDataBuffer *buffer;
CoreDFB *core;
va_list tag;
@@ -336,10 +339,10 @@ Construct( IDirectFBImageProvider *thiz,
jpeg_buffer_src(&cinfo, buffer, 1);
jpeg_read_header(&cinfo, TRUE);
jpeg_start_decompress(&cinfo);
-
+
data->width = cinfo.output_width;
data->height = cinfo.output_height;
-
+
jpeg_abort_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
@@ -424,7 +427,7 @@ IDirectFBImageProvider_JPEG_RenderTo(
IDirectFBImageProvider *thiz,
if (dest_rect) {
if (dest_rect->w < 1 || dest_rect->h < 1)
return DFB_INVARG;
-
+
rect = *dest_rect;
rect.x += dst_data->area.wanted.x;
rect.y += dst_data->area.wanted.y;
@@ -440,6 +443,14 @@ IDirectFBImageProvider_JPEG_RenderTo(
IDirectFBImageProvider *thiz,
if (ret)
return ret;
+ if (data->image &&
+ (rect.x || rect.y || rect.w != data->image_width || rect.h !=
data->image_height)) {
+ D_FREE( data->image );
+ data->image = NULL;
+ data->image_width = 0;
+ data->image_height = 0;
+ }
+
/* actual loading and rendering */
if (!data->image) {
struct jpeg_decompress_struct cinfo;
@@ -459,11 +470,11 @@ IDirectFBImageProvider_JPEG_RenderTo(
IDirectFBImageProvider *thiz,
jpeg_destroy_decompress(&cinfo);
if (data->image) {
- dfb_scale_linear_32( data->image, data->width,
data->height,
+ dfb_scale_linear_32( data->image, data->image_width,
data->image_height,
lock.addr, lock.pitch, &rect,
dst_surface, &clip );
dfb_surface_unlock_buffer( dst_surface, &lock );
if (data->render_callback) {
- DFBRectangle r = { 0, 0, data->width, data->height };
+ DFBRectangle r = { 0, 0, data->image_width,
data->image_height };
if (data->render_callback( &r,
data->render_callback_context ) != DIRCR_OK)
return DFB_INTERRUPTED;
@@ -480,10 +491,24 @@ IDirectFBImageProvider_JPEG_RenderTo(
IDirectFBImageProvider *thiz,
jpeg_create_decompress(&cinfo);
jpeg_buffer_src(&cinfo, data->buffer, 0);
jpeg_read_header(&cinfo, TRUE);
+
+ cinfo.scale_num = 1;
+ cinfo.scale_denom = 1;
jpeg_calc_output_dimensions(&cinfo);
- if (cinfo.output_width == rect.w && cinfo.output_height == rect.h)
+ data->width = cinfo.output_width;
+ data->height = cinfo.output_height;
+
+ if (cinfo.output_width == rect.w && cinfo.output_height == rect.h) {
direct = true;
+ }
+ else if (rect.x == 0 && rect.y == 0) {
+ while (cinfo.scale_denom < 16 &&
+ (cinfo.output_width >> 1) > rect.w &&
(cinfo.output_height >> 1) > rect.h) {
+ cinfo.scale_denom <<= 1;
+ jpeg_calc_output_dimensions (&cinfo);
+ }
+ }
cinfo.output_components = 3;
@@ -499,7 +524,7 @@ IDirectFBImageProvider_JPEG_RenderTo(
IDirectFBImageProvider *thiz,
}
D_INFO( "JPEG: Going through RGB color space! (%dx%d ->
%dx%d @%d,%d)\n",
cinfo.output_width, cinfo.output_height, rect.w,
rect.h, rect.x, rect.y );
-
+
default:
cinfo.out_color_space = JCS_RGB;
break;
@@ -507,15 +532,15 @@ IDirectFBImageProvider_JPEG_RenderTo(
IDirectFBImageProvider *thiz,
jpeg_start_decompress(&cinfo);
- data->width = cinfo.output_width;
- data->height = cinfo.output_height;
+ data->image_width = cinfo.output_width;
+ data->image_height = cinfo.output_height;
row_stride = cinfo.output_width * 3;
buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo,
JPOOL_IMAGE, row_stride, 1);
- data->image = D_CALLOC( data->height, data->width * 4 );
+ data->image = D_CALLOC( data->image_height, data->image_width * 4 );
if (!data->image) {
dfb_surface_unlock_buffer( dst_surface, &lock );
return D_OOM();
@@ -533,39 +558,39 @@ IDirectFBImageProvider_JPEG_RenderTo(
IDirectFBImageProvider *thiz,
lock.addr += lock.pitch;
if (data->render_callback) {
- DFBRectangle r = { 0, y, data->width, 1 };
+ DFBRectangle r = { 0, y, data->image_width,
1 };
- cb_result = data->render_callback( &r,
+ cb_result = data->render_callback( &r,
data->render_callback_context );
}
break;
}
default:
- copy_line32( row_ptr, *buffer, data->width);
+ copy_line32( row_ptr, *buffer, data->image_width);
if (direct) {
DFBRectangle r = { rect.x, rect.y+y, rect.w, 1 };
dfb_copy_buffer_32( row_ptr, lock.addr,
lock.pitch,
&r, dst_surface, &clip );
if (data->render_callback) {
- r = (DFBRectangle){ 0, y, data->width, 1 };
- cb_result = data->render_callback( &r,
+ r = (DFBRectangle){ 0, y,
data->image_width, 1 };
+ cb_result = data->render_callback( &r,
data->render_callback_context );
}
}
break;
}
- row_ptr += data->width;
+ row_ptr += data->image_width;
y++;
}
if (!direct) {
- dfb_scale_linear_32( data->image, data->width, data->height,
+ dfb_scale_linear_32( data->image, data->image_width,
data->image_height,
lock.addr, lock.pitch, &rect, dst_surface,
&clip );
if (data->render_callback) {
- DFBRectangle r = { 0, 0, data->width, data->height };
+ DFBRectangle r = { 0, 0, data->image_width,
data->image_height };
cb_result = data->render_callback( &r,
data->render_callback_context );
}
}
@@ -581,14 +606,14 @@ IDirectFBImageProvider_JPEG_RenderTo(
IDirectFBImageProvider *thiz,
jpeg_destroy_decompress(&cinfo);
}
else {
- dfb_scale_linear_32( data->image, data->width, data->height,
+ dfb_scale_linear_32( data->image, data->image_width,
data->image_height,
lock.addr, lock.pitch, &rect, dst_surface,
&clip );
if (data->render_callback) {
- DFBRectangle r = { 0, 0, data->width, data->height };
+ DFBRectangle r = { 0, 0, data->image_width, data->image_height
};
data->render_callback( &r, data->render_callback_context );
}
}
-
+
dfb_surface_unlock_buffer( dst_surface, &lock );
if (cb_result != DIRCR_OK)
@@ -615,7 +640,7 @@ IDirectFBImageProvider_JPEG_GetSurfaceDescription(
IDirectFBImageProvider *thiz,
DFBSurfaceDescription *dsc
)
{
DIRECT_INTERFACE_GET_DATA(IDirectFBImageProvider_JPEG)
-
+
dsc->flags = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT;
dsc->height = data->height;
dsc->width = data->width;
--
1.6.0.4
_______________________________________________
directfb-dev mailing list
[email protected]
http://mail.directfb.org/cgi-bin/mailman/listinfo/directfb-dev