ppmtoc.c (6052B)
1 #include <stdlib.h> 2 #include <stdint.h> 3 #include <stdio.h> 4 #include <unistd.h> 5 #include <fcntl.h> 6 7 typedef struct 8 { 9 uint32_t x, y; 10 } vec2; 11 12 typedef struct 13 { 14 vec2 dimensions; 15 uint32_t datasize, bitdepth; 16 uint8_t *start; 17 } imginfo; 18 19 typedef struct 20 { 21 uint32_t columns; 22 uint8_t *start; 23 } palinfo; 24 25 vec2 ParseDimensions(uint8_t *begin, uint32_t length) 26 { 27 vec2 ret; 28 ret.x = ret.y = 0; 29 uint8_t xd = 0; 30 for (uint8_t i = 0; i < length; ++i) 31 { 32 if (*(begin + i) == ' ') 33 { 34 xd = 1; 35 continue; 36 } 37 38 if (xd) 39 { 40 ret.y = ret.y * 10; 41 ret.y += *(begin + i) - '0'; 42 } 43 else 44 { 45 ret.x = ret.x * 10; 46 ret.x += *(begin + i) - '0'; 47 } 48 } 49 return ret; 50 } 51 52 uint32_t ParseBitDepth(uint8_t *begin, uint32_t length) 53 { 54 uint32_t depth = 0; 55 for (uint32_t i = 0; i < length; ++i) 56 { 57 depth = depth * 10; 58 depth += *(begin + i) - '0'; 59 } 60 return depth; 61 } 62 63 64 /* Parse the image header 65 ppm files begin with the identifying string P6 66 Next is the image dimensions on one line separated by a space 67 And finally the bit depth 68 We need all of this for error handling 69 Comments can appear at any point 70 */ 71 imginfo ParseImgInfo(uint8_t *filedata, uint32_t size) 72 { 73 imginfo ret; 74 ret.dimensions.x = 0; 75 ret.dimensions.y = 0; 76 ret.datasize = size; 77 uint32_t curs = 0; 78 79 uint8_t *line_start; 80 uint8_t pmode; 81 line_start = filedata; 82 83 //chop it up into lines and parse 84 while (1) 85 { 86 while (*(line_start + curs) != '\n') 87 { 88 curs++; 89 ret.datasize--; 90 } 91 92 if (*line_start == '#') 93 { 94 line_start += (curs + 1); 95 curs = 0; 96 continue; 97 } 98 99 if (pmode == 0) //first line, file identifier 100 { 101 if (!(*line_start == 'P' && *(line_start + 1) == '6')) 102 { 103 //ain't no ppm! 104 fprintf(stdout, "Invalid image file\n"); 105 exit(0); 106 } 107 pmode = 1; 108 } 109 else if (pmode == 1) //second line, dimensions 110 { 111 ret.dimensions = ParseDimensions(line_start, curs); 112 pmode = 2; 113 } 114 else if (pmode == 2) //third line, bit depth 115 { 116 ret.bitdepth = ParseBitDepth(line_start, curs); 117 if (ret.bitdepth != 255) 118 { 119 fprintf(stdout, "Can't support bitdepth other than 255\n"); 120 exit(0); 121 } 122 123 //24 bit colors, datasize can be determined by dimensions 124 ret.datasize = ret.dimensions.x * ret.dimensions.y * 3; //3 bytes 125 ret.start = (line_start + curs + 1); 126 return ret; 127 } 128 else 129 { 130 break; 131 } 132 133 line_start += (curs + 1); 134 curs = 0; 135 } 136 fprintf(stdout, "Error loading image file"); 137 exit(0); 138 } 139 140 void ParseImgData(uint32_t* clist, imginfo finfo) 141 { 142 uint32_t curs = 0; 143 for (uint32_t i = 0; i < (finfo.datasize / 3); ++i) 144 { 145 *(clist + i) = 0; 146 for (int i2 = 0; i2 < 3; i2++) 147 { 148 *(clist + i) |= *(finfo.start + curs) << ((2 - i2) * 8); 149 curs++; 150 } 151 } 152 } 153 154 //TODO: write the function lol 155 //Just need to do this and fix the ParsePalette function 156 //to use the incoming info struct 157 /* Parse the palette header 158 begins with identifying string "GIMP Palette" 159 Next is the name of the palette ("Name: thename") 160 then the amount of columns ("Columns: number") 161 the column amount is the only real important data */ 162 palinfo ParsePalHeader(uint8_t *filedata) 163 { 164 palinfo ret; 165 ret.columns = 0; 166 ret.start = filedata; 167 ret.datasize = 0; 168 return ret; 169 } 170 171 //can only parse 16 column palettes for now 172 void ParsePalette(uint32_t *clist, uint8_t *filedata, palinfo info) 173 { 174 uint32_t curs = 0; 175 for (int i = 0; i < 16; ++i) 176 { 177 *(clist + i) = 0; 178 uint8_t offs = 16; 179 uint8_t num = 0; 180 //parse line by line 181 while(1) 182 { 183 if (*(filedata + curs) == '\n') 184 { 185 *(clist + i) |= num; 186 break; 187 } 188 else if (*(filedata + curs) == ' ' && num) 189 { 190 *(clist + i) |= num << offs; 191 num = 0; 192 offs = 8; 193 } 194 else if (*(filedata + curs) != ' ') 195 { 196 num *= 10; 197 num += *(filedata + curs) - '0'; 198 } 199 curs++; 200 } 201 curs++; 202 // fprintf (stdout, "%x | curs: %d\n", *(clist + i), curs); 203 } 204 } 205 206 //print the image to stdout as an indexed .c array 207 void OutputIndexed(uint32_t *colors, uint32_t *pixels, imginfo *finfo) 208 { 209 fprintf(stdout, "#include <stdint.h>\n"); 210 fprintf(stdout, "static const uint8_t spritedata[%d] = \n{\n ", (finfo->datasize / 3)); 211 212 for (uint32_t i = 0; i < (finfo->datasize / 3); ++i) 213 { 214 uint8_t index = 0; 215 for (int i2 = 0; i2 < 11; ++i2) 216 { 217 if (*(pixels + i) == *(colors + i2)) 218 { 219 index = i2; 220 } 221 } 222 fprintf(stdout, "%d", index); 223 if ( i != (finfo->datasize / 3) - 1) 224 { 225 fprintf(stdout, ", "); 226 } 227 if ( !((i + 1) % 10)) 228 { 229 fprintf(stdout, "\n "); 230 } 231 } 232 fprintf(stdout, "\n};\n"); 233 } 234 235 236 int main(int argc, char *argv[]) 237 { 238 if (argc != 3) 239 { 240 fprintf(stdout, "Wrong number of arguments (%d).\n", argc); 241 fprintf(stdout, "Usage: ppmtoc image palette\n"); 242 return -1; 243 } 244 245 char *fname_img = argv[1]; 246 // char *fname_pal = argv[2]; 247 // fprintf(stdout, "Arg 1: %s\n", (argv[1])); 248 // fprintf(stdout, "Arg 2: %s\n", (argv[2])); 249 250 int img = 0; 251 img = open(fname_img, O_RDONLY, 700); 252 if (img < 0) 253 { 254 fprintf(stdout, "%s : Couldn't open file\n", fname_img); 255 return -1; 256 } 257 258 uint8_t buffer[64000]; //this oughta be big enough!! 259 uint32_t pal_columns = 0; 260 int size; 261 size = read(img, &buffer, 64000); 262 close(img); 263 264 //parse image header 265 imginfo info = ParseImgInfo(&buffer[0], size); 266 267 fprintf(stdout, "// Width: %d\n", info.dimensions.x); 268 fprintf(stdout, "// Height: %d\n", info.dimensions.y); 269 fprintf(stdout, "// Datasize: %d\n", info.datasize); 270 fprintf(stdout, "// BitDepth: %d\n", info.bitdepth); 271 272 /* 273 //load the image into an array of 32bit colors 274 uint32_t pixels[info.datasize / 3]; 275 ParseImgData(&pixels[0], info); 276 277 //now open the palette file 278 int pal = 0; 279 pal = open(fname_pal, O_RDONLY, 700); 280 if (pal < 0) 281 { 282 fprintf(stdout, "%s : Couldn't open file\n", fname_pal); 283 return -1; 284 } 285 size = read(pal, &buffer, 64000); 286 close(pal); 287 288 //parse palette header 289 palinfo pinfo = ParsePalHeader(&buffer[0]); 290 uint32_t colors[pinfo.columns]; 291 292 //now parse palette file 293 ParsePalette(&colors[0], &buffer[0], pinfo); 294 295 //compare the image data to the palette file and output 296 //an indexed image in a c array 297 OutputIndexed(&colors[0], &pixels[0], &info); 298 */ 299 300 }