MLX42 1.0
MLX42
Loading...
Searching...
No Matches
mlx_xpm42.c File Reference
#include "MLX42/MLX42_Int.h"
Include dependency graph for mlx_xpm42.c:

Go to the source code of this file.

Functions

static uint8_t mlx_parse_hex_channel (char *channel)
 
static bool mlx_insert_xpm_entry (xpm_t *xpm, char *line, uint32_t *ctable, size_t s)
 
static bool mlx_read_data (xpm_t *xpm, FILE *file, uint32_t *ctable, size_t s)
 
static bool mlx_read_table (xpm_t *xpm, FILE *file)
 
static bool mlx_read_xpm_header (xpm_t *xpm, FILE *file)
 
xpm_tmlx_load_xpm42 (const char *path)
 
void mlx_delete_xpm42 (xpm_t *xpm)
 

Function Documentation

◆ mlx_delete_xpm42()

void mlx_delete_xpm42 ( xpm_t xpm)

Deletes an XPM42 texture by freeing its allocated data.

This will not remove any already drawn XPMs, it simply deletes the XPM buffer.

Parameters
[in]xpmThe xpm texture to delete.

Definition at line 203 of file mlx_xpm42.c.

204{
207 free(xpm);
208}
#define MLX_NONNULL(var)
Definition MLX42_Int.h:46
GLuint GLsizei GLsizei * length
Definition glad.h:3372
uint8_t * pixels
Definition MLX42.h:268
Definition MLX42.h:280
mlx_texture_t texture
Definition MLX42.h:281

◆ mlx_insert_xpm_entry()

static bool mlx_insert_xpm_entry ( xpm_t xpm,
char line,
uint32_t ctable,
size_t  s 
)
static

Parses the XPM color value entry e.g: ".X #00FF00FF" into the color table while also verifying the format.

Parameters
xpmThe XPM.
lineThe line to parse.
ctableThe color hash table.
sSize of the hash table
Returns
True or false depending on if it successfully parsed the line.

Definition at line 64 of file mlx_xpm42.c.

65{
66 // NOTE: uintptr because windows likes to complain...
67 // Verify the length of the Pixel string by checking backwards for the first
68 // occurrence of a space and then check the distance by comparing with cpp.
69 if (((uintptr_t)strrchr(line, ' ') - (uintptr_t)line) != (uint64_t)xpm->cpp)
70 return (false);
71 if (!isspace(line[xpm->cpp]) || line[xpm->cpp + 1] != '#' || !isalnum(line[xpm->cpp + 2]))
72 return (false);
73
74 uint32_t color = 0;
75 size_t start_offset = xpm->cpp + 2;
80
83 return (true);
84}
uint64_t mlx_fnv_hash(char *str, size_t len)
Definition mlx_utils.c:68
uint32_t mlx_rgba_to_mono(uint32_t color)
Definition mlx_utils.c:109
GLuint index
Definition glad.h:3345
GLuint color
Definition glad.h:3749
GLdouble s
Definition glad.h:3009
static uint8_t mlx_parse_hex_channel(char *channel)
Definition mlx_xpm42.c:48
char mode
Definition MLX42.h:284
int32_t cpp
Definition MLX42.h:283
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mlx_load_xpm42()

xpm_t * mlx_load_xpm42 ( const char path)

Loads an XPM42 texture from the given file path.

Parameters
[in]pathThe file path to the XPM texture.
Returns
The XPM texture struct containing its information.

Definition at line 181 of file mlx_xpm42.c.

182{
183 FILE* file;
184 xpm_t* xpm = NULL;
185
187 if (!strstr(path, ".xpm42"))
188 return ((void*)mlx_error(MLX_INVEXT));
189 if (!(file = fopen(path, "r")))
190 return ((void*)mlx_error(MLX_INVFILE));
191 if (!(xpm = calloc(1, sizeof(xpm_t))))
192 return ((void*)mlx_error(MLX_MEMFAIL));
194 {
197 xpm = NULL;
198 }
199 fclose(file);
200 return (xpm);
201}
@ MLX_MEMFAIL
Definition MLX42.h:383
@ MLX_INVEXT
Definition MLX42.h:373
@ MLX_INVFILE
Definition MLX42.h:374
@ MLX_INVXPM
Definition MLX42.h:376
bool mlx_error(mlx_errno_t val)
Definition mlx_error.c:43
bool mlx_freen(int32_t count,...)
Definition mlx_utils.c:89
static bool mlx_read_xpm_header(xpm_t *xpm, FILE *file)
Definition mlx_xpm42.c:156
Here is the call graph for this function:

◆ mlx_parse_hex_channel()

static uint8_t mlx_parse_hex_channel ( char channel)
static

XPM is an obscure image format which can't seem to make up its mind whether it wants to be written in C code or not.

https://en.wikipedia.org/wiki/X_PixMap

This might anger some but instead I decided to write my own image format, very similar to XPM2, which seems to be the better option between the 3 versions. The only difference is in the header which carries the file type, width, height, color count and finally color type aka 'c' for RGBA8 or 'm' for monochrome output.

The changes, in my opinion, very much simplify the XPM format into something literally anybody can use without much guessing as to what does what.

Additionally with the C style format, the idea is that you simply include it directly into the compilation of the program (since it's just C).

As convenient as this is, I just find it hideous especially the XPM3 variant. By sticking to the XPM style format, conversion should be very easy and straightforward to this format however. Parses HEX color channel e.g: "0F"

Parameters
channelThe 2 character string to parse.
Returns
Int value of the channel.

Definition at line 48 of file mlx_xpm42.c.

49{
50 char temp_chan[] = {channel[0], channel[1], '\0'};
51 return (strtol(temp_chan, NULL, 16));
52}
Here is the caller graph for this function:

◆ mlx_read_data()

static bool mlx_read_data ( xpm_t xpm,
FILE file,
uint32_t ctable,
size_t  s 
)
static

Retrieves the pixel data line by line and then processes each pixel by hashing the characters and looking it up from the color table.

Parameters
xpmThe XPM.
fileThe filepath to the XPM42 file.
ctableThe color hash table.
sSize of the hash table.
Returns
True or false depending on if it successfully parsed the line.

Definition at line 96 of file mlx_xpm42.c.

97{
98 size_t line_len;
99 char* line = NULL;
100
101 for (int64_t y_xpm = 0; y_xpm < xpm->texture.height; y_xpm++)
102 {
103 if (!mlx_getline(&line, &line_len, file))
104 return (free(line), false);
105 if (line[line_len - 1] == '\n')
106 line_len--;
107 if (line_len != xpm->texture.width * xpm->cpp)
108 return (free(line), false);
109
110 // NOTE: Copy pixel by pixel as we need to retrieve the hash table.
111 for (int64_t x_xpm = 0, x_line = 0; x_xpm < xpm->texture.width; x_xpm++, x_line += xpm->cpp)
112 {
115 }
116 }
117 free(line);
118 return (true);
119}
void mlx_draw_pixel(uint8_t *pixel, uint32_t color)
#define BPP
Definition MLX42_Int.h:42
bool mlx_getline(char **out, size_t *out_size, FILE *file)
Definition mlx_utils.c:28
uint32_t height
Definition MLX42.h:266
uint32_t width
Definition MLX42.h:265
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mlx_read_table()

static bool mlx_read_table ( xpm_t xpm,
FILE file 
)
static

For quick lookups we basically create a stack allocated lookup table with every ascii character in it. This should help avoid a O(n) case and give us a O(1) for very fast look ups.

Downside is we still need to iterate over each pixel to solve its color. So I hope this makes it at least a bit faster.

TODO: This buffer might be way to big! Do actual collision checks, for now just straight up raw dog this.

Definition at line 132 of file mlx_xpm42.c.

133{
134 char* line = NULL;
135 size_t line_len;
137
138 for (int32_t i = 0; i < xpm->color_count; i++)
139 {
140 if (!mlx_getline(&line, &line_len, file))
141 return (free(line), false);
142 if (!mlx_insert_xpm_entry(xpm, line, ctable, (sizeof(ctable) / BPP)))
143 return (free(line), false);
144 }
145 free(line);
146 return (mlx_read_data(xpm, file, ctable, (sizeof(ctable) / BPP)));
147}
static bool mlx_insert_xpm_entry(xpm_t *xpm, char *line, uint32_t *ctable, size_t s)
Definition mlx_xpm42.c:64
static bool mlx_read_data(xpm_t *xpm, FILE *file, uint32_t *ctable, size_t s)
Definition mlx_xpm42.c:96
int32_t color_count
Definition MLX42.h:282
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mlx_read_xpm_header()

static bool mlx_read_xpm_header ( xpm_t xpm,
FILE file 
)
static

Reads the XPM42 file header which usually consists of a file type declaration of "!XPM42" followed by the next line containing image information such as width, height, unique color count and finally the color mode. Which is either c for Color or m for Monochrome.

Definition at line 156 of file mlx_xpm42.c.

157{
159 char buffer[64] = {0};
160
161 // Check file type dec...
162 if (!fgets(buffer, sizeof(buffer), file))
163 return (false);
164 if (strncmp(buffer, "!XPM42\n", sizeof(buffer)) != 0)
165 return (false);
166
167 // Get header info ...
168 if (!fgets(buffer, sizeof(buffer), file))
169 return (false);
170 flagc = sscanf(buffer, "%i %i %i %i %c\n", &xpm->texture.width, &xpm->texture.height, &xpm->color_count, &xpm->cpp, &xpm->mode);
172 !(xpm->mode == 'c' || xpm->mode == 'm') || xpm->cpp > 10)
173 return (false);
176 return (xpm->texture.pixels != NULL ? mlx_read_table(xpm, file) : false);
177}
GLuint texture
Definition glad.h:2899
GLenum GLfloat * buffer
Definition glad.h:2634
static bool mlx_read_table(xpm_t *xpm, FILE *file)
Definition mlx_xpm42.c:132
uint8_t bytes_per_pixel
Definition MLX42.h:267
Here is the call graph for this function:
Here is the caller graph for this function: