@@ -717,82 +717,113 @@ ImagingResampleInner(
717717 Imaging imTemp = NULL ;
718718 Imaging imOut = NULL ;
719719
720- int i , need_horizontal , need_vertical ;
720+ int i , second_pass , need_horizontal , need_vertical , error = 0 ;
721721 int ybox_first , ybox_last ;
722- int ksize_horiz , ksize_vert ;
722+ int ksize_horiz = 0 , ksize_vert = 0 ;
723723 int * bounds_horiz , * bounds_vert ;
724724 double * kk_horiz , * kk_vert ;
725725
726726 need_horizontal = xsize != imIn -> xsize || box [0 ] || box [2 ] != xsize ;
727727 need_vertical = ysize != imIn -> ysize || box [1 ] || box [3 ] != ysize ;
728728
729- ksize_vert = precompute_coeffs (
730- imIn -> ysize , box [1 ], box [3 ], ysize , filterp , & bounds_vert , & kk_vert
731- );
732- if (!ksize_vert ) {
733- return NULL ;
734- }
729+ // If height is being scaled down, but not width,
730+ // then run the vertical pass first, to make the horizontal pass faster
731+ int horizontal_first = !(xsize >= (box [2 ] - box [0 ]) && ysize < (box [3 ] - box [1 ]));
735732
736- // First used row in the source image
737- ybox_first = bounds_vert [0 ];
738- // Last used row in the source image
739- ybox_last = bounds_vert [ysize * 2 - 2 ] + bounds_vert [ysize * 2 - 1 ];
740-
741- /* two-pass resize, horizontal pass */
733+ if ((need_horizontal && horizontal_first ) || need_vertical ) {
734+ ksize_vert = precompute_coeffs (
735+ imIn -> ysize , box [1 ], box [3 ], ysize , filterp , & bounds_vert , & kk_vert
736+ );
737+ if (!ksize_vert ) {
738+ return NULL ;
739+ }
740+ }
742741 if (need_horizontal ) {
742+ if (horizontal_first ) {
743+ // First used row in the source image
744+ ybox_first = bounds_vert [0 ];
745+ // Last used row in the source image
746+ ybox_last = bounds_vert [ysize * 2 - 2 ] + bounds_vert [ysize * 2 - 1 ];
747+
748+ // Shift bounds for vertical pass
749+ for (i = 0 ; i < ysize ; i ++ ) {
750+ bounds_vert [i * 2 ] -= ybox_first ;
751+ }
752+ }
753+
743754 ksize_horiz = precompute_coeffs (
744755 imIn -> xsize , box [0 ], box [2 ], xsize , filterp , & bounds_horiz , & kk_horiz
745756 );
746757 if (!ksize_horiz ) {
747- free (bounds_vert );
748- free (kk_vert );
749- return NULL ;
758+ error = 1 ;
759+ goto end ;
750760 }
761+ }
751762
752- // Shift bounds for vertical pass
753- for (i = 0 ; i < ysize ; i ++ ) {
754- bounds_vert [i * 2 ] -= ybox_first ;
763+ #define PASS (function , w , h , offset , ksize , bounds , kk ) \
764+ second_pass = imTemp != NULL; \
765+ imTemp = ImagingNewDirty(imIn->mode, w, h); \
766+ if (!imTemp) { \
767+ error = 1; \
768+ goto end; \
769+ } \
770+ function(imTemp, imIn, offset, ksize, bounds, kk); \
771+ if (second_pass) { \
772+ ImagingDelete(imIn); \
773+ } \
774+ imIn = imTemp;
775+
776+ if (horizontal_first ) {
777+ if (need_horizontal ) {
778+ PASS (
779+ ResampleHorizontal ,
780+ xsize ,
781+ ybox_last - ybox_first ,
782+ ybox_first ,
783+ ksize_horiz ,
784+ bounds_horiz ,
785+ kk_horiz
786+ );
755787 }
756-
757- imTemp = ImagingNewDirty (imIn -> mode , xsize , ybox_last - ybox_first );
758- if (imTemp ) {
759- ResampleHorizontal (
760- imTemp , imIn , ybox_first , ksize_horiz , bounds_horiz , kk_horiz
788+ if (need_vertical ) {
789+ PASS (ResampleVertical , xsize , ysize , 0 , ksize_vert , bounds_vert , kk_vert );
790+ }
791+ } else {
792+ if (need_vertical ) {
793+ PASS (
794+ ResampleVertical ,
795+ imIn -> xsize ,
796+ ysize ,
797+ 0 ,
798+ ksize_vert ,
799+ bounds_vert ,
800+ kk_vert
761801 );
762802 }
763- free (bounds_horiz );
764- free (kk_horiz );
765- if (!imTemp ) {
766- free (bounds_vert );
767- free (kk_vert );
768- return NULL ;
803+ if (need_horizontal ) {
804+ PASS (
805+ ResampleHorizontal , xsize , ysize , 0 , ksize_horiz , bounds_horiz , kk_horiz
806+ );
769807 }
770- imOut = imIn = imTemp ;
771808 }
772809
773- /* vertical pass */
774- if (need_vertical ) {
775- imOut = ImagingNewDirty (imIn -> mode , imIn -> xsize , ysize );
776- if (imOut ) {
777- /* imIn can be the original image or horizontally resampled one */
778- ResampleVertical (imOut , imIn , 0 , ksize_vert , bounds_vert , kk_vert );
779- }
780- /* it's safe to call ImagingDelete with empty value
781- if previous step was not performed. */
782- ImagingDelete (imTemp );
783- free (bounds_vert );
784- free (kk_vert );
785- if (!imOut ) {
786- return NULL ;
787- }
788- } else {
789- // Free in any case
810+ end :
811+ if (ksize_horiz ) {
812+ free (bounds_horiz );
813+ free (kk_horiz );
814+ }
815+ if (ksize_vert ) {
790816 free (bounds_vert );
791817 free (kk_vert );
792818 }
819+ if (error ) {
820+ return NULL ;
821+ }
793822
794- /* none of the previous steps are performed, copying */
795- if (!imOut ) {
823+ if (imTemp ) {
824+ imOut = imTemp ;
825+ } else {
826+ // none of the previous steps are performed, copying
796827 imOut = ImagingCopy (imIn );
797828 }
798829
0 commit comments