@@ -748,7 +748,20 @@ Error HeifPixelImage::fill_RGB_16bit(uint16_t r, uint16_t g, uint16_t b, uint16_
748
748
}
749
749
750
750
751
- Error HeifPixelImage::overlay (std::shared_ptr<HeifPixelImage>& overlay, int dx, int dy)
751
+ uint32_t negate_negative_int32 (int32_t x)
752
+ {
753
+ assert (x <= 0 );
754
+
755
+ if (x == INT32_MIN) {
756
+ return static_cast <uint32_t >(INT32_MAX) + 1 ;
757
+ }
758
+ else {
759
+ return static_cast <uint32_t >(-x);
760
+ }
761
+ }
762
+
763
+
764
+ Error HeifPixelImage::overlay (std::shared_ptr<HeifPixelImage>& overlay, int32_t dx, int32_t dy)
752
765
{
753
766
std::set<enum heif_channel> channels = overlay->get_channel_set ();
754
767
@@ -773,90 +786,88 @@ Error HeifPixelImage::overlay(std::shared_ptr<HeifPixelImage>& overlay, int dx,
773
786
in_p = overlay->get_plane (channel, &in_stride);
774
787
out_p = get_plane (channel, &out_stride);
775
788
776
- int in_w = overlay->get_width (channel);
777
- int in_h = overlay->get_height (channel);
778
- assert (in_w >= 0 );
779
- assert (in_h >= 0 );
789
+ uint32_t in_w = overlay->get_width (channel);
790
+ uint32_t in_h = overlay->get_height (channel);
780
791
781
- int out_w = get_width (channel);
782
- int out_h = get_height (channel);
783
- assert (out_w >= 0 );
784
- assert (out_h >= 0 );
792
+ uint32_t out_w = get_width (channel);
793
+ uint32_t out_h = get_height (channel);
785
794
786
- // overlay image extends past the right border -> cut width for copy
787
- if (dx + in_w > out_w) {
788
- in_w = out_w - dx;
789
- }
795
+ // top-left points where to start copying in source and destination
796
+ uint32_t in_x0;
797
+ uint32_t in_y0;
798
+ uint32_t out_x0;
799
+ uint32_t out_y0;
790
800
791
- // overlay image extends past the bottom border -> cut height for copy
792
- if (dy + in_h > out_h) {
793
- in_h = out_h - dy;
801
+ if (dx > 0 && static_cast <uint32_t >(dx) >= out_w) {
802
+ // the overlay image is completely outside the right border -> skip overlaying
803
+ return Error::Ok;
804
+ }
805
+ else if (dx < 0 && in_w <= negate_negative_int32 (dx)) {
806
+ // the overlay image is completely outside the left border -> skip overlaying
807
+ return Error::Ok;
794
808
}
795
809
796
- // overlay image completely outside right or bottom border -> do not copy
797
- if (in_w < 0 || in_h < 0 ) {
798
- return Error (heif_error_Invalid_input,
799
- heif_suberror_Overlay_image_outside_of_canvas,
800
- " Overlay image outside of right or bottom canvas border" );
810
+ if (dx < 0 ) {
811
+ // overlay image started partially outside of left border
812
+
813
+ in_x0 = negate_negative_int32 (dx);
814
+ out_x0 = 0 ;
815
+ in_w = in_w - in_x0; // in_x0 < in_w because in_w > -dx = in_x0
816
+ }
817
+ else {
818
+ in_x0 = 0 ;
819
+ out_x0 = static_cast <uint32_t >(dx);
801
820
}
802
821
822
+ // we know that dx >= 0 && dx < out_w
803
823
804
- // calculate top-left point where to start copying in source and destination
805
- int in_x0 = 0 ;
806
- int in_y0 = 0 ;
807
- int out_x0 = dx;
808
- int out_y0 = dy;
824
+ if (static_cast <uint32_t >(dx) > UINT32_MAX - in_w ||
825
+ dx + in_w > out_w) {
826
+ // overlay image extends partially outside of right border
809
827
810
- // overlay image started outside of left border
811
- // -> move start into the image and start at left output column
812
- if (dx < 0 ) {
813
- in_x0 = -dx;
814
- out_x0 = 0 ;
828
+ in_w = out_w - static_cast <uint32_t >(dx); // we know that dx < out_w from first condition
829
+ }
830
+
831
+
832
+ if (dy > 0 && static_cast <uint32_t >(dy) >= out_h) {
833
+ // the overlay image is completely outside the bottom border -> skip overlaying
834
+ return Error::Ok;
835
+ }
836
+ else if (dy < 0 && in_h <= negate_negative_int32 (dy)) {
837
+ // the overlay image is completely outside the top border -> skip overlaying
838
+ return Error::Ok;
815
839
}
816
840
817
- // overlay image started outside of top border
818
- // -> move start into the image and start at top output row
819
841
if (dy < 0 ) {
820
- in_y0 = -dy;
842
+ // overlay image started partially outside of top border
843
+
844
+ in_y0 = negate_negative_int32 (dy);
821
845
out_y0 = 0 ;
846
+ in_h = in_h - in_y0; // in_y0 < in_h because in_h > -dy = in_y0
822
847
}
823
-
824
- // if overlay image is completely outside at left border, do not copy anything.
825
- if (in_w <= in_x0 ||
826
- in_h <= in_y0) {
827
- return Error (heif_error_Invalid_input,
828
- heif_suberror_Overlay_image_outside_of_canvas,
829
- " Overlay image outside of left or top canvas border" );
848
+ else {
849
+ in_y0 = 0 ;
850
+ out_y0 = static_cast <uint32_t >(dy);
830
851
}
831
852
832
- // verify that the destination points are within the bounds of the image's dimensions
833
- if (out_x0 < 0 ||
834
- out_x0 >= out_w ||
835
- out_y0 < 0 ||
836
- out_y0 >= out_h) {
837
- return Error (heif_error_Invalid_input,
838
- heif_suberror_Invalid_overlay_data,
839
- " Overlay image has invalid offsets" );
840
- }
853
+ // we know that dy >= 0 && dy < out_h
854
+
855
+ if (static_cast <uint32_t >(dy) > UINT32_MAX - in_h ||
856
+ dy + in_h > out_h) {
857
+ // overlay image extends partially outside of bottom border
841
858
842
- // verify that the source points are within the bounds of the image's dimensions
843
- if (in_x0 < 0 ||
844
- in_x0 >= in_w ||
845
- in_y0 < 0 ||
846
- in_y0 >= in_h) {
847
- return Error (heif_error_Invalid_input,
848
- heif_suberror_Invalid_overlay_data,
849
- " Overlay image has invalid offsets" );
859
+ in_h = out_h - static_cast <uint32_t >(dy); // we know that dy < out_h from first condition
850
860
}
851
861
852
- for (int y = in_y0; y < in_h; y++) {
862
+
863
+ for (uint32_t y = in_y0; y < in_h; y++) {
853
864
if (!has_alpha) {
854
865
memcpy (out_p + out_x0 + (out_y0 + y - in_y0) * out_stride,
855
866
in_p + in_x0 + y * in_stride,
856
867
in_w - in_x0);
857
868
}
858
869
else {
859
- for (int x = in_x0; x < in_w; x++) {
870
+ for (uint32_t x = in_x0; x < in_w; x++) {
860
871
uint8_t * outptr = &out_p[out_x0 + (out_y0 + y - in_y0) * out_stride + x];
861
872
uint8_t in_val = in_p[in_x0 + y * in_stride + x];
862
873
uint8_t alpha_val = alpha_p[in_x0 + y * in_stride + x];
0 commit comments