@@ -98,8 +98,6 @@ typedef struct {
9898 JxlBasicInfo basic_info ;
9999 JxlPixelFormat pixel_format ;
100100
101- Py_ssize_t n_frames ;
102-
103101 char * mode ;
104102} JpegXlDecoderObject ;
105103
@@ -166,27 +164,26 @@ _jxl_decoder_rewind(PyObject *self) {
166164 Py_RETURN_NONE ;
167165}
168166
169- bool
170- _jxl_decoder_count_frames (PyObject * self ) {
171- JpegXlDecoderObject * decp = (JpegXlDecoderObject * )self ;
172-
173- decp -> n_frames = 0 ;
167+ PyObject *
168+ _jxl_decoder_get_frames_left (PyObject * self ) {
169+ int frames_left = 0 ;
174170
175171 // count all JXL_DEC_NEED_IMAGE_OUT_BUFFER events
172+ JpegXlDecoderObject * decp = (JpegXlDecoderObject * )self ;
176173 while (decp -> status != JXL_DEC_SUCCESS ) {
177174 decp -> status = JxlDecoderProcessInput (decp -> decoder );
178175
179176 if (decp -> status == JXL_DEC_NEED_IMAGE_OUT_BUFFER ) {
180177 if (JxlDecoderSkipCurrentFrame (decp -> decoder ) != JXL_DEC_SUCCESS ) {
181- return false;
178+ PyErr_SetString (PyExc_OSError , "Error when counting frames" );
179+ break ;
182180 }
183- decp -> n_frames ++ ;
181+ frames_left ++ ;
184182 }
185183 }
184+ JxlDecoderRewind (decp -> decoder );
186185
187- _jxl_decoder_rewind ((PyObject * )decp );
188-
189- return true;
186+ return Py_BuildValue ("i" , frames_left );
190187}
191188
192189PyObject *
@@ -206,7 +203,6 @@ _jxl_decoder_new(PyObject *self, PyObject *args) {
206203 decp -> jxl_exif_len = 0 ;
207204 decp -> jxl_xmp = NULL ;
208205 decp -> jxl_xmp_len = 0 ;
209- decp -> n_frames = 0 ;
210206
211207 // used for printing more detailed error messages
212208 char * jxl_call_name ;
@@ -371,14 +367,6 @@ _jxl_decoder_new(PyObject *self, PyObject *args) {
371367 goto end_with_custom_error ;
372368 }
373369
374- if (decp -> basic_info .have_animation ) {
375- // get frame count by iterating over image out events
376- if (!_jxl_decoder_count_frames ((PyObject * )decp )) {
377- PyErr_SetString (PyExc_OSError , "something went wrong when counting frames" );
378- goto end_with_custom_error ;
379- }
380- }
381-
382370 return (PyObject * )decp ;
383371
384372 // on success we should never reach here
@@ -410,15 +398,14 @@ _jxl_decoder_get_info(PyObject *self) {
410398 JpegXlDecoderObject * decp = (JpegXlDecoderObject * )self ;
411399
412400 return Py_BuildValue (
413- "(II)sOIIII " ,
401+ "(II)sOIII " ,
414402 decp -> basic_info .xsize ,
415403 decp -> basic_info .ysize ,
416404 decp -> mode ,
417405 decp -> basic_info .have_animation ? Py_True : Py_False ,
418406 decp -> basic_info .animation .tps_numerator ,
419407 decp -> basic_info .animation .tps_denominator ,
420- decp -> basic_info .animation .num_loops ,
421- decp -> n_frames
408+ decp -> basic_info .animation .num_loops
422409 );
423410}
424411
@@ -432,6 +419,10 @@ _jxl_decoder_get_next(PyObject *self) {
432419 char * jxl_call_name ;
433420
434421 // process events until next frame output is ready
422+ if (decp -> status == JXL_DEC_FRAME ) {
423+ decp -> status = JxlDecoderGetFrameHeader (decp -> decoder , & fhdr );
424+ _JXL_CHECK ("JxlDecoderGetFrameHeader" );
425+ }
435426 while (decp -> status != JXL_DEC_NEED_IMAGE_OUT_BUFFER ) {
436427 decp -> status = JxlDecoderProcessInput (decp -> decoder );
437428
@@ -444,14 +435,10 @@ _jxl_decoder_get_next(PyObject *self) {
444435 if (decp -> status == JXL_DEC_NEED_MORE_INPUT ) {
445436 _jxl_decoder_set_input ((PyObject * )decp );
446437 _JXL_CHECK ("JxlDecoderSetInput" )
447- continue ;
448- }
449-
450- if (decp -> status == JXL_DEC_FRAME ) {
438+ } else if (decp -> status == JXL_DEC_FRAME ) {
451439 // decode frame header
452440 decp -> status = JxlDecoderGetFrameHeader (decp -> decoder , & fhdr );
453441 _JXL_CHECK ("JxlDecoderGetFrameHeader" );
454- continue ;
455442 }
456443 }
457444
@@ -573,6 +560,10 @@ static struct PyMethodDef _jpegxl_decoder_methods[] = {
573560 {"get_icc" , (PyCFunction )_jxl_decoder_get_icc , METH_NOARGS , "get_icc" },
574561 {"get_exif" , (PyCFunction )_jxl_decoder_get_exif , METH_NOARGS , "get_exif" },
575562 {"get_xmp" , (PyCFunction )_jxl_decoder_get_xmp , METH_NOARGS , "get_xmp" },
563+ {"get_frames_left" ,
564+ (PyCFunction )_jxl_decoder_get_frames_left ,
565+ METH_NOARGS ,
566+ "get_frames_left" },
576567 {"rewind" , (PyCFunction )_jxl_decoder_rewind , METH_NOARGS , "rewind" },
577568 {NULL , NULL } /* sentinel */
578569};
0 commit comments