Skip to content

Instantly share code, notes, and snippets.

@NathaanTFM
Last active September 21, 2023 10:46
Show Gist options
  • Save NathaanTFM/f2bd7a7e74cf2427a36bfaffdc94d0cd to your computer and use it in GitHub Desktop.
Save NathaanTFM/f2bd7a7e74cf2427a36bfaffdc94d0cd to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "lodepng.h"
#define IS_BLANK(ch) ((ch) == '\n' || (ch) == '\t' || (ch) == '\r' || (ch) == ' ' || (ch) == 0x7F)
static void ppmSkipLine(char **cur) {
for (;;) {
char ch = **cur;
(*cur)++;
if (ch == 0) {
(*cur)--;
break;
} else if (ch == '\n') {
break;
}
}
}
// read a number
static int ppmReadNumber(char **cur, unsigned int *res) {
unsigned int value = 0;
for (;;) {
//int ch = fgetc(fp);
char ch = **cur;
(*cur)++;
if (IS_BLANK(ch)) {
// skip blank characters
continue;
} else if (ch == '#') {
// skip the comment
ppmSkipLine(cur);
continue;
} else if (ch >= '0' && ch <= '9') {
// found a number,
value = ch - '0';
break;
} else if (ch == 0) {
// EOF
(*cur)--;
} else {
// found another character, it's invalid or EOF
return 0;
}
}
// read the number
for (;;) {
//int ch = fgetc(fp);
char ch = **cur;
(*cur)++;
if (ch >= '0' && ch <= '9') {
value = (value * 10) + (ch - '0');
} else if (IS_BLANK(ch)) {
break; // success
} else if (ch == 0 || ch == '#') {
(*cur)--;
break; // success
} else {
// any other character is invalid or EOF
return 0;
}
}
*res = value;
return 1;
}
#define READ_NUMBER(name) do { if (!ppmReadNumber(&cur, &(name))) { fprintf(stderr, "Failed to read " #name "\n"); return 1; } } while (0)
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
return 1;
}
FILE *fp = fopen(argv[1], "rb");
if (!fp) {
fprintf(stderr, "Failed to open %s\n", argv[1]);
return 1;
}
// trying to buf everything
fseek(fp, 0, SEEK_END);
unsigned long size = ftell(fp);
fseek(fp, 0, SEEK_SET);
char *data = (char*)malloc(size+1);
fread(data, 1, size, fp);
data[size] = 0; // EOF
char *cur = data;
//fread(buf, 1, 2, fp);
if (cur[0] != 'P' && cur[1] != '3') {
fprintf(stderr, "File is not a PPM file\n");
return 1;
}
cur += 2;
unsigned int width, height;
READ_NUMBER(width);
READ_NUMBER(height);
unsigned int maxval;
READ_NUMBER(maxval);
printf("Dimensions: %ux%u\n", width, height);
unsigned char *image = (unsigned char*)malloc(width * height * 3);
unsigned char *curimg = image;
for (unsigned int x = 0; x < width; x++) {
for (unsigned int y = 0; y < height; y++) {
unsigned int red, green, blue;
READ_NUMBER(red);
READ_NUMBER(green);
READ_NUMBER(blue);
// do the division thingy
red = (unsigned int)round(((double)red / (double)maxval) * 255.0);
green = (unsigned int)round(((double)green / (double)maxval) * 255.0);
blue = (unsigned int)round(((double)blue / (double)maxval) * 255.0);
*curimg++ = red;
*curimg++ = green;
*curimg++ = blue;
}
}
printf("Encoding PNG...\n");
int length = strlen(argv[1]);
char *target = (char*)malloc(length + 5);
memcpy(target, argv[1], length+1);
// get filename for target
// if filename ends with ".ppm", replace with ".png"
if (strcmp(target + length - 4, ".ppm") == 0) {
memcpy(target + length - 4, ".png", 4);
} else {
// otherwise, just append png
memcpy(target + length, ".png", 5); // include null terminator
}
unsigned error = lodepng_encode24_file(target, image, width, height);
/*if there's an error, display it*/
if(error) printf("error %u: %s\n", error, lodepng_error_text(error));
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment