A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 252 lines 6.8 kB view raw
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#include "../imageviewer.h" 26 27static int ppm_read_magic_number(int fd) 28{ 29 unsigned char i1, i2; 30 if(rb->read(fd, &i1, 1) < 1 || rb->read(fd, &i2, 1) < 1) 31 { 32 ppm_error( "Error reading magic number from ppm image stream. "\ 33 "Most often, this means your input file is empty." ); 34 return PLUGIN_ERROR; 35 } 36 return i1 * 256 + i2; 37} 38 39static int ppm_getc(int fd) 40{ 41 unsigned char ch; 42 43 if (rb->read(fd, &ch, 1) < 1) { 44 ppm_error("EOF. Read error reading a byte"); 45 return PLUGIN_ERROR; 46 } 47 48 if (ch == '#') { 49 do { 50 if (rb->read(fd, &ch, 1) < 1) { 51 ppm_error("EOF. Read error reading a byte"); 52 return PLUGIN_ERROR; 53 } 54 } while (ch != '\n' && ch != '\r'); 55 } 56 return (int)ch; 57} 58 59static int ppm_getuint(int fd) 60{ 61 int ch; 62 int i; 63 int digitVal; 64 65 do { 66 ch = ppm_getc(fd); 67 } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'); 68 69 if (ch == PLUGIN_ERROR) return PLUGIN_ERROR; 70 if (ch < '0' || ch > '9') { 71 ppm_error("Junk (%c) in file where an integer should be.", ch); 72 return PLUGIN_ERROR; 73 } 74 75 i = 0; 76 77 do { 78 digitVal = ch - '0'; 79 80 if (i > INT_MAX/10 - digitVal) { 81 ppm_error("ASCII decimal integer in file is "\ 82 "too large to be processed."); 83 return PLUGIN_ERROR; 84 } 85 86 i = i * 10 + digitVal; 87 ch = ppm_getc(fd); 88 89 } while (ch >= '0' && ch <= '9'); 90 if (ch == PLUGIN_ERROR) return PLUGIN_ERROR; 91 92 return i; 93} 94 95static int ppm_getrawbyte(int fd) 96{ 97 unsigned char by; 98 99 if (rb->read(fd, &by, 1) < 1) { 100 ppm_error("EOF. Read error while reading a one-byte sample."); 101 return PLUGIN_ERROR; 102 } 103 104 return (int)by; 105} 106 107static int ppm_getrawsample(int fd, int const maxval) 108{ 109 if (maxval < 256) { 110 /* The sample is just one byte. Read it. */ 111 return(ppm_getrawbyte(fd)); 112 } else { 113 /* The sample is two bytes. Read both. */ 114 unsigned char byte_pair[2]; 115 116 if (rb->read(fd, byte_pair, 2) < 2) { 117 ppm_error("EOF. Read error while reading a long sample."); 118 return PLUGIN_ERROR; 119 } 120 return((byte_pair[0]<<8) | byte_pair[1]); 121 } 122} 123 124/* Read from the file header dimensions as well as max 125 * int value used 126 */ 127static int read_ppm_init_rest(int fd, struct ppm_info *ppm) 128{ 129 /* Read size. */ 130 ppm->x = ppm_getuint(fd); 131 ppm->y = ppm_getuint(fd); 132 133#ifdef HAVE_LCD_COLOR 134 ppm->native_img_size = ppm->x * ppm->y * FB_DATA_SZ; 135#endif 136 137 if (ppm->native_img_size > ppm->buf_size) { 138 return PLUGIN_OUTOFMEM; 139 } 140 141 /* Read maxval. */ 142 ppm->maxval = ppm_getuint(fd); 143 144 if (ppm->maxval > PPM_OVERALLMAXVAL) { 145 ppm_error("maxval of input image (%u) is too large. "\ 146 "The maximum allowed by the PPM is %u.", 147 ppm->maxval, PPM_OVERALLMAXVAL); 148 return PLUGIN_ERROR; 149 } 150 if (ppm->maxval == 0) { 151 ppm_error("maxval of input image is zero."); 152 return PLUGIN_ERROR; 153 } 154 return PLUGIN_OK; 155} 156 157static int read_ppm_init(int fd, struct ppm_info *ppm) 158{ 159 /* Check magic number. */ 160 ppm->format = ppm_read_magic_number( fd ); 161 162 if (ppm->format == PLUGIN_ERROR) return PLUGIN_ERROR; 163 switch (ppm->format) { 164 case PPM_FORMAT: 165 case RPPM_FORMAT: 166 return read_ppm_init_rest(fd, ppm); 167 168 default: 169 ppm_error( "Bad magic number - not a ppm or rppm file." ); 170 return PLUGIN_ERROR; 171 } 172 return PLUGIN_OK; 173} 174 175static int read_ppm_row(int fd, struct ppm_info *ppm, int row) 176{ 177 int col; 178 int r, g, b; 179#ifdef HAVE_LCD_COLOR 180#if LCD_STRIDEFORMAT == VERTICAL_STRIDE 181 fb_data *dst = (fb_data *) ppm->buf + row; 182 const int stride = ppm->x; 183#else 184 fb_data *dst = (fb_data *) ppm->buf + ppm->x*row; 185 const int stride = 1; 186#endif 187#endif /* HAVE_LCD_COLOR */ 188 switch (ppm->format) { 189 case PPM_FORMAT: 190 for (col = 0; col < ppm->x; ++col) { 191 r = ppm_getuint(fd); 192 g = ppm_getuint(fd); 193 b = ppm_getuint(fd); 194 195 if (r == PLUGIN_ERROR || g == PLUGIN_ERROR || 196 b == PLUGIN_ERROR) 197 { 198 return PLUGIN_ERROR; 199 } 200 *dst = FB_RGBPACK( 201 (255 * r)/ppm->maxval, 202 (255 * g)/ppm->maxval, 203 (255 * b)/ppm->maxval); 204 dst += stride; 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 *dst = FB_RGBPACK( 220 (255 * r)/ppm->maxval, 221 (255 * g)/ppm->maxval, 222 (255 * b)/ppm->maxval); 223 dst += stride; 224 } 225 break; 226 227 default: 228 ppm_error("What?!"); 229 return PLUGIN_ERROR; 230 } 231 return PLUGIN_OK; 232} 233 234/* public */ 235int read_ppm(int fd, struct ppm_info *ppm) 236{ 237 int row, ret; 238 239 ret = read_ppm_init(fd, ppm); 240 if(ret != PLUGIN_OK) { 241 return ret; 242 } 243 244 for (row = 0; row < ppm->y; ++row) { 245 ret = read_ppm_row(fd, ppm, row); 246 if(ret != PLUGIN_OK) { 247 return ret; 248 } 249 iv->cb_progress(row, ppm->y); 250 } 251 return PLUGIN_OK; 252}