/* Calcite, src/user-libs/silver/pam.c * Copyright 2025 Benji Dial * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include #include static int starts_with(const char *big_string, const char *little_string) { while (*little_string) { if (*big_string != *little_string) return 0; ++big_string; ++little_string; } return 1; } static int strequ(const char *str1, const char *str2) { while (1) { if (!*str1 && !*str2) return 1; if (*str1 != *str2) return 0; ++str1; ++str2; } } static int parse_uint(const char *str) { int i = 0; while (*str) i = i * 10 + *(str++) - '0'; return i; } enum pam_tupltype { PTT_RGB_ALPHA }; #define MAX_LINE_LENGTH 1023 int load_pam(const char *path, struct image **image_out) { struct file_stream *stream; if (open_file_stream(path, &stream) != FAR_SUCCESS) return 0; if (read_file_stream_byte(stream) != 'P' || read_file_stream_byte(stream) != '7' || read_file_stream_byte(stream) != '\n') { close_file_stream(stream); return 0; } int width = -1, height = -1, depth = -1, maxval = -1, tupltype = -1; while (1) { char line[MAX_LINE_LENGTH + 1]; int line_length = 0; while (1) { int c = read_file_stream_byte(stream); if (c == -1) { close_file_stream(stream); return 0; } if (c == '\n') { line[line_length] = 0; break; } if (line_length == MAX_LINE_LENGTH) { close_file_stream(stream); return 0; } line[line_length++] = c; } if (line[0] == '#') continue; if (starts_with(line, "WIDTH ")) width = parse_uint(&line[6]); else if (starts_with(line, "HEIGHT ")) height = parse_uint(&line[7]); else if (starts_with(line, "DEPTH ")) depth = parse_uint(&line[6]); else if (starts_with(line, "MAXVAL ")) maxval = parse_uint(&line[7]); else if (strequ(line, "TUPLTYPE RGB_ALPHA")) tupltype = PTT_RGB_ALPHA; else if (strequ(line, "ENDHDR")) break; } if (width == -1 || height == -1 || depth != 4 || maxval != 255 || tupltype != PTT_RGB_ALPHA) { close_file_stream(stream); return 0; } create_image(width, height, image_out); if (read_file_stream( stream, (*image_out)->pixels, width * height * 4) != FAR_SUCCESS) { close_file_stream(stream); destroy_image(*image_out); return 0; } close_file_stream(stream); return 1; }