Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

Rework ppmviewer to fit our shiny new imageviewer framework. FS#11818 by me.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29012 a1c6a512-1295-4272-9138-f99709370657

+574 -358
+1 -1
apps/plugins/CATEGORIES
··· 71 71 plasma,demos 72 72 png,viewers 73 73 pong,games 74 - ppmviewer,viewers 74 + ppm,viewers 75 75 properties,viewers 76 76 random_folder_advance_config,apps 77 77 remote_control,apps
-1
apps/plugins/SOURCES
··· 182 182 183 183 #ifdef HAVE_LCD_COLOR 184 184 clix.c 185 - ppmviewer.c 186 185 codebuster.c 187 186 #endif 188 187
+3
apps/plugins/imageviewer/SUBDIRS
··· 1 1 bmp 2 2 jpeg 3 3 png 4 + #ifdef HAVE_LCD_COLOR 5 + ppm 6 + #endif
+6
apps/plugins/imageviewer/image_decoder.c
··· 27 27 "bmp", 28 28 "jpeg", 29 29 "png", 30 + #ifdef HAVE_LCD_COLOR 31 + "ppm" 32 + #endif 30 33 }; 31 34 32 35 /* check file type by extention */ ··· 41 44 { ".jpe", IMAGE_JPEG }, 42 45 { ".jpeg", IMAGE_JPEG }, 43 46 { ".png", IMAGE_PNG }, 47 + #ifdef HAVE_LCD_COLOR 48 + { ".ppm", IMAGE_PPM }, 49 + #endif 44 50 }; 45 51 46 52 const char *ext = rb->strrchr(name, '.');
+3
apps/plugins/imageviewer/image_decoder.h
··· 29 29 IMAGE_BMP = 0, 30 30 IMAGE_JPEG, 31 31 IMAGE_PNG, 32 + #ifdef HAVE_LCD_COLOR 33 + IMAGE_PPM, 34 + #endif 32 35 MAX_IMAGE_TYPES 33 36 }; 34 37
+2
apps/plugins/imageviewer/ppm/SOURCES
··· 1 + ppm.c 2 + ppm_decoder.c
+233
apps/plugins/imageviewer/ppm/ppm.c
··· 1 + /*************************************************************************** 2 + * __________ __ ___. 3 + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 + * \/ \/ \/ \/ \/ 8 + * $Id$ 9 + * 10 + * Copyright (C) 2010 Marcin Bukat 11 + * 12 + * This program is free software; you can redistribute it and/or 13 + * modify it under the terms of the GNU General Public License 14 + * as published by the Free Software Foundation; either version 2 15 + * of the License, or (at your option) any later version. 16 + * 17 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 + * KIND, either express or implied. 19 + * 20 + ****************************************************************************/ 21 + 22 + #include "plugin.h" 23 + #include "lcd.h" 24 + #include <lib/pluginlib_bmp.h> 25 + #include "../imageviewer.h" 26 + #include "ppm_decoder.h" 27 + #include "bmp.h" 28 + 29 + static char print[32]; /* use a common snprintf() buffer */ 30 + 31 + /* decompressed image in the possible sizes (1,2,4,8), wasting the other */ 32 + static unsigned char *disp[9]; 33 + static unsigned char *disp_buf; 34 + static struct ppm_info ppm; 35 + 36 + #if defined(HAVE_LCD_COLOR) 37 + #define resize_bitmap smooth_resize_bitmap 38 + #else 39 + #define resize_bitmap grey_resize_bitmap 40 + #endif 41 + 42 + #if defined(USEGSLIB) && (CONFIG_PLATFORM & PLATFORM_HOSTED) 43 + /* hack: fix error "undefined reference to `_grey_info'". */ 44 + GREY_INFO_STRUCT 45 + #endif /* USEGSLIB */ 46 + 47 + static void draw_image_rect(struct image_info *info, 48 + int x, int y, int width, int height) 49 + { 50 + unsigned char **pdisp = (unsigned char **)info->data; 51 + 52 + #ifdef HAVE_LCD_COLOR 53 + rb->lcd_bitmap_part((fb_data *)*pdisp, info->x + x, info->y + y, 54 + STRIDE(SCREEN_MAIN, info->width, info->height), 55 + x + MAX(0, (LCD_WIDTH-info->width)/2), 56 + y + MAX(0, (LCD_HEIGHT-info->height)/2), 57 + width, height); 58 + #else 59 + mylcd_ub_gray_bitmap_part(*pdisp, 60 + info->x + x, info->y + y, info->width, 61 + x + MAX(0, (LCD_WIDTH-info->width)/2), 62 + y + MAX(0, (LCD_HEIGHT-info->height)/2), 63 + width, height); 64 + #endif 65 + } 66 + 67 + static int img_mem(int ds) 68 + { 69 + 70 + #ifdef USEGSLIB 71 + return (ppm.x/ds) * (ppm.y/ds); 72 + #else 73 + return (ppm.x/ds) * (ppm.y/ds) * FB_DATA_SZ; 74 + #endif 75 + } 76 + 77 + static int load_image(char *filename, struct image_info *info, 78 + unsigned char *buf, ssize_t *buf_size) 79 + { 80 + int fd; 81 + int rc = PLUGIN_OK; 82 + long time = 0; /* measured ticks */ 83 + int w, h; /* used to center output */ 84 + 85 + unsigned char *memory, *memory_max; 86 + size_t memory_size, file_size; 87 + 88 + /* cleanup */ 89 + memset(&disp, 0, sizeof(disp)); 90 + 91 + /* align buffer */ 92 + memory = (unsigned char *)((intptr_t)(buf + 3) & ~3); 93 + memory_max = (unsigned char *)((intptr_t)(memory + *buf_size) & ~3); 94 + memory_size = memory_max - memory; 95 + 96 + fd = rb->open(filename, O_RDONLY); 97 + if (fd < 0) 98 + { 99 + rb->splashf(HZ, "err opening %s: %d", filename, fd); 100 + return PLUGIN_ERROR; 101 + } 102 + 103 + file_size = rb->filesize(fd); 104 + DEBUGF("reading file '%s'\n", filename); 105 + 106 + if (!iv->running_slideshow) 107 + { 108 + rb->lcd_puts(0, 0, rb->strrchr(filename,'/')+1); 109 + rb->lcd_update(); 110 + } 111 + 112 + if (!iv->running_slideshow) 113 + { 114 + rb->lcd_putsf(0, 1, "loading %zu bytes", file_size); 115 + rb->lcd_update(); 116 + } 117 + 118 + /* init decoder struct */ 119 + ppm.buf = memory; 120 + ppm.buf_size = memory_size; 121 + 122 + /* the actual decoding */ 123 + time = *rb->current_tick; 124 + #ifdef HAVE_ADJUSTABLE_CPU_FREQ 125 + rb->cpu_boost(true); 126 + rc = read_ppm(fd, &ppm); 127 + rb->cpu_boost(false); 128 + #else 129 + rc = read_ppm(fd, &ppm); 130 + #endif /*HAVE_ADJUSTABLE_CPU_FREQ*/ 131 + time = *rb->current_tick - time; 132 + 133 + /* close file descriptor */ 134 + rb->close(fd); 135 + 136 + /* check return value from decoder */ 137 + if ( rc == PLUGIN_ERROR ) 138 + { 139 + rb->splashf(HZ, "ppm decoder error"); 140 + return PLUGIN_ERROR; 141 + } 142 + 143 + if (!iv->running_slideshow) 144 + { 145 + rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ); 146 + rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */ 147 + rb->lcd_putsxy((LCD_WIDTH - w)/2, LCD_HEIGHT - h, print); 148 + rb->lcd_update(); 149 + } 150 + 151 + info->x_size = ppm.x; 152 + info->y_size = ppm.y; 153 + 154 + ppm.native_img_size = (ppm.native_img_size + 3) & ~3; 155 + disp_buf = buf + ppm.native_img_size; 156 + *buf_size = memory_max - disp_buf; 157 + 158 + return PLUGIN_OK; 159 + } 160 + 161 + static int get_image(struct image_info *info, int ds) 162 + { 163 + unsigned char **p_disp = &disp[ds]; /* short cut */ 164 + struct ppm_info *p_ppm = &ppm; 165 + 166 + info->width = ppm.x / ds; 167 + info->height = ppm.y / ds; 168 + info->data = p_disp; 169 + 170 + if (*p_disp != NULL) 171 + { 172 + /* we still have it */ 173 + return PLUGIN_OK; 174 + } 175 + 176 + /* assign image buffer */ 177 + if (ds > 1) 178 + { 179 + if (!iv->running_slideshow) 180 + { 181 + rb->lcd_putsf(0, 3, "resizing %d*%d", info->width, info->height); 182 + rb->lcd_update(); 183 + } 184 + 185 + struct bitmap bmp_src, bmp_dst; 186 + int size = img_mem(ds); 187 + 188 + if (disp_buf + size >= p_ppm->buf + p_ppm->buf_size) 189 + { 190 + /* have to discard the current */ 191 + int i; 192 + for (i=1; i<=8; i++) 193 + disp[i] = NULL; /* invalidate all bitmaps */ 194 + 195 + /* start again from the beginning of the buffer */ 196 + disp_buf = p_ppm->buf + p_ppm->native_img_size; 197 + } 198 + 199 + *p_disp = disp_buf; 200 + disp_buf += size; 201 + 202 + bmp_src.width = ppm.x; 203 + bmp_src.height = ppm.y; 204 + bmp_src.data = ppm.buf; 205 + 206 + bmp_dst.width = info->width; 207 + bmp_dst.height = info->height; 208 + bmp_dst.data = *p_disp; 209 + #ifdef HAVE_ADJUSTABLE_CPU_FREQ 210 + rb->cpu_boost(true); 211 + resize_bitmap(&bmp_src, &bmp_dst); 212 + rb->cpu_boost(false); 213 + #else 214 + resize_bitmap(&bmp_src, &bmp_dst); 215 + #endif /*HAVE_ADJUSTABLE_CPU_FREQ*/ 216 + } 217 + else 218 + { 219 + *p_disp = p_ppm->buf; 220 + } 221 + 222 + return PLUGIN_OK; 223 + } 224 + 225 + const struct image_decoder image_decoder = { 226 + true, 227 + img_mem, 228 + load_image, 229 + get_image, 230 + draw_image_rect, 231 + }; 232 + 233 + IMGDEC_HEADER
+29
apps/plugins/imageviewer/ppm/ppm.make
··· 1 + # __________ __ ___. 2 + # Open \______ \ ____ ____ | | _\_ |__ _______ ___ 3 + # Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 4 + # Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 5 + # Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 6 + # \/ \/ \/ \/ \/ 7 + # $Id$ 8 + # 9 + 10 + PPMSRCDIR := $(IMGVSRCDIR)/ppm 11 + PPMBUILDDIR := $(IMGVBUILDDIR)/ppm 12 + 13 + PPM_SRC := $(call preprocess, $(PPMSRCDIR)/SOURCES) 14 + PPM_OBJ := $(call c2obj, $(PPM_SRC)) 15 + 16 + OTHER_SRC += $(PPM_SRC) 17 + 18 + ROCKS += $(PPMBUILDDIR)/ppm.ovl 19 + 20 + $(PPMBUILDDIR)/ppm.refmap: $(PPM_OBJ) 21 + $(PPMBUILDDIR)/ppm.link: $(PPM_OBJ) $(PPMBUILDDIR)/ppm.refmap 22 + $(PPMBUILDDIR)/ppm.ovl: $(PPM_OBJ) 23 + 24 + PPMFLAGS = $(IMGDECFLAGS) -Os 25 + 26 + # Compile PPM plugin with extra flags (adapted from ZXBox) 27 + $(PPMBUILDDIR)/%.o: $(PPMSRCDIR)/%.c $(PPMSRCDIR)/ppm.make 28 + $(SILENT)mkdir -p $(dir $@) 29 + $(call PRINTS,CC $(subst $(ROOTDIR)/,,$<))$(CC) -I$(dir $<) $(PPMFLAGS) -c $< -o $@
+250
apps/plugins/imageviewer/ppm/ppm_decoder.c
··· 1 + /***************************************************************************** 2 + * __________ __ ___. 3 + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 + * Source | _// __ \_/ ___\| |/ /| __ \ / __ \ \/ / 5 + * Jukebox | | ( (__) ) \___| ( | \_\ ( (__) ) ( 6 + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 + * \/ \/ \/ \/ \/ 8 + * $Id$ 9 + * 10 + * Copyright (C) 2008 Alexander Papst 11 + * 12 + * This program is free software; you can redistribute it and/or 13 + * modify it under the terms of the GNU General Public License 14 + * as published by the Free Software Foundation; either version 2 15 + * of the License, or (at your option) any later version. 16 + * 17 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 + * KIND, either express or implied. 19 + * 20 + ****************************************************************************/ 21 + 22 + #include "plugin.h" 23 + #include "lib/pluginlib_bmp.h" 24 + #include "ppm_decoder.h" 25 + 26 + static int ppm_read_magic_number(int fd) 27 + { 28 + char i1, i2; 29 + if(!rb->read(fd, &i1, 1) || !rb->read(fd, &i2, 1)) 30 + { 31 + ppm_error( "Error reading magic number from ppm image stream. "\ 32 + "Most often, this means your input file is empty." ); 33 + return PLUGIN_ERROR; 34 + } 35 + return i1 * 256 + i2; 36 + } 37 + 38 + static char ppm_getc(int fd) 39 + { 40 + char ch; 41 + 42 + if (!rb->read(fd, &ch, 1)) { 43 + ppm_error("EOF. Read error reading a byte"); 44 + return PLUGIN_ERROR; 45 + } 46 + 47 + if (ch == '#') { 48 + do { 49 + if (!rb->read(fd, &ch, 1)) { 50 + ppm_error("EOF. Read error reading a byte"); 51 + return PLUGIN_ERROR; 52 + } 53 + } while (ch != '\n' && ch != '\r'); 54 + } 55 + return ch; 56 + } 57 + 58 + static int ppm_getuint(int fd) 59 + { 60 + char ch; 61 + int i; 62 + int digitVal; 63 + 64 + do { 65 + ch = ppm_getc(fd); 66 + } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'); 67 + 68 + if (ch < '0' || ch > '9') { 69 + ppm_error("Junk (%c) in file where an integer should be.", ch); 70 + return PLUGIN_ERROR; 71 + } 72 + 73 + i = 0; 74 + 75 + do { 76 + digitVal = ch - '0'; 77 + 78 + if (i > INT_MAX/10 - digitVal) { 79 + ppm_error("ASCII decimal integer in file is "\ 80 + "too large to be processed."); 81 + return PLUGIN_ERROR; 82 + } 83 + 84 + i = i * 10 + digitVal; 85 + ch = ppm_getc(fd); 86 + 87 + } while (ch >= '0' && ch <= '9'); 88 + 89 + return i; 90 + } 91 + 92 + static int ppm_getrawbyte(int fd) 93 + { 94 + unsigned char by; 95 + 96 + if (!rb->read(fd, &by, 1)) { 97 + ppm_error("EOF. Read error while reading a one-byte sample."); 98 + return PLUGIN_ERROR; 99 + } 100 + 101 + return (int)by; 102 + } 103 + 104 + static int ppm_getrawsample(int fd, int const maxval) 105 + { 106 + if (maxval < 256) { 107 + /* The sample is just one byte. Read it. */ 108 + return(ppm_getrawbyte(fd)); 109 + } else { 110 + /* The sample is two bytes. Read both. */ 111 + unsigned char byte_pair[2]; 112 + 113 + if (!rb->read(fd, byte_pair, 2)) { 114 + ppm_error("EOF. Read error while reading a long sample."); 115 + return PLUGIN_ERROR; 116 + } 117 + return((byte_pair[0]<<8) | byte_pair[1]); 118 + } 119 + } 120 + 121 + /* Read from the file header dimensions as well as max 122 + * int value used 123 + */ 124 + static int read_ppm_init_rest(int fd, struct ppm_info *ppm) 125 + { 126 + /* Read size. */ 127 + ppm->x = ppm_getuint(fd); 128 + ppm->y = ppm_getuint(fd); 129 + 130 + #ifdef HAVE_LCD_COLOR 131 + ppm->native_img_size = ppm->x * ppm->y * FB_DATA_SZ; 132 + #endif 133 + 134 + if (ppm->native_img_size > ppm->buf_size) { 135 + ppm_error("Imagesize (%ld pixels) is too large. "\ 136 + "The maximum allowed is %ld.", 137 + (long)ppm->native_img_size, 138 + (long)ppm->buf_size); 139 + return PLUGIN_ERROR; 140 + } 141 + 142 + /* Read maxval. */ 143 + ppm->maxval = ppm_getuint(fd); 144 + 145 + if (ppm->maxval > PPM_OVERALLMAXVAL) { 146 + ppm_error("maxval of input image (%u) is too large. "\ 147 + "The maximum allowed by the PPM is %u.", 148 + ppm->maxval, PPM_OVERALLMAXVAL); 149 + return PLUGIN_ERROR; 150 + } 151 + if (ppm->maxval == 0) { 152 + ppm_error("maxval of input image is zero."); 153 + return PLUGIN_ERROR; 154 + } 155 + return 1; 156 + } 157 + 158 + static void read_ppm_init(int fd, struct ppm_info *ppm) 159 + { 160 + /* Check magic number. */ 161 + ppm->format = ppm_read_magic_number( fd ); 162 + 163 + if (ppm->format == PLUGIN_ERROR) return; 164 + switch (ppm->format) { 165 + case PPM_FORMAT: 166 + case RPPM_FORMAT: 167 + if(read_ppm_init_rest(fd, ppm) == PLUGIN_ERROR) { 168 + ppm->format = PLUGIN_ERROR; 169 + } 170 + break; 171 + 172 + default: 173 + ppm_error( "Bad magic number - not a ppm or rppm file." ); 174 + ppm->format = PLUGIN_ERROR; 175 + } 176 + } 177 + 178 + #if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE 179 + #define BUFADDR(x, y, width, height) ( ppm->buf + (height*(x) + (y))*FB_DATA_SZ) 180 + #else 181 + #define BUFADDR(x, y, width, height) ( ppm->buf + (width*(y) + (x))*FB_DATA_SZ) 182 + #endif 183 + 184 + static int read_ppm_row(int fd, struct ppm_info *ppm, int row) 185 + { 186 + 187 + int col; 188 + int r, g, b; 189 + switch (ppm->format) { 190 + case PPM_FORMAT: 191 + for (col = 0; col < ppm->x; ++col) { 192 + r = ppm_getuint(fd); 193 + g = ppm_getuint(fd); 194 + b = ppm_getuint(fd); 195 + 196 + if (r == PLUGIN_ERROR || g == PLUGIN_ERROR || 197 + b == PLUGIN_ERROR) 198 + { 199 + return PLUGIN_ERROR; 200 + } 201 + *(fb_data *)BUFADDR(col, row, ppm->x, ppm->y) = LCD_RGBPACK( 202 + (255 * r)/ppm->maxval, 203 + (255 * g)/ppm->maxval, 204 + (255 * b)/ppm->maxval); 205 + } 206 + break; 207 + 208 + case RPPM_FORMAT: 209 + for (col = 0; col < ppm->x; ++col) { 210 + r = ppm_getrawsample(fd, ppm->maxval); 211 + g = ppm_getrawsample(fd, ppm->maxval); 212 + b = ppm_getrawsample(fd, ppm->maxval); 213 + 214 + if (r == PLUGIN_ERROR || g == PLUGIN_ERROR || 215 + b == PLUGIN_ERROR) 216 + { 217 + return PLUGIN_ERROR; 218 + } 219 + *(fb_data *)BUFADDR(col, row, ppm->x, ppm->y) = LCD_RGBPACK( 220 + (255 * r)/ppm->maxval, 221 + (255 * g)/ppm->maxval, 222 + (255 * b)/ppm->maxval); 223 + } 224 + break; 225 + 226 + default: 227 + ppm_error("What?!"); 228 + return PLUGIN_ERROR; 229 + } 230 + return 1; 231 + } 232 + 233 + /* public */ 234 + int read_ppm(int fd, struct ppm_info *ppm) 235 + { 236 + int row; 237 + 238 + read_ppm_init(fd, ppm); 239 + 240 + if(ppm->format == PLUGIN_ERROR) { 241 + return PLUGIN_ERROR; 242 + } 243 + 244 + for (row = 0; row < ppm->y; ++row) { 245 + if( read_ppm_row(fd, ppm, row) == PLUGIN_ERROR) { 246 + return PLUGIN_ERROR; 247 + } 248 + } 249 + return 1; 250 + }
+44
apps/plugins/imageviewer/ppm/ppm_decoder.h
··· 1 + /*************************************************************************** 2 + * __________ __ ___. 3 + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 + * \/ \/ \/ \/ \/ 8 + * $Id$ 9 + * 10 + * Copyright (C) 2010 Marcin Bukat 11 + * 12 + * This program is free software; you can redistribute it and/or 13 + * modify it under the terms of the GNU General Public License 14 + * as published by the Free Software Foundation; either version 2 15 + * of the License, or (at your option) any later version. 16 + * 17 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 + * KIND, either express or implied. 19 + * 20 + ****************************************************************************/ 21 + 22 + /* Magic constants. */ 23 + #define PPM_MAGIC1 'P' 24 + #define PPM_MAGIC2 '3' 25 + #define RPPM_MAGIC2 '6' 26 + #define PPM_FORMAT (PPM_MAGIC1 * 256 + PPM_MAGIC2) 27 + #define RPPM_FORMAT (PPM_MAGIC1 * 256 + RPPM_MAGIC2) 28 + 29 + #define PPM_OVERALLMAXVAL 65535 30 + 31 + #define ppm_error(...) rb->splashf(HZ*2, __VA_ARGS__ ) 32 + 33 + struct ppm_info { 34 + int x; 35 + int y; 36 + int maxval; 37 + int format; 38 + unsigned char *buf; 39 + size_t buf_size; 40 + unsigned int native_img_size; 41 + }; 42 + 43 + /* public prototype */ 44 + int read_ppm(int fd, struct ppm_info *ppm);
-355
apps/plugins/ppmviewer.c
··· 1 - /***************************************************************************** 2 - * __________ __ ___. 3 - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 - * Source | _// __ \_/ ___\| |/ /| __ \ / __ \ \/ / 5 - * Jukebox | | ( (__) ) \___| ( | \_\ ( (__) ) ( 6 - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 - * \/ \/ \/ \/ \/ 8 - * $Id$ 9 - * 10 - * Copyright (C) 2008 Alexander Papst 11 - * 12 - * This program is free software; you can redistribute it and/or 13 - * modify it under the terms of the GNU General Public License 14 - * as published by the Free Software Foundation; either version 2 15 - * of the License, or (at your option) any later version. 16 - * 17 - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 - * KIND, either express or implied. 19 - * 20 - ****************************************************************************/ 21 - 22 - #include "plugin.h" 23 - #include "lib/pluginlib_bmp.h" 24 - 25 - /* Magic constants. */ 26 - #define PPM_MAGIC1 'P' 27 - #define PPM_MAGIC2 '3' 28 - #define RPPM_MAGIC2 '6' 29 - #define PPM_FORMAT (PPM_MAGIC1 * 256 + PPM_MAGIC2) 30 - #define RPPM_FORMAT (PPM_MAGIC1 * 256 + RPPM_MAGIC2) 31 - 32 - #define PPM_OVERALLMAXVAL 65535 33 - #define PPM_MAXSIZE (300*1024)/sizeof(fb_data) 34 - 35 - #define ppm_error(...) rb->splashf(HZ*2, __VA_ARGS__ ) 36 - 37 - static fb_data *buffer, *lcd_buf; 38 - 39 - int ppm_read_magic_number(int fd) 40 - { 41 - char i1, i2; 42 - if(!rb->read(fd, &i1, 1) || !rb->read(fd, &i2, 1)) 43 - { 44 - ppm_error( "Error reading magic number from ppm image stream. "\ 45 - "Most often, this means your input file is empty." ); 46 - return PLUGIN_ERROR; 47 - } 48 - return i1 * 256 + i2; 49 - } 50 - 51 - char ppm_getc(int fd) 52 - { 53 - char ch; 54 - 55 - if (!rb->read(fd, &ch, 1)) { 56 - ppm_error("EOF. Read error reading a byte"); 57 - return PLUGIN_ERROR; 58 - } 59 - 60 - if (ch == '#') { 61 - do { 62 - if (!rb->read(fd, &ch, 1)) { 63 - ppm_error("EOF. Read error reading a byte"); 64 - return PLUGIN_ERROR; 65 - } 66 - } while (ch != '\n' && ch != '\r'); 67 - } 68 - return ch; 69 - } 70 - 71 - int ppm_getuint(int fd) 72 - { 73 - char ch; 74 - int i; 75 - int digitVal; 76 - 77 - do { 78 - ch = ppm_getc(fd); 79 - } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'); 80 - 81 - if (ch < '0' || ch > '9') { 82 - ppm_error("Junk (%c) in file where an integer should be.", ch); 83 - return PLUGIN_ERROR; 84 - } 85 - 86 - i = 0; 87 - 88 - do { 89 - digitVal = ch - '0'; 90 - 91 - if (i > INT_MAX/10 - digitVal) { 92 - ppm_error("ASCII decimal integer in file is "\ 93 - "too large to be processed."); 94 - return PLUGIN_ERROR; 95 - } 96 - 97 - i = i * 10 + digitVal; 98 - ch = ppm_getc(fd); 99 - 100 - } while (ch >= '0' && ch <= '9'); 101 - 102 - return i; 103 - } 104 - 105 - int ppm_getrawbyte(int fd) 106 - { 107 - unsigned char by; 108 - 109 - if (!rb->read(fd, &by, 1)) { 110 - ppm_error("EOF. Read error while reading a one-byte sample."); 111 - return PLUGIN_ERROR; 112 - } 113 - 114 - return (int)by; 115 - } 116 - 117 - int ppm_getrawsample(int fd, int const maxval) 118 - { 119 - if (maxval < 256) { 120 - /* The sample is just one byte. Read it. */ 121 - return(ppm_getrawbyte(fd)); 122 - } else { 123 - /* The sample is two bytes. Read both. */ 124 - unsigned char byte_pair[2]; 125 - 126 - if (!rb->read(fd, byte_pair, 2)) { 127 - ppm_error("EOF. Read error while reading a long sample."); 128 - return PLUGIN_ERROR; 129 - } 130 - return((byte_pair[0]<<8) | byte_pair[1]); 131 - } 132 - } 133 - 134 - int read_ppm_init_rest(int fd, 135 - int * const cols, 136 - int * const rows, 137 - int * const maxval) 138 - { 139 - /* Read size. */ 140 - *cols = ppm_getuint(fd); 141 - *rows = ppm_getuint(fd); 142 - 143 - if ((long unsigned int)(*cols * *rows) > PPM_MAXSIZE) { 144 - ppm_error("Imagesize (%ld pixels) is too large. "\ 145 - "The maximum allowed is %ld.", 146 - (long unsigned int)(*cols * *rows), 147 - (long unsigned int)PPM_MAXSIZE); 148 - return PLUGIN_ERROR; 149 - } 150 - 151 - /* Read maxval. */ 152 - *maxval = ppm_getuint(fd); 153 - 154 - if (*maxval > PPM_OVERALLMAXVAL) { 155 - ppm_error("maxval of input image (%u) is too large. "\ 156 - "The maximum allowed by the PPM is %u.", 157 - *maxval, PPM_OVERALLMAXVAL); 158 - return PLUGIN_ERROR; 159 - } 160 - if (*maxval == 0) { 161 - ppm_error("maxval of input image is zero."); 162 - return PLUGIN_ERROR; 163 - } 164 - return 1; 165 - } 166 - 167 - void read_ppm_init(int fd, 168 - int * const cols, 169 - int * const rows, 170 - int * const maxval, 171 - int * const format) 172 - { 173 - /* Check magic number. */ 174 - *format = ppm_read_magic_number( fd ); 175 - 176 - if (*format == PLUGIN_ERROR) return; 177 - switch (*format) { 178 - case PPM_FORMAT: 179 - case RPPM_FORMAT: 180 - if(read_ppm_init_rest(fd, cols, rows, maxval) == PLUGIN_ERROR) { 181 - *format = PLUGIN_ERROR; 182 - } 183 - break; 184 - 185 - default: 186 - ppm_error( "Bad magic number - not a ppm or rppm file." ); 187 - *format = PLUGIN_ERROR; 188 - } 189 - } 190 - 191 - #if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE 192 - #define BUFADDR(x, y, width, height) ( buffer + height*(x) + (y)) 193 - #else 194 - #define BUFADDR(x, y, width, height) ( buffer + width*(y) + (x)) 195 - #endif 196 - 197 - int read_ppm_row(int fd, 198 - int const row, 199 - int const cols, 200 - int const rows, 201 - int const maxval, 202 - int const format) 203 - { 204 - #if !(defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE) 205 - (void) rows; 206 - #endif 207 - 208 - int col; 209 - int r, g, b; 210 - switch (format) { 211 - case PPM_FORMAT: 212 - for (col = 0; col < cols; ++col) { 213 - r = ppm_getuint(fd); 214 - g = ppm_getuint(fd); 215 - b = ppm_getuint(fd); 216 - 217 - if (r == PLUGIN_ERROR || g == PLUGIN_ERROR || 218 - b == PLUGIN_ERROR) 219 - { 220 - return PLUGIN_ERROR; 221 - } 222 - *BUFADDR(col, row, cols, rows) = LCD_RGBPACK( 223 - (255 / maxval) * r, 224 - (255 / maxval) * g, 225 - (255 / maxval) * b); 226 - } 227 - break; 228 - 229 - case RPPM_FORMAT: 230 - for (col = 0; col < cols; ++col) { 231 - r = ppm_getrawsample(fd, maxval); 232 - g = ppm_getrawsample(fd, maxval); 233 - b = ppm_getrawsample(fd, maxval); 234 - 235 - if (r == PLUGIN_ERROR || g == PLUGIN_ERROR || 236 - b == PLUGIN_ERROR) 237 - { 238 - return PLUGIN_ERROR; 239 - } 240 - *BUFADDR(col, row, cols, rows) = LCD_RGBPACK( 241 - (255 / maxval) * r, 242 - (255 / maxval) * g, 243 - (255 / maxval) * b); 244 - } 245 - break; 246 - 247 - default: 248 - ppm_error("What?!"); 249 - return PLUGIN_ERROR; 250 - } 251 - return 1; 252 - } 253 - 254 - int read_ppm(int fd, 255 - int * const cols, 256 - int * const rows, 257 - int * const maxval) 258 - { 259 - int row; 260 - int format; 261 - 262 - read_ppm_init(fd, cols, rows, maxval, &format); 263 - 264 - if(format == PLUGIN_ERROR) { 265 - return PLUGIN_ERROR; 266 - } 267 - 268 - for (row = 0; row < *rows; ++row) { 269 - if( read_ppm_row(fd, row, *cols, *rows, *maxval, format) == PLUGIN_ERROR) { 270 - return PLUGIN_ERROR; 271 - } 272 - } 273 - return 1; 274 - } 275 - 276 - /* this is the plugin entry point */ 277 - enum plugin_status plugin_start(const void* parameter) 278 - { 279 - static char filename[MAX_PATH]; 280 - int fd; 281 - 282 - int cols; 283 - int rows; 284 - int maxval; 285 - 286 - int result; 287 - 288 - struct bitmap small_bitmap, orig_bitmap; 289 - 290 - if(!parameter) return PLUGIN_ERROR; 291 - 292 - size_t buffer_size; 293 - char *audiobuf = rb->plugin_get_buffer(&buffer_size); 294 - if (buffer_size < PPM_MAXSIZE + LCD_WIDTH * LCD_HEIGHT + 1) 295 - { 296 - /* steal from audiobuffer if plugin buffer is too small */ 297 - audiobuf = rb->plugin_get_audio_buffer(&buffer_size); 298 - 299 - if (buffer_size < PPM_MAXSIZE + LCD_WIDTH * LCD_HEIGHT + 1) 300 - { 301 - rb->splash(HZ, "Not enough memory"); 302 - return PLUGIN_ERROR; 303 - } 304 - } 305 - 306 - /* align on 16 bits */ 307 - audiobuf = (char *)(((uintptr_t)audiobuf + 1) & ~1); 308 - buffer = (fb_data *)audiobuf; 309 - lcd_buf = (fb_data*) (audiobuf + PPM_MAXSIZE); 310 - 311 - rb->strcpy(filename, parameter); 312 - 313 - fd = rb->open(filename, O_RDONLY); 314 - if (fd < 0) 315 - { 316 - ppm_error("Couldnt open file: %s, %d", filename, fd); 317 - return PLUGIN_ERROR; 318 - } 319 - 320 - result = read_ppm(fd, &cols, &rows, &maxval); 321 - 322 - rb->close(fd); 323 - if(result == PLUGIN_ERROR) return PLUGIN_ERROR; 324 - 325 - orig_bitmap.width = cols; 326 - orig_bitmap.height = rows; 327 - orig_bitmap.data = (char*)buffer; 328 - 329 - if (cols > LCD_WIDTH || rows > LCD_HEIGHT) 330 - { 331 - if (cols > LCD_WIDTH) { 332 - small_bitmap.width = LCD_WIDTH; 333 - small_bitmap.height = 334 - (int)(((float)LCD_WIDTH / (float)cols) * (float)rows); 335 - 336 - } else { /* rows > LCD_HEIGHT */ 337 - 338 - small_bitmap.width = 339 - (int)(((float)LCD_HEIGHT / (float)rows) * (float)cols); 340 - small_bitmap.height = LCD_HEIGHT; 341 - } 342 - small_bitmap.data = (char*)lcd_buf; 343 - 344 - smooth_resize_bitmap( &orig_bitmap, &small_bitmap ); 345 - 346 - rb->lcd_bitmap((fb_data*)small_bitmap.data, 0, 0, 347 - small_bitmap.width, small_bitmap.height); 348 - } else { 349 - rb->lcd_bitmap((fb_data*)orig_bitmap.data, 0, 0, cols, rows); 350 - } 351 - rb->lcd_update(); 352 - rb->button_get(true); 353 - 354 - return PLUGIN_OK; 355 - }
+3 -1
apps/plugins/viewers.config
··· 20 20 jpeg,viewers/test_mem_jpeg,- 21 21 jpeg,viewers/bench_mem_jpeg,- 22 22 png,viewers/imageviewer,2 23 + #ifdef HAVE_LCD_COLOR 24 + ppm,viewers/imageviewer,2 25 + #endif 23 26 ucl,viewers/rockbox_flash,3 24 27 rvf,viewers/video,4 25 28 mp3,viewers/vbrfix,5 ··· 73 76 sna,viewers/zxbox,12 74 77 tzx,viewers/zxbox,12 75 78 z80,viewers/zxbox,12 76 - ppm,viewers/ppmviewer,2 77 79 cfg,viewers/theme_remove,- 78 80 *,viewers/properties,- 79 81 *,viewers/shortcuts_append,-