17 #define ERROR_IF(cond, message) if (cond) { printf(message); return -1; }; 18 #define MAX_FILENAME_LENGTH 255 29 int main(
int argc,
char * argv[]) {
30 ERROR_IF(argc != 2,
"Usage: inliner source.png");
31 const char * inputPath = argv[1];
33 FILE * inputFile = fopen(inputPath,
"rb");
34 ERROR_IF(inputFile ==
NULL,
"Error: could not open input file.");
36 unsigned char magic[8];
37 fread(magic, 1, 8, inputFile);
38 ERROR_IF(png_sig_cmp(magic, 0, 8),
"Error: Input file is not a PNG file");
40 png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING,
NULL,
NULL,
NULL);
43 png_infop info = png_create_info_struct(png);
46 png_init_io(png, inputFile);
47 png_set_sig_bytes(png, 8);
49 png_read_info(png, info);
51 png_uint_32 width = png_get_image_width(png, info);
52 png_uint_32 height = png_get_image_height(png, info);
53 png_byte colorType = png_get_color_type(png, info);
54 png_byte bitDepth = png_get_bit_depth(png, info);
56 ERROR_IF(colorType != PNG_COLOR_TYPE_RGB_ALPHA,
"Error: Inliner only handles RGBA PNG images.");
57 ERROR_IF(bitDepth != 8,
"Error: Inliner only handles RGBA8888 PNG images.");
59 png_bytep * rowPointers = (png_bytep *)
malloc(
sizeof(png_bytep)*height);
60 for (
int i=0; i<height; i++) {
61 rowPointers[i] = (png_byte *)
malloc(png_get_rowbytes(png, info));
63 png_read_image(png, rowPointers);
68 const char * inputFileName = inputPath;
70 for (
const char * currentChar=inputPath; *currentChar != 0; currentChar++) {
71 if (*currentChar ==
'/') {
72 inputFileName = currentChar+1;
81 size_t pathLength =
strlen(inputPath);
82 strcpy(headerPath, inputPath);
84 headerPath[pathLength-3] =
'h';
85 headerPath[pathLength-2] = 0;
88 strcpy(implementationPath, inputPath);
90 implementationPath[pathLength-3] =
'c';
91 implementationPath[pathLength-2] =
'p';
92 implementationPath[pathLength-1] =
'p';
94 FILE * header = fopen(headerPath,
"w");
98 FILE * implementation = fopen(implementationPath,
"w");
100 fclose(implementation);
106 for (
int i=0; i<maxLength; i++) {
107 snakeCaseName[i] = fileName[i];
108 if (fileName[i] ==
'.') {
109 snakeCaseName[i] = 0;
113 snakeCaseName[maxLength-1] = 0;
117 for (
int i=0; i<maxLength; i++) {
118 upperSnakeCaseName[i] = toupper(snakeCaseName[i]);
124 for (
int i=0; i<maxLength; i++) {
125 char nextLetter = snakeCaseName[i];
126 if (nextLetter ==
'_') {
129 if (i==0 || snakeCaseName[i-1] ==
'_') {
130 nextLetter = upperSnakeCaseName[i];
132 camelCaseName[j++] = nextLetter;
134 camelCaseName[j] = 0;
138 fprintf(file,
"// This file is auto-generated by Inliner. Do not edit manually.\n");
139 fprintf(file,
"#ifndef IMAGE_STORE_%s_H\n", guardian);
140 fprintf(file,
"#define IMAGE_STORE_%s_H\n\n", guardian);
141 fprintf(file,
"#include <escher/image.h>\n\n");
142 fprintf(file,
"namespace ImageStore {\n\n");
143 fprintf(file,
"extern const Image * %s;\n\n", variable);
144 fprintf(file,
"};\n\n");
145 fprintf(file,
"#endif\n");
149 fprintf(file,
"// This file is auto-generated by Inliner. Do not edit manually.\n");
150 fprintf(file,
"#include \"%s.h\"\n\n", header);
151 fprintf(file,
"#define P(c) KDColor::RGB24(c)\n\n");
152 fprintf(file,
"const KDColor pixels[] = {");
153 for (
int j=0; j<height; j++) {
154 png_bytep pixelRow = pixelsRowPointers[j];
155 for (
int i=0; i<width; i++) {
156 if ((i+j*width) % 6 == 0) {
157 fprintf(file,
"\n ");
161 png_bytep pixel = &(pixelRow[i*4]);
162 double red = pixel[0]/255.0;
163 double green = pixel[1]/255.0;
164 double blue = pixel[2]/255.0;
165 double alpha = pixel[3]/255.0;
167 double blendedRed = red*alpha + 1.0*(1.0-alpha);
168 double blendedGreen = green*alpha + 1.0*(1.0-alpha);
169 double blendedBlue = blue*alpha + 1.0*(1.0-alpha);
170 fprintf(file,
"P(0x%02X%02X%02X)", (
int)(blendedRed*0xFF), (
int)(blendedGreen*0xFF), (
int)(blendedBlue*0xFF));
171 if (i!=width-1 || j!= height-1) {
176 fprintf(file,
"\n};\n\n");
177 fprintf(file,
"constexpr Image image = Image(%d, %d, pixels);\n\n", width, height);
178 fprintf(file,
"const Image * ImageStore::%s = ℑ\n", variable);
#define ERROR_IF(cond, message)
void generateHeaderFromImage(FILE *file, const char *guardian, const char *variable)
int main(int argc, char *argv[])
void camelCaseNameFromSnakeCaseNames(const char *snakeCaseName, const char *upperSnakeCaseName, char *camelCaseName, size_t maxLength)
size_t strlen(const char *s)
void * malloc(size_t size)
#define MAX_FILENAME_LENGTH
void generateImplementationFromImage(FILE *file, const char *header, const char *variable, uint32_t width, uint32_t height, png_bytep *pixelsRowPointers)
void fileNameToSnakeCaseName(const char *fileName, char *snakeCaseName, size_t maxLength)
void snakeCaseNameToUpperSnakeName(const char *snakeCaseName, char *upperSnakeCaseName, size_t maxLength)