A very small library for reading image files
at main 2.6 kB view raw
1#include "img.h" 2#include <stdio.h> 3#include <stdlib.h> 4 5struct Ctx { 6 FILE *file; 7}; 8 9static ImgStatus ctxRead(ImgAny user, ImgAny buf, ImgSz bufSz) 10{ 11 struct Ctx *ctx = user; 12 if(fread(buf, bufSz, 1, ctx->file) != 1) { 13 return ImgErrIO; 14 } 15 return ImgOK; 16} 17 18static ImgStatus ctxSeek(ImgAny user, ImgOff off) 19{ 20 struct Ctx *ctx = user; 21 fseek(ctx->file, off, SEEK_CUR); 22 return ImgOK; 23} 24 25static ImgStatus ctxClose(ImgAny user) 26{ 27 struct Ctx *ctx = user; 28 fclose(ctx->file); 29 return ImgOK; 30} 31 32static void saveToPPM_RGB(const Img *img, const ImgU8 *pixels, const char *filename) 33{ 34 FILE *file = fopen(filename, "wb"); 35 if(file == NULL) { 36 perror("Could not open output file"); 37 return; 38 } 39 40 fprintf(file, "P6\n%u %u\n255\n", img->width, img->height); 41 fwrite(pixels, 3, (ImgSz)img->width * img->height, file); 42 fclose(file); 43} 44 45static void saveToPPM_RGBA(const Img *img, const ImgU8 *pixels, const char *filename) 46{ 47 FILE *file = fopen(filename, "wb"); 48 if(file == NULL) { 49 perror("Could not open output file"); 50 return; 51 } 52 53 fprintf(file, "P6\n%u %u\n255\n", img->width, img->height); 54 for(ImgSz i = 0; i < (ImgSz)img->width * img->height; ++i) { 55 fwrite(&pixels[i * 4], 1, 3, file); 56 } 57 fclose(file); 58} 59 60int main(int argc, char **argv) 61{ 62 if(argc < 3) { 63 printf("Usage: %s <input file> <output PPM file>\n", argv[0]); 64 return 1; 65 } 66 67 FILE *file = fopen(argv[1], "rb"); 68 if(file == NULL) { 69 perror("Could not open file"); 70 return 1; 71 } 72 73 struct Ctx ctx; 74 ctx.file = file; 75 ImgFuncs funcs; 76 funcs.user = &ctx; 77 funcs.read = &ctxRead; 78 funcs.seek = &ctxSeek; 79 funcs.close = &ctxClose; 80 81 Img img; 82 ImgStatus status = imgOpen(&img, &funcs); 83 if(status != ImgOK) { 84 printf("Could not open image: %s\n", imgStatusMessage(status)); 85 return 1; 86 } 87 88 printf( 89 "Detected %s\n" 90 "Size: %ux%u\n" 91 "Channel count: %u\n", 92 imgFormatName(img.format), 93 img.width, img.height, 94 img.channelCount); 95 96 ImgSz size = (ImgSz)img.width * img.height * img.channelCount; 97 ImgU8 *pixels = (ImgU8*)malloc(size); 98 status = imgRead(&img, pixels, size); 99 if(status != ImgOK) { 100 printf("Could not decode image: %s\n", imgStatusMessage(status)); 101 /* return 1; */ 102 } 103 104 if(img.channelCount == 3) { 105 saveToPPM_RGB(&img, pixels, argv[2]); 106 } else if(img.channelCount == 4) { 107 saveToPPM_RGBA(&img, pixels, argv[2]); 108 } else { 109 printf("Image must have 3 or 4 channels. Not converting.\n"); 110 } 111 112 status = imgClose(&img); 113 if(status != ImgOK) { 114 printf("Could not close image: %s\n", imgStatusMessage(status)); 115 return 1; 116 } 117 118 return 0; 119}