@@ -131,87 +131,96 @@ static int stbi_eof_cb (void *user)
131131/*
132132============
133133Image_LoadImage
134+ of an image filename 'name' (with no extension)
134135either returns a pointer to Mem_Alloc allocated RGBA data
135136or returns NULL if not loaded, either because not found OR if name
136137is ignored because from a gamedir with lower priority than min_path_id.
137138Use min_path_id = 0 if gamedir priority is N/A.
138139Search 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