A very small library for reading image files
1#include "img.h"
2#include <stdio.h>
3#include <string.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
32int main(int argc, char **argv)
33{
34 if(argc < 2) {
35 printf("Usage: %s <file>\n", argv[0]);
36 return 1;
37 }
38
39 int dumpColorMap = 0;
40 for(int i = 2; i < argc; ++i) {
41 /* BMP Color Table, TGA Color Map */
42 if(strcmp(argv[i], "-colorMap") == 0
43 || strcmp(argv[i], "-colorTable") == 0) {
44 dumpColorMap = 1;
45 }
46 }
47
48 FILE *file = fopen(argv[1], "rb");
49 if(file == NULL) {
50 perror("Could not open file");
51 return 1;
52 }
53
54 struct Ctx ctx;
55 ctx.file = file;
56 ImgFuncs funcs;
57 funcs.user = &ctx;
58 funcs.read = &ctxRead;
59 funcs.seek = &ctxSeek;
60 funcs.close = &ctxClose;
61
62 Img img;
63 ImgStatus status = imgOpen(&img, &funcs);
64 if(status != ImgOK) {
65 printf("Could not open image: %s\n", imgStatusMessage(status));
66 return 1;
67 }
68
69 printf(
70 "Detected %s\n"
71 "Size: %ux%u\n"
72 "Channel count: %u\n",
73 imgFormatName(img.format),
74 img.width, img.height,
75 img.channelCount);
76
77 switch(img.format) {
78 case ImgFormatQoi:
79 printf("Color space: %s\n",
80 img.qoi.colorSpace == 0 ? "sRGB" : "Linear");
81 break;
82 case ImgFormatPbm:
83 printf(
84 "Variant: %c\n"
85 "Max. value: %u\n",
86 img.pbm.variant,
87 img.pbm.max);
88 break;
89 case ImgFormatBmp:
90 printf(
91 "Bitmap offset: %08X\n"
92 "Header size: %u\n"
93 "Bit count: %u\n"
94 "Compression: %u\n"
95 "Image size: %u\n"
96 "X pixels per meter: %d\n"
97 "Y pixels per meter: %d\n"
98 "Color table size: %u\n",
99 img.bmp.bitmapOffset,
100 img.bmp.headerSize,
101 img.bmp.bitCount,
102 img.bmp.compression,
103 img.bmp.imageSize,
104 img.bmp.xPPM,
105 img.bmp.yPPM,
106 img.bmp.colorTableSize);
107 if(dumpColorMap && img.bmp.colorTableSize) {
108 printf(" Color table:\n");
109 for(int i = 0; i < img.bmp.colorTableSize; ++i) {
110 const struct ImgBmpRGBQuad *color = &img.bmp.colorTable[i];
111 printf(" %u,%u,%u,%u\n",
112 color->red, color->green, color->blue, color->reserved);
113 }
114 }
115 break;
116 case ImgFormatTga:
117 printf(
118 "ID: %s\n"
119 "Color map type: %u\n"
120 "Image type: %u\n"
121 "Color map first index: %u\n"
122 "Color map length: %u\n"
123 "Color map entry size: %u\n"
124 "Origin X: %u\n"
125 "Origin Y: %u\n"
126 "Pixel Depth: %u\n"
127 "Image Origin: %u\n"
128 "Alpha Bits: %u\n",
129 img.tga.id,
130 img.tga.colorMapType,
131 img.tga.imageType,
132 img.tga.colorMapFirstIndex,
133 img.tga.colorMapLength,
134 img.tga.colorMapEntrySize,
135 img.tga.originX,
136 img.tga.originY,
137 img.tga.pixelDepth,
138 img.tga.imageOrigin,
139 img.tga.alphaBits);
140 if(dumpColorMap && img.tga.colorMapType) {
141 printf(" Color map:\n");
142 for(int i = 0; i < img.tga.colorMapLength; ++i) {
143 const struct ImgTgaColor *color = &img.tga.colorMap[i];
144 printf(" %u,%u,%u,%u\n",
145 color->red, color->green, color->blue, color->alpha);
146 }
147 }
148 break;
149 case ImgFormatGif:
150 printf(
151 "Global Color Table Flag: %u\n"
152 "Color Resolution: %u\n"
153 "Sort Flag: %u\n"
154 "Global Color Table Size: %u\n"
155 "Background Color Index: %u\n"
156 "Pixel Aspect Ratio: %u\n",
157 img.gif.globalColorTableFlag,
158 img.gif.colorResolution,
159 img.gif.sortFlag,
160 img.gif.globalColorTableSize,
161 img.gif.backgroundColorIndex,
162 img.gif.pixelAspectRatio);
163 if(dumpColorMap && img.gif.globalColorTableFlag) {
164 printf(" Global Color Table:\n");
165 for(int i = 0; i < img.gif.globalColorTableSize; ++i) {
166 const struct ImgGifColor *color = &img.gif.globalColorTable[i];
167 printf(" %u,%u,%u\n",
168 color->red, color->green, color->blue);
169 }
170 }
171 break;
172 default:
173 break;
174 }
175
176 status = imgClose(&img);
177 if(status != ImgOK) {
178 printf("Could not close image: %s\n", imgStatusMessage(status));
179 return 1;
180 }
181
182 return 0;
183}