@@ -666,6 +666,116 @@ function _createGif(
666
666
finishCallback ( ) ;
667
667
}
668
668
669
+ /**
670
+ * @private
671
+ * @param {Constant } xAlign either LEFT, RIGHT or CENTER
672
+ * @param {Constant } yAlign either TOP, BOTTOM or CENTER
673
+ * @param {Number } dx
674
+ * @param {Number } dy
675
+ * @param {Number } dw
676
+ * @param {Number } dh
677
+ * @param {Number } sw
678
+ * @param {Number } sh
679
+ * @returns {Object }
680
+ */
681
+
682
+ function _imageContain ( xAlign , yAlign , dx , dy , dw , dh , sw , sh ) {
683
+ const r = Math . max ( sw / dw , sh / dh ) ;
684
+ const [ adjusted_dw , adjusted_dh ] = [ sw / r , sh / r ] ;
685
+ let x = dx ;
686
+ let y = dy ;
687
+
688
+ if ( xAlign === constants . CENTER ) {
689
+ x += ( dw - adjusted_dw ) / 2 ;
690
+ } else if ( xAlign === constants . RIGHT ) {
691
+ x += dw - adjusted_dw ;
692
+ }
693
+
694
+ if ( yAlign === constants . CENTER ) {
695
+ y += ( dh - adjusted_dh ) / 2 ;
696
+ } else if ( yAlign === constants . BOTTOM ) {
697
+ y += dh - adjusted_dh ;
698
+ }
699
+ return { x, y, w : adjusted_dw , h : adjusted_dh } ;
700
+ }
701
+ /**
702
+ * @private
703
+ * @param {Constant } xAlign either LEFT, RIGHT or CENTER
704
+ * @param {Constant } yAlign either TOP, BOTTOM or CENTER
705
+ * @param {Number } dw
706
+ * @param {Number } dh
707
+ * @param {Number } sx
708
+ * @param {Number } sy
709
+ * @param {Number } sw
710
+ * @param {Number } sh
711
+ * @returns {Object }
712
+ */
713
+
714
+ function _imageCover ( xAlign , yAlign , dw , dh , sx , sy , sw , sh ) {
715
+ const r = Math . max ( dw / sw , dh / sh ) ;
716
+ const [ adjusted_sw , adjusted_sh ] = [ dw / r , dh / r ] ;
717
+
718
+ let x = sx ;
719
+ let y = sy ;
720
+
721
+ if ( xAlign === constants . CENTER ) {
722
+ x += ( sw - adjusted_sw ) / 2 ;
723
+ } else if ( xAlign === constants . RIGHT ) {
724
+ x += sw - adjusted_sw ;
725
+ }
726
+
727
+ if ( yAlign === constants . CENTER ) {
728
+ y += ( sh - adjusted_sh ) / 2 ;
729
+ } else if ( yAlign === constants . BOTTOM ) {
730
+ y += sh - adjusted_sh ;
731
+ }
732
+
733
+ return { x, y, w : adjusted_sw , h : adjusted_sh } ;
734
+ }
735
+
736
+ /**
737
+ * @private
738
+ * @param {Constant } [fit] either CONTAIN or COVER
739
+ * @param {Constant } xAlign either LEFT, RIGHT or CENTER
740
+ * @param {Constant } yAlign either TOP, BOTTOM or CENTER
741
+ * @param {Number } dx
742
+ * @param {Number } dy
743
+ * @param {Number } dw
744
+ * @param {Number } dh
745
+ * @param {Number } sx
746
+ * @param {Number } sy
747
+ * @param {Number } sw
748
+ * @param {Number } sh
749
+ * @returns {Object }
750
+ */
751
+ function _imageFit ( fit , xAlign , yAlign , dx , dy , dw , dh , sx , sy , sw , sh ) {
752
+ if ( fit === constants . COVER ) {
753
+ const { x, y, w, h } = _imageCover ( xAlign , yAlign , dw , dh , sx , sy , sw , sh ) ;
754
+ sx = x ;
755
+ sy = y ;
756
+ sw = w ;
757
+ sh = h ;
758
+ }
759
+
760
+ if ( fit === constants . CONTAIN ) {
761
+ const { x, y, w, h } = _imageContain (
762
+ xAlign ,
763
+ yAlign ,
764
+ dx ,
765
+ dy ,
766
+ dw ,
767
+ dh ,
768
+ sw ,
769
+ sh
770
+ ) ;
771
+ dx = x ;
772
+ dy = y ;
773
+ dw = w ;
774
+ dh = h ;
775
+ }
776
+ return { sx, sy, sw, sh, dx, dy, dw, dh } ;
777
+ }
778
+
669
779
/**
670
780
* Validates clipping params. Per drawImage spec sWidth and sHight cannot be
671
781
* negative or greater than image intrinsic width and height
@@ -691,7 +801,7 @@ function _sAssign(sVal, iVal) {
691
801
* the position of the image. Two more parameters can optionally be added to
692
802
* specify the width and height of the image.
693
803
*
694
- * This function can also be used with all eight Number parameters. To
804
+ * This function can also be used with eight Number parameters. To
695
805
* differentiate between all these parameters, p5.js uses the language of
696
806
* "destination rectangle" (which corresponds to "dx", "dy", etc.) and "source
697
807
* image" (which corresponds to "sx", "sy", etc.) below. Specifying the
@@ -700,6 +810,14 @@ function _sAssign(sVal, iVal) {
700
810
* to explain further:
701
811
* <img src="assets/drawImage.png"></img>
702
812
*
813
+ * This function can also be used to draw images without distorting the orginal aspect ratio,
814
+ * by adding 9th parameter, fit, which can either be COVER or CONTAIN.
815
+ * CONTAIN, as the name suggests, contains the whole image within the specified destination box
816
+ * without distorting the image ratio.
817
+ * COVER covers the entire destination box.
818
+ *
819
+ *
820
+ *
703
821
* @method image
704
822
* @param {p5.Image|p5.Element|p5.Texture } img the image to display
705
823
* @param {Number } x the x-coordinate of the top-left corner of the image
@@ -766,6 +884,37 @@ function _sAssign(sVal, iVal) {
766
884
* }
767
885
* </code>
768
886
* </div>
887
+ * <div>
888
+ * <code>
889
+ * let img;
890
+ * function preload() {
891
+ * // dimensions of image are 780 x 440
892
+ * // dimensions of canvas are 100 x 100
893
+ * img = loadImage('assets/moonwalk.jpg');
894
+ * }
895
+ * function setup() {
896
+ * // CONTAIN the whole image without distorting the image's aspect ratio
897
+ * // CONTAIN the image within the specified destination box and display at LEFT,CENTER position
898
+ * background(color('green'));
899
+ * image(img, 0, 0, width, height, 0, 0, img.width, img.height, CONTAIN, LEFT);
900
+ * }
901
+ * </code>
902
+ * </div>
903
+ * <div>
904
+ * <code>
905
+ * let img;
906
+ * function preload() {
907
+ * img = loadImage('assets/laDefense50.png'); // dimensions of image are 50 x 50
908
+ * }
909
+ * function setup() {
910
+ * // COVER the whole destination box without distorting the image's aspect ratio
911
+ * // COVER the specified destination box which is of dimension 100 x 100
912
+ * // Without specifying xAlign or yAlign, the image will be
913
+ * // centered in the destination box in both axes
914
+ * image(img, 0, 0, width, height, 0, 0, img.width, img.height, COVER);
915
+ * }
916
+ * </code>
917
+ * </div>
769
918
* @alt
770
919
* image of the underside of a white umbrella and gridded ceiling above
771
920
* image of the underside of a white umbrella and gridded ceiling above
@@ -788,6 +937,9 @@ function _sAssign(sVal, iVal) {
788
937
* rectangle
789
938
* @param {Number } [sHeight] the height of the subsection of the
790
939
* source image to draw into the destination rectangle
940
+ * @param {Constant } [fit] either CONTAIN or COVER
941
+ * @param {Constant } [xAlign] either LEFT, RIGHT or CENTER default is CENTER
942
+ * @param {Constant } [yAlign] either TOP, BOTTOM or CENTER default is CENTER
791
943
*/
792
944
p5 . prototype . image = function (
793
945
img ,
@@ -798,25 +950,30 @@ p5.prototype.image = function(
798
950
sx ,
799
951
sy ,
800
952
sWidth ,
801
- sHeight
953
+ sHeight ,
954
+ fit ,
955
+ xAlign ,
956
+ yAlign
802
957
) {
803
958
// set defaults per spec: https://goo.gl/3ykfOq
804
959
805
960
p5 . _validateParameters ( 'image' , arguments ) ;
806
961
807
962
let defW = img . width ;
808
963
let defH = img . height ;
964
+ yAlign = yAlign || constants . CENTER ;
965
+ xAlign = xAlign || constants . CENTER ;
809
966
810
967
if ( img . elt && img . elt . videoWidth && ! img . canvas ) {
811
968
// video no canvas
812
969
defW = img . elt . videoWidth ;
813
970
defH = img . elt . videoHeight ;
814
971
}
815
972
816
- const _dx = dx ;
817
- const _dy = dy ;
818
- const _dw = dWidth || defW ;
819
- const _dh = dHeight || defH ;
973
+ let _dx = dx ;
974
+ let _dy = dy ;
975
+ let _dw = dWidth || defW ;
976
+ let _dh = dHeight || defH ;
820
977
let _sx = sx || 0 ;
821
978
let _sy = sy || 0 ;
822
979
let _sw = sWidth || defW ;
@@ -847,10 +1004,33 @@ p5.prototype.image = function(
847
1004
_sh *= pd ;
848
1005
_sw *= pd ;
849
1006
850
- const vals = canvas . modeAdjust ( _dx , _dy , _dw , _dh , this . _renderer . _imageMode ) ;
1007
+ let vals = canvas . modeAdjust ( _dx , _dy , _dw , _dh , this . _renderer . _imageMode ) ;
1008
+ vals = _imageFit (
1009
+ fit ,
1010
+ xAlign ,
1011
+ yAlign ,
1012
+ vals . x ,
1013
+ vals . y ,
1014
+ vals . w ,
1015
+ vals . h ,
1016
+ _sx ,
1017
+ _sy ,
1018
+ _sw ,
1019
+ _sh
1020
+ ) ;
851
1021
852
1022
// tint the image if there is a tint
853
- this . _renderer . image ( img , _sx , _sy , _sw , _sh , vals . x , vals . y , vals . w , vals . h ) ;
1023
+ this . _renderer . image (
1024
+ img ,
1025
+ vals . sx ,
1026
+ vals . sy ,
1027
+ vals . sw ,
1028
+ vals . sh ,
1029
+ vals . dx ,
1030
+ vals . dy ,
1031
+ vals . dw ,
1032
+ vals . dh
1033
+ ) ;
854
1034
} ;
855
1035
856
1036
/**
0 commit comments