* Optimize JPEG scaling by downscaling as much as possible during decompression.

This commit is contained in:
Justin Maggard 2010-06-08 17:34:29 +00:00
parent 20bb1db8a7
commit c779eab4de
6 changed files with 33 additions and 19 deletions

View File

@ -218,7 +218,7 @@ check_embedded_art(const char * path, const char * image_data, int image_size)
} }
last_hash = hash; 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 ) if( !imsrc )
{ {
last_success = 0; last_success = 0;
@ -286,7 +286,7 @@ check_for_album_file(char * dir, const char * path)
if( art_cache_exists(file, &art_file) ) if( art_cache_exists(file, &art_file) )
goto existing_file; goto existing_file;
free(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 ) if( imsrc )
goto found_file; goto found_file;
} }
@ -298,7 +298,7 @@ check_for_album_file(char * dir, const char * path)
if( art_cache_exists(file, &art_file) ) if( art_cache_exists(file, &art_file) )
goto existing_file; goto existing_file;
free(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 ) if( imsrc )
goto found_file; goto found_file;
} }
@ -316,7 +316,7 @@ existing_file:
return art_file; return art_file;
} }
free(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 ) if( !imsrc )
continue; continue;
found_file: found_file:

View File

@ -393,7 +393,7 @@ image_new(int32_t width, int32_t height)
} }
image * 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; image *vimage;
FILE *file = NULL; FILE *file = NULL;
@ -427,6 +427,7 @@ image_new_from_jpeg(const char * path, int is_file, const char * buf, int size)
return NULL; return NULL;
} }
jpeg_read_header(&cinfo, TRUE); jpeg_read_header(&cinfo, TRUE);
cinfo.scale_denom = scale;
cinfo.do_fancy_upsampling = FALSE; cinfo.do_fancy_upsampling = FALSE;
cinfo.do_block_smoothing = FALSE; cinfo.do_block_smoothing = FALSE;
jpeg_start_decompress(&cinfo); jpeg_start_decompress(&cinfo);

View File

@ -27,7 +27,7 @@ int
image_get_jpeg_resolution(const char * path, int * width, int * height); image_get_jpeg_resolution(const char * path, int * width, int * height);
image * 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 *
image_resize(image * src_image, int32_t width, int32_t height); image_resize(image * src_image, int32_t width, int32_t height);

View File

@ -558,7 +558,7 @@ GetImageMetadata(const char * path, char * name)
/* We might need to verify that the thumbnail is 160x160 or smaller */ /* We might need to verify that the thumbnail is 160x160 or smaller */
if( ed->size > 12000 ) 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 )
{ {
if( (imsrc->width <= 160) && (imsrc->height <= 160) ) if( (imsrc->width <= 160) && (imsrc->height <= 160) )

View File

@ -719,6 +719,7 @@ ProcessTiVoCommand(struct upnphttp * h, const char * orig_path)
{ {
strip_ext(anchorItem); strip_ext(anchorItem);
} }
free(path);
if( command ) if( command )
{ {
@ -741,9 +742,9 @@ ProcessTiVoCommand(struct upnphttp * h, const char * orig_path)
{ {
DPRINTF(E_DEBUG, L_GENERAL, "Unhandled command [%s]\n", command); DPRINTF(E_DEBUG, L_GENERAL, "Unhandled command [%s]\n", command);
Send501(h); Send501(h);
return;
} }
} }
free(path);
CloseSocket_upnphttp(h); CloseSocket_upnphttp(h);
} }
#endif // TIVO_SUPPORT #endif // TIVO_SUPPORT

View File

@ -1382,9 +1382,12 @@ SendResp_resizedimg(struct upnphttp * h, char * object)
char *pixelshape=NULL; char *pixelshape=NULL;
sqlite_int64 id; sqlite_int64 id;
int rows=0, chunked=0, ret; int rows=0, chunked=0, ret;
#ifdef __sparc__
ExifData *ed; ExifData *ed;
ExifLoader *l; ExifLoader *l;
#endif
image *imsrc = NULL, *imdst = NULL; image *imsrc = NULL, *imdst = NULL;
int scale = 1;
id = strtoll(object, NULL, 10); id = strtoll(object, NULL, 10);
sprintf(str_buf, "SELECT PATH, RESOLUTION, THUMBNAIL from DETAILS where ID = '%lld'", id); 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 else
strcpy(dlna_pn, "LRG"); 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)); 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" snprintf(header, sizeof(header)-100, "HTTP/1.1 200 OK\r\n"
"Content-Type: image/jpeg\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 */ /* Resizing from a thumbnail is much faster than from a large image */
#ifdef __sparc__ #ifdef __sparc__
if( dstw <= 200 && dsth <= 150 && atoi(tn) )
#else
if( dstw <= 160 && dsth <= 120 && atoi(tn) ) if( dstw <= 160 && dsth <= 120 && atoi(tn) )
#endif
{ {
l = exif_loader_new(); l = exif_loader_new();
exif_loader_write_file(l, file_path); exif_loader_write_file(l, file_path);
@ -1507,15 +1514,18 @@ SendResp_resizedimg(struct upnphttp * h, char * object)
{ {
if( ed ) if( ed )
exif_data_unref(ed); exif_data_unref(ed);
Send404(h); DPRINTF(E_WARN, L_HTTP, "Unable to access image thumbnail!\n");
Send500(h);
goto resized_error; 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); 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 else
{ {
@ -1527,7 +1537,8 @@ SendResp_resizedimg(struct upnphttp * h, char * object)
{ {
if( !imsrc ) if( !imsrc )
{ {
Send404(h); DPRINTF(E_WARN, L_HTTP, "Unable to open image %s!\n", file_path);
Send500(h);
goto resized_error; goto resized_error;
} }
@ -1542,10 +1553,11 @@ SendResp_resizedimg(struct upnphttp * h, char * object)
{ {
if( chunked ) 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 ) if( !imsrc )
{ {
Send404(h); DPRINTF(E_WARN, L_HTTP, "Unable to open image %s!\n", file_path);
Send500(h);
goto resized_error; goto resized_error;
} }
imdst = image_resize(imsrc, dstw, dsth); imdst = image_resize(imsrc, dstw, dsth);