@@ -77,7 +77,8 @@ static dt_imageio_retval_t _read_pgm(dt_image_t *img, FILE*f, float *buf)
7777 dt_imageio_retval_t result = DT_IMAGEIO_OK ;
7878
7979 unsigned int max ;
80- // We expect at most a 5-digit number (65535) + a newline + '\0', so 7 characters.
80+ // We expect at most a 5-digit number (65535) + a newline + '\0',
81+ // so 7 characters.
8182 char maxvalue_string [7 ];
8283 if (fgets (maxvalue_string ,7 ,f ))
8384 max = atoi (maxvalue_string );
@@ -122,6 +123,9 @@ static dt_imageio_retval_t _read_pgm(dt_image_t *img, FILE*f, float *buf)
122123 for (size_t x = 0 ; x < img -> width ; x ++ )
123124 {
124125 uint16_t intvalue = line [x ];
126+ // PGM files are big endian, the most significant byte is first
127+ // in the case where the value must be represented by two bytes.
128+ // See http://netpbm.sourceforge.net/doc/pgm.html
125129 if (G_BYTE_ORDER != G_BIG_ENDIAN )
126130 intvalue = GUINT16_SWAP_LE_BE (intvalue );
127131 float value = (float )intvalue / (float )max ;
@@ -142,7 +146,8 @@ static dt_imageio_retval_t _read_ppm(dt_image_t *img, FILE*f, float *buf)
142146 dt_imageio_retval_t result = DT_IMAGEIO_OK ;
143147
144148 unsigned int max ;
145- // We expect at most a 5-digit number (65535) + a newline + '\0', so 7 characters.
149+ // We expect at most a 5-digit number (65535) + a newline + '\0',
150+ // so 7 characters.
146151 char maxvalue_string [7 ];
147152 if (fgets (maxvalue_string ,7 ,f ))
148153 max = atoi (maxvalue_string );
@@ -191,7 +196,9 @@ static dt_imageio_retval_t _read_ppm(dt_image_t *img, FILE*f, float *buf)
191196 for (int c = 0 ; c < 3 ; c ++ )
192197 {
193198 uint16_t intvalue = line [x * 3 + c ];
194- // PPM files are big endian! http://netpbm.sourceforge.net/doc/ppm.html
199+ // PPM files are big endian, the most significant byte is first
200+ // in the case where the value must be represented by two bytes.
201+ // See http://netpbm.sourceforge.net/doc/ppm.html
195202 if (G_BYTE_ORDER != G_BIG_ENDIAN )
196203 intvalue = GUINT16_SWAP_LE_BE (intvalue );
197204 float value = (float )intvalue / (float )max ;
@@ -206,50 +213,60 @@ static dt_imageio_retval_t _read_ppm(dt_image_t *img, FILE*f, float *buf)
206213 return result ;
207214}
208215
209- dt_imageio_retval_t dt_imageio_open_pnm (dt_image_t * img , const char * filename , dt_mipmap_buffer_t * mbuf )
216+ dt_imageio_retval_t dt_imageio_open_pnm (dt_image_t * img ,
217+ const char * filename ,
218+ dt_mipmap_buffer_t * mbuf )
210219{
211- const char * ext = filename + strlen (filename );
212- while (* ext != '.' && ext > filename ) ext -- ;
213- if (strcasecmp (ext , ".pbm" ) && strcasecmp (ext , ".pgm" ) && strcasecmp (ext , ".pnm" ) && strcasecmp (ext , ".ppm" ))
214- return DT_IMAGEIO_UNSUPPORTED_FORMAT ;
215220 FILE * f = g_fopen (filename , "rb" );
216221 if (!f ) return DT_IMAGEIO_FILE_NOT_FOUND ;
217222 int ret = 0 ;
218223 dt_imageio_retval_t result = DT_IMAGEIO_LOAD_FAILED ;
219224
220225 char head [2 ] = { 'X' , 'X' };
221226 ret = fscanf (f , "%c%c " , head , head + 1 );
222- if (ret != 2 || head [0 ] != 'P' ) goto end ;
227+ if (ret != 2 || head [0 ] != 'P' )
228+ {
229+ fclose (f );
230+ return DT_IMAGEIO_LOAD_FAILED ;
231+ }
223232
224233 char width_string [10 ] = { 0 };
225234 char height_string [10 ] = { 0 };
226235 ret = fscanf (f , "%9s %9s " , width_string , height_string );
227- if (ret != 2 ) goto end ;
236+ if (ret != 2 )
237+ {
238+ fclose (f );
239+ return DT_IMAGEIO_FILE_CORRUPTED ;
240+ }
228241
229242 errno = 0 ;
230243 img -> width = strtol (width_string , NULL , 0 );
231244 img -> height = strtol (height_string , NULL , 0 );
232- if (errno != 0 || img -> width <= 0 || img -> height <= 0 ) goto end ;
245+ if (errno != 0 || img -> width <= 0 || img -> height <= 0 )
246+ {
247+ fclose (f );
248+ return DT_IMAGEIO_FILE_CORRUPTED ;
249+ }
233250
234251 img -> buf_dsc .channels = 4 ;
235252 img -> buf_dsc .datatype = TYPE_FLOAT ;
236253
237254 float * buf = (float * )dt_mipmap_cache_alloc (mbuf , img );
238255 if (!buf )
239256 {
240- result = DT_IMAGEIO_CACHE_FULL ;
241- goto end ;
257+ fclose ( f ) ;
258+ return DT_IMAGEIO_CACHE_FULL ;
242259 }
243260
244- // we don't support ASCII variants or P7 anymaps! thanks to magic numbers those shouldn't reach us anyway.
261+ // We don't support ASCII variants or P7 anymaps!
262+ // Thanks to magic numbers those shouldn't reach us anyway.
245263 if (head [1 ] == '4' )
246264 result = _read_pbm (img , f , buf );
247265 else if (head [1 ] == '5' )
248266 result = _read_pgm (img , f , buf );
249267 else if (head [1 ] == '6' )
250268 result = _read_ppm (img , f , buf );
251269
252- end :
253270 fclose (f );
254271
255272 if (result == DT_IMAGEIO_OK )
@@ -259,6 +276,12 @@ dt_imageio_retval_t dt_imageio_open_pnm(dt_image_t *img, const char *filename, d
259276 img -> flags &= ~DT_IMAGE_RAW ;
260277 img -> flags &= ~DT_IMAGE_S_RAW ;
261278 img -> flags &= ~DT_IMAGE_HDR ;
279+
280+ // The most common and generally assumed interpretation of the
281+ // image data in PNM seems to be that the values are non-linear.
282+ // This is why we set the so called 'LDR' flag, which essentially,
283+ // in the absence of metadata, signals darktable the need to treat
284+ // the image data as non-linear.
262285 img -> flags |= DT_IMAGE_LDR ;
263286 img -> loader = LOADER_PNM ;
264287 }
0 commit comments