@@ -666,6 +666,116 @@ function _createGif(
666666 finishCallback ( ) ;
667667}
668668
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+
669779/**
670780 * Validates clipping params. Per drawImage spec sWidth and sHight cannot be
671781 * negative or greater than image intrinsic width and height
@@ -691,7 +801,7 @@ function _sAssign(sVal, iVal) {
691801 * the position of the image. Two more parameters can optionally be added to
692802 * specify the width and height of the image.
693803 *
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
695805 * differentiate between all these parameters, p5.js uses the language of
696806 * "destination rectangle" (which corresponds to "dx", "dy", etc.) and "source
697807 * image" (which corresponds to "sx", "sy", etc.) below. Specifying the
@@ -700,6 +810,14 @@ function _sAssign(sVal, iVal) {
700810 * to explain further:
701811 * <img src="assets/drawImage.png"></img>
702812 *
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+ *
703821 * @method image
704822 * @param {p5.Image|p5.Element|p5.Texture } img the image to display
705823 * @param {Number } x the x-coordinate of the top-left corner of the image
@@ -766,6 +884,37 @@ function _sAssign(sVal, iVal) {
766884 * }
767885 * </code>
768886 * </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>
769918 * @alt
770919 * image of the underside of a white umbrella and gridded ceiling above
771920 * image of the underside of a white umbrella and gridded ceiling above
@@ -788,6 +937,9 @@ function _sAssign(sVal, iVal) {
788937 * rectangle
789938 * @param {Number } [sHeight] the height of the subsection of the
790939 * 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
791943 */
792944p5 . prototype . image = function (
793945 img ,
@@ -798,25 +950,30 @@ p5.prototype.image = function(
798950 sx ,
799951 sy ,
800952 sWidth ,
801- sHeight
953+ sHeight ,
954+ fit ,
955+ xAlign ,
956+ yAlign
802957) {
803958 // set defaults per spec: https://goo.gl/3ykfOq
804959
805960 p5 . _validateParameters ( 'image' , arguments ) ;
806961
807962 let defW = img . width ;
808963 let defH = img . height ;
964+ yAlign = yAlign || constants . CENTER ;
965+ xAlign = xAlign || constants . CENTER ;
809966
810967 if ( img . elt && img . elt . videoWidth && ! img . canvas ) {
811968 // video no canvas
812969 defW = img . elt . videoWidth ;
813970 defH = img . elt . videoHeight ;
814971 }
815972
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 ;
820977 let _sx = sx || 0 ;
821978 let _sy = sy || 0 ;
822979 let _sw = sWidth || defW ;
@@ -847,10 +1004,33 @@ p5.prototype.image = function(
8471004 _sh *= pd ;
8481005 _sw *= pd ;
8491006
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+ ) ;
8511021
8521022 // 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+ ) ;
8541034} ;
8551035
8561036/**
0 commit comments