Skip to content

Commit 18f73fe

Browse files
committed
Image_LoadImage: load the highest path_id image first, then the best format second (png, tga, jpg, pcx, lmp)
1 parent 8fed52d commit 18f73fe

2 files changed

Lines changed: 65 additions & 56 deletions

File tree

Quake/gl_draw.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ qpic_t *Draw_TryCachePic (const char *path, unsigned int texflags)
307307
//
308308
enum srcformat pic_fmt = SRC_INDEXED;
309309

310-
// Image_LoadImage works without file extension.
310+
// Image_LoadImage works without file extensions.
311311
char npath[MAX_QPATH];
312312
COM_StripExtension (path, npath, sizeof (npath));
313313

Quake/image.c

Lines changed: 64 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -131,87 +131,96 @@ static int stbi_eof_cb (void *user)
131131
/*
132132
============
133133
Image_LoadImage
134+
of an image filename 'name' (with no extension)
134135
either returns a pointer to Mem_Alloc allocated RGBA data
135136
or returns NULL if not loaded, either because not found OR if name
136137
is ignored because from a gamedir with lower priority than min_path_id.
137138
Use min_path_id = 0 if gamedir priority is N/A.
138139
Search order: png tga jpg pcx lmp
139-
Note : makes a thread-safe copy of 'name' so ve can use va() as inuput.
140+
Note : makes a thread-safe copy of 'name' so we can use va() as inuput.
140141
============
141142
*/
142-
byte *Image_LoadImage (const char *name, int *width, int *height, enum srcformat *fmt, unsigned int min_path_id)
143+
// image formats supported, ordered by priority
144+
typedef enum
143145
{
144-
static const char *const stbi_formats[] = {"png", "tga", "jpg", NULL};
145-
146-
char loadfilename[MAX_OSPATH];
146+
STB_IMAGE_LOADER,
147+
PCX_LOADER,
148+
LMP_LOADER
149+
} image_loader_t;
147150

148-
int file_handle = -1;
149-
int i;
151+
static struct
152+
{
153+
const char *file_extension;
154+
image_loader_t loader;
155+
} supported_image_formats[] = {{"png", STB_IMAGE_LOADER}, {"tga", STB_IMAGE_LOADER}, {"jpg", STB_IMAGE_LOADER}, {"pcx", PCX_LOADER}, {"lmp", LMP_LOADER}};
150156

151-
unsigned int opened_file_path_id = 0;
157+
const int num_supported_image_formats = countof (supported_image_formats);
152158

153-
for (i = 0; stbi_formats[i]; i++)
159+
byte *Image_LoadImage (const char *name, int *width, int *height, enum srcformat *fmt, unsigned int min_path_id)
160+
{
161+
// 1. Search 'name' image by supported_image_formats, keeping only the best, as:
162+
// a) The highest path_id wins,
163+
// b) For equivalent path_id, Highest supported_image_formats[] priority wins. (smallest index)
164+
int best_path_id = -1;
165+
unsigned int path_id = 0;
166+
int best_image_kind_index = -1;
167+
char loadfilename[MAX_OSPATH];
168+
int file_handle = -1;
169+
170+
for (int image_kind_index = 0; image_kind_index < num_supported_image_formats; image_kind_index++)
154171
{
155-
q_snprintf (loadfilename, sizeof (loadfilename), "%s.%s", name, stbi_formats[i]);
156-
COM_OpenFile (loadfilename, &file_handle, &opened_file_path_id);
172+
q_snprintf (loadfilename, sizeof (loadfilename), "%s.%s", name, supported_image_formats[image_kind_index].file_extension);
157173

158-
if (file_handle >= 0)
174+
if (COM_FileExists (loadfilename, &path_id))
159175
{
160-
if (opened_file_path_id >= min_path_id)
176+
if ((int)path_id > best_path_id)
161177
{
162-
stbi_io_callbacks sys_file_cb = {.read = stbi_read_cb, .eof = stbi_eof_cb, .skip = stbi_skip_cb};
163-
164-
// data is managed by our Mem_Alloc routines, nothing more to do.
165-
byte *data = stbi_load_from_callbacks (&sys_file_cb, (void *)&file_handle, width, height, NULL, 4);
166-
167-
if (data)
168-
{
169-
*fmt = SRC_RGBA;
170-
}
171-
else
172-
Con_Warning ("couldn't load %s (%s)\n", loadfilename, stbi_failure_reason ());
173-
174-
COM_CloseFile (file_handle);
175-
return data;
176-
}
177-
else
178-
{
179-
Con_DPrintf ("Image_LoadImage: ignored %s from a gamedir with lower priority\n", loadfilename);
180-
COM_CloseFile (file_handle);
178+
best_path_id = (int)path_id;
179+
best_image_kind_index = image_kind_index;
181180
}
182181
}
183182
}
184183

185-
q_snprintf (loadfilename, sizeof (loadfilename), "%s.pcx", name);
186-
COM_OpenFile (loadfilename, &file_handle, &opened_file_path_id);
187-
if (file_handle >= 0)
184+
// at that point, best_image_kind_index points on the highest path_id image,
185+
// or in case of path_id equality, the best format in terms of priority.
186+
// min_path_id is the final barrier of entry:
187+
// if no file was found, this is also used to bail out. (best_path_id = -1 < min_path_id ( = 0))
188+
if (best_path_id < (int)min_path_id)
189+
return NULL;
190+
191+
// 2. Load image matching supported_image_formats[best_image_kind_index].file_extension
192+
q_snprintf (loadfilename, sizeof (loadfilename), "%s.%s", name, supported_image_formats[best_image_kind_index].file_extension);
193+
194+
COM_OpenFile (loadfilename, &file_handle, NULL);
195+
196+
assert (file_handle >= 0);
197+
198+
if (supported_image_formats[best_image_kind_index].loader == STB_IMAGE_LOADER)
188199
{
189-
if (opened_file_path_id >= min_path_id)
200+
stbi_io_callbacks sys_file_cb = {.read = stbi_read_cb, .eof = stbi_eof_cb, .skip = stbi_skip_cb};
201+
202+
// data is managed by our Mem_Alloc routines, nothing more to do.
203+
byte *data = stbi_load_from_callbacks (&sys_file_cb, (void *)&file_handle, width, height, NULL, 4);
204+
205+
if (data)
190206
{
191207
*fmt = SRC_RGBA;
192-
return Image_LoadPCX (file_handle, width, height, loadfilename);
193208
}
194209
else
195-
{
196-
Con_DPrintf ("Image_LoadImage: ignored %s from a gamedir with lower priority\n", loadfilename);
197-
COM_CloseFile (file_handle);
198-
}
199-
}
210+
Con_Warning ("couldn't load %s (%s)\n", loadfilename, stbi_failure_reason ());
200211

201-
q_snprintf (loadfilename, sizeof (loadfilename), "%s%s.lmp", "", name);
202-
COM_OpenFile (loadfilename, &file_handle, &opened_file_path_id);
203-
if (file_handle >= 0)
212+
COM_CloseFile (file_handle);
213+
return data;
214+
}
215+
else if (supported_image_formats[best_image_kind_index].loader == PCX_LOADER)
204216
{
205-
if (opened_file_path_id >= min_path_id)
206-
{
207-
*fmt = SRC_INDEXED;
208-
return Image_LoadLMP (file_handle, width, height, loadfilename);
209-
}
210-
else
211-
{
212-
Con_DPrintf ("Image_LoadImage: ignored %s from a gamedir with lower priority\n", loadfilename);
213-
COM_CloseFile (file_handle);
214-
}
217+
*fmt = SRC_RGBA;
218+
return Image_LoadPCX (file_handle, width, height, loadfilename);
219+
}
220+
else if (supported_image_formats[best_image_kind_index].loader == LMP_LOADER)
221+
{
222+
*fmt = SRC_INDEXED;
223+
return Image_LoadLMP (file_handle, width, height, loadfilename);
215224
}
216225

217226
return NULL;

0 commit comments

Comments
 (0)