/* 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;
}