diff --git a/apps/plugins/CATEGORIES b/apps/plugins/CATEGORIES index 79186b7aed..aa7dbf38e5 100644 --- a/apps/plugins/CATEGORIES +++ b/apps/plugins/CATEGORIES @@ -51,6 +51,7 @@ iriverify,viewers jackpot,games jewels,games jpeg,viewers +jpegp,viewers keybox,apps keyremap,apps lamp,apps diff --git a/apps/plugins/imageviewer/SUBDIRS b/apps/plugins/imageviewer/SUBDIRS index 1f7b4d8b52..ea7c304218 100644 --- a/apps/plugins/imageviewer/SUBDIRS +++ b/apps/plugins/imageviewer/SUBDIRS @@ -3,5 +3,6 @@ jpeg png #ifdef HAVE_LCD_COLOR ppm +jpegp #endif gif diff --git a/apps/plugins/imageviewer/image_decoder.c b/apps/plugins/imageviewer/image_decoder.c index 0c1776daaa..c481899bae 100644 --- a/apps/plugins/imageviewer/image_decoder.c +++ b/apps/plugins/imageviewer/image_decoder.c @@ -25,12 +25,13 @@ static const char *decoder_names[MAX_IMAGE_TYPES] = { "bmp", - "jpeg", + "jpeg", // Default decoder for jpeg: Use jpeg for old decoder, jpegp for new "png", #ifdef HAVE_LCD_COLOR "ppm", #endif - "gif" + "gif", + "jpegp", }; /* Check file type by magic number or file extension diff --git a/apps/plugins/imageviewer/image_decoder.h b/apps/plugins/imageviewer/image_decoder.h index c27ed33e8e..7a9cd5d06c 100644 --- a/apps/plugins/imageviewer/image_decoder.h +++ b/apps/plugins/imageviewer/image_decoder.h @@ -33,6 +33,8 @@ enum image_type { IMAGE_PPM, #endif IMAGE_GIF, + IMAGE_JPEG_PROGRESSIVE, + MAX_IMAGE_TYPES }; diff --git a/apps/plugins/imageviewer/imageviewer.c b/apps/plugins/imageviewer/imageviewer.c index b849812508..ba5f8fec16 100644 --- a/apps/plugins/imageviewer/imageviewer.c +++ b/apps/plugins/imageviewer/imageviewer.c @@ -853,6 +853,8 @@ static int load_and_show(char* filename, struct image_info *info) file_pt[curfile] = NULL; return change_filename(direction); } + +reload_decoder: if (image_type != status) /* type of image is changed, load decoder. */ { struct loader_info loader_info = { @@ -881,6 +883,13 @@ static int load_and_show(char* filename, struct image_info *info) else status = imgdec->load_image(filename, info, buf, &remaining); + if (status == PLUGIN_JPEG_PROGRESSIVE) + { + rb->lcd_clear_display(); + status = IMAGE_JPEG_PROGRESSIVE; + goto reload_decoder; + } + if (status == PLUGIN_OUTOFMEM) { #ifdef USE_PLUG_BUF diff --git a/apps/plugins/imageviewer/imageviewer.h b/apps/plugins/imageviewer/imageviewer.h index ac15df5960..44e56c0696 100644 --- a/apps/plugins/imageviewer/imageviewer.h +++ b/apps/plugins/imageviewer/imageviewer.h @@ -55,6 +55,7 @@ enum { PLUGIN_OTHER = 0x200, PLUGIN_ABORT, PLUGIN_OUTOFMEM, + PLUGIN_JPEG_PROGRESSIVE, ZOOM_IN, ZOOM_OUT, diff --git a/apps/plugins/imageviewer/jpeg/jpeg.c b/apps/plugins/imageviewer/jpeg/jpeg.c index 3d8c9c3ac8..c231209beb 100644 --- a/apps/plugins/imageviewer/jpeg/jpeg.c +++ b/apps/plugins/imageviewer/jpeg/jpeg.c @@ -170,8 +170,12 @@ static int load_image(char *filename, struct image_info *info, if (status < 0 || (status & (DQT | SOF0)) != (DQT | SOF0)) { /* bad format or minimum components not contained */ +#ifndef HAVE_LCD_COLOR rb->splashf(HZ, "unsupported %d", status); return PLUGIN_ERROR; +#else + return PLUGIN_JPEG_PROGRESSIVE; +#endif } if (!(status & DHT)) /* if no Huffman table present: */ diff --git a/apps/plugins/imageviewer/jpegp/BUFFILEGETC.c b/apps/plugins/imageviewer/jpegp/BUFFILEGETC.c new file mode 100644 index 0000000000..5124636731 --- /dev/null +++ b/apps/plugins/imageviewer/jpegp/BUFFILEGETC.c @@ -0,0 +1,94 @@ +/* Simple buffered version of file reader. + * JPEG decoding seems to work faster with it. + * Not fully tested. In case of any issues try FILEGETC (see SOURCES) + * */ +#include "rb_glue.h" + +static int fd; +static unsigned char buff[256]; //TODO: Adjust it... +static int length = 0; +static int cur_buff_pos = 0; +static int file_pos = 0; + +extern int GETC(void) +{ + if (cur_buff_pos >= length) + { + length = rb->read(fd, buff, sizeof(buff)); + file_pos += length; + cur_buff_pos = 0; + } + + return buff[cur_buff_pos++]; +} + +// multibyte readers: host-endian independent - if evaluated in right order (ie. don't optimize) + +extern int GETWbi(void) // 16-bit big-endian +{ + return ( GETC()<<8 ) | GETC(); +} + +extern int GETDbi(void) // 32-bit big-endian +{ + return ( GETC()<<24 ) | ( GETC()<<16 ) | ( GETC()<<8 ) | GETC(); +} + +extern int GETWli(void) // 16-bit little-endian +{ + return GETC() | ( GETC()<<8 ); +} + +extern int GETDli(void) // 32-bit little-endian +{ + return GETC() | ( GETC()<<8 ) | ( GETC()<<16 ) | ( GETC()<<24 ); +} + +// seek + +extern void SEEK(int d) +{ + int newPos = cur_buff_pos + d; + if (newPos < length && newPos >= 0) + { + cur_buff_pos = newPos; + return; + } + file_pos = rb->lseek(fd, (cur_buff_pos - length) + d, SEEK_CUR); + cur_buff_pos = length = 0; +} + +extern void POS(int d) +{ + cur_buff_pos = length = 0; + file_pos = d; + rb->lseek(fd, d, SEEK_SET); +} + +extern int TELL(void) +{ + return file_pos + cur_buff_pos - length; +} + +// OPEN/CLOSE file + +extern void *OPEN(char *f) +{ + printf("Opening %s\n", f); + cur_buff_pos = length = file_pos = 0; + fd = rb->open(f,O_RDONLY); + + if ( fd < 0 ) + { + printf("Error opening %s\n", f); + return NULL; + } + + return &fd; +} + +extern int CLOSE(void) +{ + cur_buff_pos = length = file_pos = 0; + return rb->close(fd); +} diff --git a/apps/plugins/imageviewer/jpegp/FILEGETC.c b/apps/plugins/imageviewer/jpegp/FILEGETC.c new file mode 100644 index 0000000000..bb7f0c485f --- /dev/null +++ b/apps/plugins/imageviewer/jpegp/FILEGETC.c @@ -0,0 +1,71 @@ +#include "rb_glue.h" + +static int fd; + +extern int GETC(void) +{ + unsigned char x; + rb->read(fd, &x, 1); + return x; +} + +// multibyte readers: host-endian independent - if evaluated in right order (ie. don't optimize) + +extern int GETWbi(void) // 16-bit big-endian +{ + return ( GETC()<<8 ) | GETC(); +} + +extern int GETDbi(void) // 32-bit big-endian +{ + return ( GETC()<<24 ) | ( GETC()<<16 ) | ( GETC()<<8 ) | GETC(); +} + +extern int GETWli(void) // 16-bit little-endian +{ + return GETC() | ( GETC()<<8 ); +} + +extern int GETDli(void) // 32-bit little-endian +{ + return GETC() | ( GETC()<<8 ) | ( GETC()<<16 ) | ( GETC()<<24 ); +} + +// seek + +extern void SEEK(int d) +{ + rb->lseek(fd, d, SEEK_CUR); +} + +extern void POS(int d) +{ + rb->lseek(fd, d, SEEK_SET); +} + +extern int TELL(void) +{ + return rb->lseek(fd, 0, SEEK_CUR); +} + +// OPEN/CLOSE file + +extern void *OPEN(char *f) +{ + printf("Opening %s\n", f); + + fd = rb->open(f,O_RDONLY); + + if ( fd < 0 ) + { + printf("Error opening %s\n", f); + return NULL; + } + + return &fd; +} + +extern int CLOSE(void) +{ + return rb->close(fd); +} diff --git a/apps/plugins/imageviewer/jpegp/GETC.h b/apps/plugins/imageviewer/jpegp/GETC.h index d17cdb9857..5e8a3c6a9d 100644 --- a/apps/plugins/imageviewer/jpegp/GETC.h +++ b/apps/plugins/imageviewer/jpegp/GETC.h @@ -37,20 +37,20 @@ // For decoders -extern int GETC(); +extern int GETC(void); // Multibyte helpers -extern int GETWbi(); // read word (16-bit) big-endian -extern int GETWli(); // little-endian -extern int GETDbi(); // read double word (32-bit) big-endian -extern int GETDli(); // little-endian +extern int GETWbi(void); // read word (16-bit) big-endian +extern int GETWli(void); // little-endian +extern int GETDbi(void); // read double word (32-bit) big-endian +extern int GETDli(void); // little-endian // positioning extern void SEEK(int); // move relative to current extern void POS(int); // move absolute position (TIFF) -extern int TELL(); // read actual position +extern int TELL(void); // read actual position // For RAINBOW clients to implement outside of Rainbow Library extern void *OPEN(char*); -extern void CLOSE(); +extern void CLOSE(void); diff --git a/apps/plugins/imageviewer/jpegp/SOURCES b/apps/plugins/imageviewer/jpegp/SOURCES new file mode 100644 index 0000000000..dfaf63a42f --- /dev/null +++ b/apps/plugins/imageviewer/jpegp/SOURCES @@ -0,0 +1,6 @@ +jpegp.c +//FILEGETC.c +BUFFILEGETC.c +jpeg81.c +idct.c +mempool.c \ No newline at end of file diff --git a/apps/plugins/imageviewer/jpegp/jpeg81.c b/apps/plugins/imageviewer/jpegp/jpeg81.c index 95e46dbd17..76b36ca950 100644 --- a/apps/plugins/imageviewer/jpegp/jpeg81.c +++ b/apps/plugins/imageviewer/jpegp/jpeg81.c @@ -40,12 +40,12 @@ jpeg81.c * SOFTWARE. */ -#include "GETC.h" +#include "GETC.h" +#include "rb_glue.h" #include "jpeg81.h" -#include // calloc() called once -#include // debug only - +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" ///////////////////////////////////////// LOSSLESS ///////////////////////////////////////// static int P1(struct COMP *C, TSAMP *samp) // Px = Ra @@ -63,17 +63,17 @@ static int P3(struct COMP *C, TSAMP *samp) // Px = Rc return samp[-C->du_width-1]; } -static int P4(struct COMP *C, TSAMP *samp) // Px = Ra + Rb – Rc +static int P4(struct COMP *C, TSAMP *samp) // Px = Ra + Rb - Rc { return samp[-1] + samp[-C->du_width] - samp[-C->du_width-1]; } -static int P5(struct COMP *C, TSAMP *samp) // Px = Ra + ((Rb – Rc)/2) +static int P5(struct COMP *C, TSAMP *samp) // Px = Ra + ((Rb - Rc)/2) { return samp[-1] + ( (samp[-C->du_width] - samp[-C->du_width-1]) >> 1 ); } -static int P6(struct COMP *C, TSAMP *samp) // Px = Rb + ((Ra – Rc)/2) +static int P6(struct COMP *C, TSAMP *samp) // Px = Rb + ((Ra - Rc)/2) { return samp[-C->du_width] + ( (samp[-1] - samp[-C->du_width-1]) >> 1 ); } @@ -215,7 +215,7 @@ static void du_sequential_huff(struct JPEGD *j, struct COMP *sc, TCOEF *coef) { int s, k; dc_decode_huff(j, sc, coef); - for (k=1; s=sc->ACS[ReadHuffmanCode(j, sc->ACB)]; k++) { // EOB? + for (k=1; (s=sc->ACS[ReadHuffmanCode(j, sc->ACB)]); k++) { // EOB? k+= s>>4; if (s==0xf0) continue; // ZRL coef[k]= ReadDiff(j, s&15); @@ -496,7 +496,7 @@ static void Ri(struct JPEGD *j, int n) printf("RST%d\n", Marker&7); printf("%08X: ECS\n", TELL()); } - else printf("STREAM ERROR: expected RSTn missing from ECS\n"); + else { printf("STREAM ERROR: expected RSTn missing from ECS\n"); } j->Reset_decoder(j); } } @@ -832,7 +832,7 @@ extern enum JPEGENUM JPEGDecode(struct JPEGD *j) } } - printf(" Malloc for %d Data Units (%d bytes)\n\n", TotalDU, sizeof(DU)*TotalDU); + printf(" Malloc for %d Data Units (%lu bytes)\n\n", TotalDU, sizeof(DU)*TotalDU); if (j->SOF > 0xC8) { // DCT Arithmetic j->Reset_decoder= Reset_decoder_arith; @@ -953,7 +953,7 @@ extern enum JPEGENUM JPEGDecode(struct JPEGD *j) for (Lq-=2; Lq; Lq -= 65 + 64*Pq) { - int (*get)(); + int (*get)(void); int T= GETC(); int Tq= T&3; int *qt= j->QT[Tq]; @@ -993,3 +993,5 @@ extern enum JPEGENUM JPEGDecode(struct JPEGD *j) } } } + +#pragma GCC diagnostic pop \ No newline at end of file diff --git a/apps/plugins/imageviewer/jpegp/jpeg81.h b/apps/plugins/imageviewer/jpegp/jpeg81.h index fa71b10113..e265d84926 100644 --- a/apps/plugins/imageviewer/jpegp/jpeg81.h +++ b/apps/plugins/imageviewer/jpegp/jpeg81.h @@ -144,4 +144,4 @@ struct JPEGD { // The JPEG DECODER OBJECT }; -extern int JPEGDecode(struct JPEGD *j); +extern enum JPEGENUM JPEGDecode(struct JPEGD *j); diff --git a/apps/plugins/imageviewer/jpegp/jpegp.c b/apps/plugins/imageviewer/jpegp/jpegp.c new file mode 100644 index 0000000000..bb7be314f1 --- /dev/null +++ b/apps/plugins/imageviewer/jpegp/jpegp.c @@ -0,0 +1,260 @@ +#include "jpeg81.h" +#include "idct.h" +#include "GETC.h" +#include "rb_glue.h" + +#include "../imageviewer.h" + + +/**************** begin Application ********************/ + +/************************* Types ***************************/ + +struct t_disp +{ + unsigned char* bitmap; +}; + +/************************* Globals ***************************/ + +/* decompressed image in the possible sizes (1,2,4,8), wasting the other */ +static struct t_disp disp[9]; + +static struct JPEGD jpg; /* too large for stack */ + +/************************* Implementation ***************************/ + +static 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 + rb->lcd_bitmap_part( + (fb_data*)pdisp->bitmap, info->x + x, info->y + y, + STRIDE(SCREEN_MAIN, info->width, info->height), + x + MAX(0, (LCD_WIDTH-info->width)/2), + y + MAX(0, (LCD_HEIGHT-info->height)/2), + width, height); +#else + mylcd_ub_gray_bitmap_part( + pdisp->bitmap, info->x + x, info->y + y, info->width, + x + MAX(0, (LCD_WIDTH-info->width)/2), + y + MAX(0, (LCD_HEIGHT-info->height)/2), + width, height); +#endif +} + +static int img_mem(int ds) +{ + struct JPEGD* j = &jpg; + return j->Y/ds * j->X/ds*sizeof(fb_data); +} + +/* my memory pool (from the mp3 buffer) */ +static char print[32]; /* use a common snprintf() buffer */ + +static void scaled_dequantization_and_idct(void) +{ + struct JPEGD* j = &jpg; + // The following code is based on RAINBOW lib jpeg2bmp example: + // https://github.com/Halicery/vc_rainbow/blob/605c045a564dad8e2df84e48914eac3d2d8d4a9b/jpeg2bmp.c + + printf("Scaled de-quantization and IDCT.. "); + int c, i, n; + + // Pre-scale quant-tables + int SQ[4][64]; + for (c=0; c<4 && j->QT[c][0]; c++) + { + int *q= j->QT[c], *sq= SQ[c]; + for (i=0; i<64; i++) sq[i]= q[i] * SCALEM[zigzag[i]]; + } + + // DEQUANT + IDCT + for (c=0; cNf; c++) + { + struct COMP *C= j->Components+c; + //int *q= j->QT[C->Qi]; + int *sq= SQ[C->Qi]; + + for (n=0; n < C->du_size; n++) + { + /* + // <--- scaled idct + int k, t[64]; + TCOEF *coef= du[x]; + t[0]= coef[0] * q[0] + 1024; // dequant DC and level-shift (8-bit) + for (k=1; k<64; k++) t[zigzag[k]] = coef[k] * q[k]; // dequant AC (+zigzag) + idct_s(t, coef); + */ + + // <--- scaled idct with dequant + idct_sq( C->du[ (n / C->du_w) * C->du_width + n % C->du_w ], sq ); + } + } + printf("done\n"); +} + +static int load_image(char *filename, struct image_info *info, + unsigned char *buf, ssize_t *buf_size) +{ + int status; + struct JPEGD *p_jpg = &jpg; + + memset(&disp, 0, sizeof(disp)); + memset(&jpg, 0, sizeof(jpg)); + + init_mem_pool(buf, *buf_size); + + if (!OPEN(filename)) + { + return PLUGIN_ERROR; + } + + if (!iv->running_slideshow) + { + rb->lcd_puts(0, 0, rb->strrchr(filename,'/')+1); + rb->lcd_puts(0, 2, "decoding..."); + rb->lcd_update(); + } + long time; /* measured ticks */ + + /* the actual decoding */ + time = *rb->current_tick; + status = JPEGDecode(p_jpg); + time = *rb->current_tick - time; + + CLOSE(); + + if (status < 0) + { /* bad format or minimum components not contained */ + if (status == JPEGENUMERR_MALLOC) + { + return PLUGIN_OUTOFMEM; + } + rb->splashf(HZ, "unsupported %d", status); + return PLUGIN_ERROR; + } + + if (!iv->running_slideshow) + { + rb->lcd_putsf(0, 2, "image %dx%d", p_jpg->X, p_jpg->Y); + int w, h; /* used to center output */ + rb->snprintf(print, sizeof(print), "jpegp %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(); + //rb->sleep(100); + } + + info->x_size = p_jpg->X; + info->y_size = p_jpg->Y; + +#ifdef DISK_SPINDOWN + if (iv->running_slideshow && iv->immediate_ata_off) + { + /* running slideshow and time is long enough: power down disk */ + rb->storage_sleep(); + } +#endif + + if ( 3 != p_jpg->Nf ) + return PLUGIN_ERROR; + + scaled_dequantization_and_idct(); + + *buf_size = freeze_mem_pool(); + return PLUGIN_OK; +} + +static int get_image(struct image_info *info, int frame, int ds) +{ + (void)frame; + struct JPEGD* p_jpg = &jpg; + struct t_disp* p_disp = &disp[ds]; /* short cut */ + + info->width = p_jpg->X / ds; + info->height = p_jpg->Y / ds; + info->data = p_disp; + + if (p_disp->bitmap != NULL) + { + /* we still have it */ + return PLUGIN_OK; + } + + struct JPEGD* j = p_jpg; + int mem = img_mem(ds); + + p_disp->bitmap = malloc(mem); + + if (!p_disp->bitmap) + { + clear_mem_pool(); + memset(&disp, 0, sizeof(disp)); + p_disp->bitmap = malloc(mem); + if (!p_disp->bitmap) + return PLUGIN_ERROR; + } + + fb_data *bmp = (fb_data *)p_disp->bitmap; + + // The following code is based on RAINBOW lib jpeg2bmp example: + // https://github.com/Halicery/vc_rainbow/blob/605c045a564dad8e2df84e48914eac3d2d8d4a9b/jpeg2bmp.c + // Primitive yuv-rgb converter for all sub-sampling types, 24-bit BMP only + printf("YUV-to-RGB conversion.. "); + int h0 = j->Hmax / j->Components[0].Hi; + int v0 = j->Vmax / j->Components[0].Vi; + int h1 = j->Hmax / j->Components[1].Hi; + int v1 = j->Vmax / j->Components[1].Vi; + int h2 = j->Hmax / j->Components[2].Hi; + int v2 = j->Vmax / j->Components[2].Vi; + + int x, y; + for (y = 0; y < j->Y; y++) + { + if (y%ds != 0) + continue; + + TCOEF *C0 = + j->Components[0].du[j->Components[0].du_width * ((y / v0) / 8)] + 8 * ((y / v0) & 7); + TCOEF *C1 = + j->Components[1].du[j->Components[1].du_width * ((y / v1) / 8)] + 8 * ((y / v1) & 7); + TCOEF *C2 = + j->Components[2].du[j->Components[2].du_width * ((y / v2) / 8)] + 8 * ((y / v2) & 7); + + for (x = 0; x < j->X; x++) + { + if (x%ds != 0) + continue; + + TCOEF c0 = C0[(x / h0 / 8) * 64 + ((x / h0) & 7)]; + TCOEF c1 = C1[(x / h1 / 8) * 64 + ((x / h1) & 7)]; + TCOEF c2 = C2[(x / h2 / 8) * 64 + ((x / h2) & 7)]; + + // ITU BT.601 full-range YUV-to-RGB integer approximation + { + int y = (c0 << 5) + 16; + int u = c1 - 128; + int v = c2 - 128; + + int b = CLIP[(y + 57 * u)>>5]; // B; + int g = CLIP[(y - 11 * u - 23 * v)>>5]; // G + int r = CLIP[(y + 45 * v)>>5]; // R; + *bmp++= FB_RGBPACK(r,g,b); + } + } + } + printf("done\n"); + return 0; +} + +const struct image_decoder image_decoder = { + false, + img_mem, + load_image, + get_image, + draw_image_rect, +}; + +IMGDEC_HEADER diff --git a/apps/plugins/imageviewer/jpegp/jpegp.make b/apps/plugins/imageviewer/jpegp/jpegp.make new file mode 100644 index 0000000000..8d15af3a68 --- /dev/null +++ b/apps/plugins/imageviewer/jpegp/jpegp.make @@ -0,0 +1,32 @@ +# __________ __ ___. +# Open \______ \ ____ ____ | | _\_ |__ _______ ___ +# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +# \/ \/ \/ \/ \/ +# $Id$ +# + +JPEGPSRCDIR := $(IMGVSRCDIR)/jpegp +JPEGPBUILDDIR := $(IMGVBUILDDIR)/jpegp + +JPEGP_SRC := $(call preprocess, $(JPEGPSRCDIR)/SOURCES) +JPEGP_OBJ := $(call c2obj, $(JPEGP_SRC)) + +OTHER_SRC += $(JPEGP_SRC) + +ROCKS += $(JPEGPBUILDDIR)/jpegp.ovl + +$(JPEGPBUILDDIR)/jpegp.refmap: $(JPEGP_OBJ) $(TLSFLIB) +$(JPEGPBUILDDIR)/jpegp.link: $(PLUGIN_LDS) $(JPEGPBUILDDIR)/jpegp.refmap +$(JPEGPBUILDDIR)/jpegp.ovl: $(JPEGP_OBJ) $(TLSFLIB) + +JPEGPFLAGS = $(IMGDECFLAGS) +ifndef DEBUG +JPEGPFLAGS += -Os +endif + +# Compile plugin with extra flags (adapted from ZXBox) +$(JPEGPBUILDDIR)/%.o: $(JPEGPSRCDIR)/%.c $(JPEGPSRCDIR)/jpegp.make + $(SILENT)mkdir -p $(dir $@) + $(call PRINTS,CC $(subst $(ROOTDIR)/,,$<))$(CC) -I$(dir $<) $(JPEGPFLAGS) -c $< -o $@ diff --git a/apps/plugins/imageviewer/jpegp/mempool.c b/apps/plugins/imageviewer/jpegp/mempool.c new file mode 100644 index 0000000000..f777ff230a --- /dev/null +++ b/apps/plugins/imageviewer/jpegp/mempool.c @@ -0,0 +1,50 @@ +#include +#include "plugin.h" + +static unsigned char *mem_pool; +static unsigned char *mem_pool_start; +static size_t memory_size; + +extern void *malloc(size_t size) +{ + if (size > memory_size) + return NULL; + + memory_size -= size; + unsigned char* ptr = mem_pool; + + mem_pool+= size; + return ptr; +} + +extern void *calloc(size_t nelem, size_t elem_size) +{ + unsigned char* ptr = malloc(nelem*elem_size); + if (!ptr) + return NULL; + rb->memset(ptr, 0, nelem*elem_size); + return ptr; +} + +extern void init_mem_pool(const unsigned char *buf, const ssize_t buf_size) +{ + //TODO: do we need this alignment? (copied from gif lib) + unsigned char *memory_max; + + /* align buffer */ + mem_pool_start = mem_pool = (unsigned char *)((intptr_t)(buf + 3) & ~3); + memory_max = (unsigned char *)((intptr_t)(mem_pool + buf_size) & ~3); + memory_size = memory_max - mem_pool; +} + +extern ssize_t freeze_mem_pool(void) +{ + mem_pool_start = mem_pool; + return memory_size; +} + +extern void clear_mem_pool(void) +{ + memory_size += mem_pool - mem_pool_start; + mem_pool = mem_pool_start; +} \ No newline at end of file diff --git a/apps/plugins/imageviewer/jpegp/mempool.h b/apps/plugins/imageviewer/jpegp/mempool.h new file mode 100644 index 0000000000..55bbdaf363 --- /dev/null +++ b/apps/plugins/imageviewer/jpegp/mempool.h @@ -0,0 +1,7 @@ +#include + +extern void init_mem_pool(const unsigned char *buf, const ssize_t buf_size); +extern void *malloc(size_t size); +extern void *calloc(size_t nelem, size_t elem_size); +extern ssize_t freeze_mem_pool(void); +extern void clear_mem_pool(void); diff --git a/apps/plugins/imageviewer/jpegp/rb_glue.h b/apps/plugins/imageviewer/jpegp/rb_glue.h new file mode 100644 index 0000000000..ce08483deb --- /dev/null +++ b/apps/plugins/imageviewer/jpegp/rb_glue.h @@ -0,0 +1,35 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * $Id$ + * + * 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 "mempool.h" + +//define from rbunicode.h clashes with jpeg81.h struct +#undef COMP + +#undef memset +#define memset(a,b,c) rb->memset((a),(b),(c)) + +#if defined(DEBUG) || defined(SIMULATOR) +#define printf rb->debugf +#else +#undef printf +#define printf(...) +#endif \ No newline at end of file diff --git a/manual/plugins/imageviewer.tex b/manual/plugins/imageviewer.tex index cc5b27eee4..0676f21a9f 100644 --- a/manual/plugins/imageviewer.tex +++ b/manual/plugins/imageviewer.tex @@ -161,7 +161,8 @@ for JPEG images. \end{description} \note{ -Progressive scan and other unusual JPEG files are not supported, and will +\opt{lcd_color}{Progressive scan is supported. Unsupported JPEG files} +\nopt{lcd_color}{Progressive scan and other unusual JPEG files are not supported, and} will result in various ``unsupported xx'' messages. Processing could also fail if the image is too big to decode which will be explained by a respective message.