diff options
| author | Teruaki Kawashima <teru@rockbox.org> | 2010-01-18 12:46:19 +0000 |
|---|---|---|
| committer | Teruaki Kawashima <teru@rockbox.org> | 2010-01-18 12:46:19 +0000 |
| commit | 5bd08237499dfc66309ba2a5a4dac75018e794ac (patch) | |
| tree | fe742342707b8789ce0dbf1a18e5a8346ae2601d /apps/plugins/imageviewer/jpeg/jpeg.c | |
| parent | 135d983433e741cf9658ff5d7457bdf37ef48ce0 (diff) | |
| download | rockbox-5bd08237499dfc66309ba2a5a4dac75018e794ac.zip rockbox-5bd08237499dfc66309ba2a5a4dac75018e794ac.tar.gz rockbox-5bd08237499dfc66309ba2a5a4dac75018e794ac.tar.bz2 rockbox-5bd08237499dfc66309ba2a5a4dac75018e794ac.tar.xz | |
jpeg,png: Merge user interface code and plugin entry point of the two plugins (part of FS#6321).
* Created new directory, imageviewer/ and moved both jpeg/ and png/ under it.
- this still doesn't merge the two plugins. i.e. both jpeg.rock and png.rock will be made for color targets.
- I'm thinking to merge the two plugins to single image viewer later.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24272 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/imageviewer/jpeg/jpeg.c')
| -rw-r--r-- | apps/plugins/imageviewer/jpeg/jpeg.c | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/apps/plugins/imageviewer/jpeg/jpeg.c b/apps/plugins/imageviewer/jpeg/jpeg.c new file mode 100644 index 0000000..b4ac6c0 --- /dev/null +++ b/apps/plugins/imageviewer/jpeg/jpeg.c @@ -0,0 +1,308 @@ +/*************************************************************************** +* __________ __ ___. +* Open \______ \ ____ ____ | | _\_ |__ _______ ___ +* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +* \/ \/ \/ \/ \/ +* $Id$ +* +* JPEG image viewer +* (This is a real mess if it has to be coded in one single C file) +* +* File scrolling addition (C) 2005 Alexander Spyridakis +* Copyright (C) 2004 Jörg Hohensohn aka [IDC]Dragon +* Heavily borrowed from the IJG implementation (C) Thomas G. Lane +* Small & fast downscaling IDCT (C) 2002 by Guido Vollbeding JPEGclub.org +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +* KIND, either express or implied. +* +****************************************************************************/ + +#include "plugin.h" + +#include "../imageviewer.h" +#include "jpeg_decoder.h" + +#ifdef HAVE_LCD_COLOR +#include "yuv2rgb.h" +#endif + +/**************** begin Application ********************/ + +/************************* Types ***************************/ + +struct t_disp +{ +#ifdef HAVE_LCD_COLOR + unsigned char* bitmap[3]; /* Y, Cr, Cb */ + int csub_x, csub_y; +#else + unsigned char* bitmap[1]; /* Y only */ +#endif + int stride; +}; + +/************************* Globals ***************************/ + +/* decompressed image in the possible sizes (1,2,4,8), wasting the other */ +static struct t_disp disp[9]; + +/* my memory pool (from the mp3 buffer) */ +static char print[32]; /* use a common snprintf() buffer */ + +/* the root of the images, hereafter are decompresed ones */ +static unsigned char* buf_root; +static int root_size; + +/* up to here currently used by image(s) */ +static unsigned char* buf_images; +static ssize_t buf_images_size; + +static struct jpeg jpg; /* too large for stack */ + +/************************* Implementation ***************************/ + +bool img_ext(const char *ext) +{ + if(!ext) + return false; + if(!rb->strcasecmp(ext,".jpg") || + !rb->strcasecmp(ext,".jpe") || + !rb->strcasecmp(ext,".jpeg")) + return true; + else + return false; +} + +void draw_image_rect(struct image_info *info, + int x, int y, int width, int height) +{ + struct t_disp* pdisp = (struct t_disp*)info->data; +#ifdef HAVE_LCD_COLOR + yuv_bitmap_part( + pdisp->bitmap, pdisp->csub_x, pdisp->csub_y, + info->x + x, info->y + y, pdisp->stride, + x + MAX(0, (LCD_WIDTH - info->width) / 2), + y + MAX(0, (LCD_HEIGHT - info->height) / 2), + width, height, + settings.jpeg_colour_mode, settings.jpeg_dither_mode); +#else + MYXLCD(gray_bitmap_part)( + pdisp->bitmap[0], info->x + x, info->y + y, pdisp->stride, + x + MAX(0, (LCD_WIDTH-info->width)/2), + y + MAX(0, (LCD_HEIGHT-info->height)/2), + width, height); +#endif +} + +int img_mem(int ds) +{ + int size; + struct jpeg *p_jpg = &jpg; + + size = (p_jpg->x_phys/ds/p_jpg->subsample_x[0]) + * (p_jpg->y_phys/ds/p_jpg->subsample_y[0]); +#ifdef HAVE_LCD_COLOR + if (p_jpg->blocks > 1) /* colour, add requirements for chroma */ + { + size += (p_jpg->x_phys/ds/p_jpg->subsample_x[1]) + * (p_jpg->y_phys/ds/p_jpg->subsample_y[1]); + size += (p_jpg->x_phys/ds/p_jpg->subsample_x[2]) + * (p_jpg->y_phys/ds/p_jpg->subsample_y[2]); + } +#endif + return size; +} + +int load_image(char *filename, struct image_info *info, + unsigned char *buf, ssize_t *buf_size) +{ + int fd; + int filesize; + unsigned char* buf_jpeg; /* compressed JPEG image */ + int status; + struct jpeg *p_jpg = &jpg; + + rb->memset(&disp, 0, sizeof(disp)); + rb->memset(&jpg, 0, sizeof(jpg)); + + fd = rb->open(filename, O_RDONLY); + if (fd < 0) + { + rb->splashf(HZ, "err opening %s:%d", filename, fd); + return PLUGIN_ERROR; + } + filesize = rb->filesize(fd); + + /* allocate JPEG buffer */ + buf_jpeg = buf; + + /* we can start the decompressed images behind it */ + buf_images = buf_root = buf + filesize; + buf_images_size = root_size = *buf_size - filesize; + + if (buf_images_size <= 0) + { + rb->close(fd); + return PLUGIN_OUTOFMEM; + } + + if(!running_slideshow) + { + rb->snprintf(print, sizeof(print), "%s:", rb->strrchr(filename,'/')+1); + rb->lcd_puts(0, 0, print); + rb->lcd_update(); + + rb->snprintf(print, sizeof(print), "loading %d bytes", filesize); + rb->lcd_puts(0, 1, print); + rb->lcd_update(); + } + + rb->read(fd, buf_jpeg, filesize); + rb->close(fd); + + if(!running_slideshow) + { + rb->snprintf(print, sizeof(print), "decoding markers"); + rb->lcd_puts(0, 2, print); + rb->lcd_update(); + } +#ifdef DISK_SPINDOWN + else if(immediate_ata_off) + { + /* running slideshow and time is long enough: power down disk */ + rb->storage_sleep(); + } +#endif + + /* process markers, unstuffing */ + status = process_markers(buf_jpeg, filesize, p_jpg); + + if (status < 0 || (status & (DQT | SOF0)) != (DQT | SOF0)) + { /* bad format or minimum components not contained */ + rb->splashf(HZ, "unsupported %d", status); + return PLUGIN_ERROR; + } + + if (!(status & DHT)) /* if no Huffman table present: */ + default_huff_tbl(p_jpg); /* use default */ + build_lut(p_jpg); /* derive Huffman and other lookup-tables */ + + if(!running_slideshow) + { + rb->snprintf(print, sizeof(print), "image %dx%d", + p_jpg->x_size, p_jpg->y_size); + rb->lcd_puts(0, 2, print); + rb->lcd_update(); + } + + info->x_size = p_jpg->x_size; + info->y_size = p_jpg->y_size; + *buf_size = buf_images_size; + return PLUGIN_OK; +} + +int get_image(struct image_info *info, int ds) +{ + int w, h; /* used to center output */ + int size; /* decompressed image size */ + long time; /* measured ticks */ + int status; + struct jpeg* p_jpg = &jpg; + struct t_disp* p_disp = &disp[ds]; /* short cut */ + + info->width = p_jpg->x_size / ds; + info->height = p_jpg->y_size / ds; + info->data = p_disp; + + if (p_disp->bitmap[0] != NULL) + { + /* we still have it */ + return PLUGIN_OK; + } + + /* assign image buffer */ + + /* physical size needed for decoding */ + size = img_mem(ds); + if (buf_images_size <= size) + { /* have to discard the current */ + int i; + for (i=1; i<=8; i++) + disp[i].bitmap[0] = NULL; /* invalidate all bitmaps */ + buf_images = buf_root; /* start again from the beginning of the buffer */ + buf_images_size = root_size; + } + +#ifdef HAVE_LCD_COLOR + if (p_jpg->blocks > 1) /* colour jpeg */ + { + int i; + + for (i = 1; i < 3; i++) + { + size = (p_jpg->x_phys / ds / p_jpg->subsample_x[i]) + * (p_jpg->y_phys / ds / p_jpg->subsample_y[i]); + p_disp->bitmap[i] = buf_images; + buf_images += size; + buf_images_size -= size; + } + p_disp->csub_x = p_jpg->subsample_x[1]; + p_disp->csub_y = p_jpg->subsample_y[1]; + } + else + { + p_disp->csub_x = p_disp->csub_y = 0; + p_disp->bitmap[1] = p_disp->bitmap[2] = buf_images; + } +#endif + /* size may be less when decoded (if height is not block aligned) */ + size = (p_jpg->x_phys/ds) * (p_jpg->y_size/ds); + p_disp->bitmap[0] = buf_images; + buf_images += size; + buf_images_size -= size; + + if(!running_slideshow) + { + rb->snprintf(print, sizeof(print), "decoding %d*%d", + p_jpg->x_size/ds, p_jpg->y_size/ds); + rb->lcd_puts(0, 3, print); + rb->lcd_update(); + } + + /* update image properties */ + p_disp->stride = p_jpg->x_phys / ds; /* use physical size for stride */ + + /* the actual decoding */ + time = *rb->current_tick; +#ifdef HAVE_ADJUSTABLE_CPU_FREQ + rb->cpu_boost(true); + status = jpeg_decode(p_jpg, p_disp->bitmap, ds, cb_progress); + rb->cpu_boost(false); +#else + status = jpeg_decode(p_jpg, p_disp->bitmap, ds, cb_progress); +#endif + if (status) + { + rb->splashf(HZ, "decode error %d", status); + return PLUGIN_ERROR; + } + time = *rb->current_tick - time; + + if(!running_slideshow) + { + rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ); + rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */ + rb->lcd_putsxy((LCD_WIDTH - w)/2, LCD_HEIGHT - h, print); + rb->lcd_update(); + } + + return PLUGIN_OK; +} |