From c779eab4de7fc544b0cd3d3fffbcd0558925a1b7 Mon Sep 17 00:00:00 2001 From: Justin Maggard Date: Tue, 8 Jun 2010 17:34:29 +0000 Subject: [PATCH] * Optimize JPEG scaling by downscaling as much as possible during decompression. --- albumart.c | 8 ++++---- image_utils.c | 3 ++- image_utils.h | 2 +- metadata.c | 2 +- tivo_commands.c | 3 ++- upnphttp.c | 34 +++++++++++++++++++++++----------- 6 files changed, 33 insertions(+), 19 deletions(-) diff --git a/albumart.c b/albumart.c index dbae914..4450ba7 100644 --- a/albumart.c +++ b/albumart.c @@ -218,7 +218,7 @@ check_embedded_art(const char * path, const char * image_data, int image_size) } last_hash = hash; - imsrc = image_new_from_jpeg(NULL, 0, image_data, image_size); + imsrc = image_new_from_jpeg(NULL, 0, image_data, image_size, 1); if( !imsrc ) { last_success = 0; @@ -286,7 +286,7 @@ check_for_album_file(char * dir, const char * path) if( art_cache_exists(file, &art_file) ) goto existing_file; free(art_file); - imsrc = image_new_from_jpeg(file, 1, NULL, 0); + imsrc = image_new_from_jpeg(file, 1, NULL, 0, 1); if( imsrc ) goto found_file; } @@ -298,7 +298,7 @@ check_for_album_file(char * dir, const char * path) if( art_cache_exists(file, &art_file) ) goto existing_file; free(art_file); - imsrc = image_new_from_jpeg(file, 1, NULL, 0); + imsrc = image_new_from_jpeg(file, 1, NULL, 0, 1); if( imsrc ) goto found_file; } @@ -316,7 +316,7 @@ existing_file: return art_file; } free(art_file); - imsrc = image_new_from_jpeg(file, 1, NULL, 0); + imsrc = image_new_from_jpeg(file, 1, NULL, 0, 1); if( !imsrc ) continue; found_file: diff --git a/image_utils.c b/image_utils.c index 95161a8..d237bc3 100644 --- a/image_utils.c +++ b/image_utils.c @@ -393,7 +393,7 @@ image_new(int32_t width, int32_t height) } image * -image_new_from_jpeg(const char * path, int is_file, const char * buf, int size) +image_new_from_jpeg(const char * path, int is_file, const char * buf, int size, int scale) { image *vimage; FILE *file = NULL; @@ -427,6 +427,7 @@ image_new_from_jpeg(const char * path, int is_file, const char * buf, int size) return NULL; } jpeg_read_header(&cinfo, TRUE); + cinfo.scale_denom = scale; cinfo.do_fancy_upsampling = FALSE; cinfo.do_block_smoothing = FALSE; jpeg_start_decompress(&cinfo); diff --git a/image_utils.h b/image_utils.h index 6d712d0..570976a 100644 --- a/image_utils.h +++ b/image_utils.h @@ -27,7 +27,7 @@ int image_get_jpeg_resolution(const char * path, int * width, int * height); image * -image_new_from_jpeg(const char * path, int is_file, const char * ptr, int size); +image_new_from_jpeg(const char * path, int is_file, const char * ptr, int size, int scale); image * image_resize(image * src_image, int32_t width, int32_t height); diff --git a/metadata.c b/metadata.c index b6304e8..4d4b562 100644 --- a/metadata.c +++ b/metadata.c @@ -558,7 +558,7 @@ GetImageMetadata(const char * path, char * name) /* We might need to verify that the thumbnail is 160x160 or smaller */ if( ed->size > 12000 ) { - imsrc = image_new_from_jpeg(NULL, 0, (char *)ed->data, ed->size); + imsrc = image_new_from_jpeg(NULL, 0, (char *)ed->data, ed->size, 1); if( imsrc ) { if( (imsrc->width <= 160) && (imsrc->height <= 160) ) diff --git a/tivo_commands.c b/tivo_commands.c index e977836..19ce1e1 100644 --- a/tivo_commands.c +++ b/tivo_commands.c @@ -719,6 +719,7 @@ ProcessTiVoCommand(struct upnphttp * h, const char * orig_path) { strip_ext(anchorItem); } + free(path); if( command ) { @@ -741,9 +742,9 @@ ProcessTiVoCommand(struct upnphttp * h, const char * orig_path) { DPRINTF(E_DEBUG, L_GENERAL, "Unhandled command [%s]\n", command); Send501(h); + return; } } - free(path); CloseSocket_upnphttp(h); } #endif // TIVO_SUPPORT diff --git a/upnphttp.c b/upnphttp.c index 7e6f6ed..ecc1705 100644 --- a/upnphttp.c +++ b/upnphttp.c @@ -1382,9 +1382,12 @@ SendResp_resizedimg(struct upnphttp * h, char * object) char *pixelshape=NULL; sqlite_int64 id; int rows=0, chunked=0, ret; +#ifdef __sparc__ ExifData *ed; ExifLoader *l; +#endif image *imsrc = NULL, *imdst = NULL; + int scale = 1; id = strtoll(object, NULL, 10); sprintf(str_buf, "SELECT PATH, RESOLUTION, THUMBNAIL from DETAILS where ID = '%lld'", id); @@ -1472,6 +1475,13 @@ SendResp_resizedimg(struct upnphttp * h, char * object) else strcpy(dlna_pn, "LRG"); + if( srcw>>3 >= dstw && srch>>3 >= dsth) + scale = 8; + else if( srcw>>2 >= dstw && srch>>2 >= dsth ) + scale = 4; + else if( srcw>>1 >= dstw && srch>>1 >= dsth ) + scale = 2; + strftime(date, 30,"%a, %d %b %Y %H:%M:%S GMT" , gmtime(&curtime)); snprintf(header, sizeof(header)-100, "HTTP/1.1 200 OK\r\n" "Content-Type: image/jpeg\r\n" @@ -1492,11 +1502,8 @@ SendResp_resizedimg(struct upnphttp * h, char * object) } /* Resizing from a thumbnail is much faster than from a large image */ - #ifdef __sparc__ - if( dstw <= 200 && dsth <= 150 && atoi(tn) ) - #else +#ifdef __sparc__ if( dstw <= 160 && dsth <= 120 && atoi(tn) ) - #endif { l = exif_loader_new(); exif_loader_write_file(l, file_path); @@ -1507,15 +1514,18 @@ SendResp_resizedimg(struct upnphttp * h, char * object) { if( ed ) exif_data_unref(ed); - Send404(h); + DPRINTF(E_WARN, L_HTTP, "Unable to access image thumbnail!\n"); + Send500(h); goto resized_error; } - imsrc = image_new_from_jpeg(NULL, 0, (char *)ed->data, ed->size); + imsrc = image_new_from_jpeg(NULL, 0, (char *)ed->data, ed->size, 1); exif_data_unref(ed); } - else if( strcmp(h->HttpVer, "HTTP/1.0") == 0 ) + else +#endif + if( strcmp(h->HttpVer, "HTTP/1.0") == 0 ) { - imsrc = image_new_from_jpeg(file_path, 1, NULL, 0); + imsrc = image_new_from_jpeg(file_path, 1, NULL, 0, scale); } else { @@ -1527,7 +1537,8 @@ SendResp_resizedimg(struct upnphttp * h, char * object) { if( !imsrc ) { - Send404(h); + DPRINTF(E_WARN, L_HTTP, "Unable to open image %s!\n", file_path); + Send500(h); goto resized_error; } @@ -1542,10 +1553,11 @@ SendResp_resizedimg(struct upnphttp * h, char * object) { if( chunked ) { - imsrc = image_new_from_jpeg(file_path, 1, NULL, 0); + imsrc = image_new_from_jpeg(file_path, 1, NULL, 0, scale); if( !imsrc ) { - Send404(h); + DPRINTF(E_WARN, L_HTTP, "Unable to open image %s!\n", file_path); + Send500(h); goto resized_error; } imdst = image_resize(imsrc, dstw, dsth);