3636 * the input pixels onto the output frame geometry (for example, by stretching the input frame to
3737 * match the specified output frame, or fitting the input frame using letterboxing).
3838 *
39- * <p>Aspect ratio is applied before setting resolution.
40- *
4139 * <p>The background color of the output frame will be black, with alpha = 0 if applicable.
4240 */
4341@ UnstableApi
@@ -49,8 +47,7 @@ public final class Presentation implements MatrixTransformation {
4947 * <p>One of {@link #LAYOUT_SCALE_TO_FIT}, {@link #LAYOUT_SCALE_TO_FIT_WITH_CROP}, or {@link
5048 * #LAYOUT_STRETCH_TO_FIT}.
5149 *
52- * <p>May scale either width or height, leaving the other output dimension equal to its input,
53- * unless {@link Builder#setResolution(int)} rescales width and height.
50+ * <p>May scale either width or height, leaving the other output dimension equal to its input.
5451 */
5552 @ Documented
5653 @ Retention (SOURCE )
@@ -100,81 +97,82 @@ public final class Presentation implements MatrixTransformation {
10097 */
10198 public static final int LAYOUT_STRETCH_TO_FIT = 2 ;
10299
103- /** A builder for {@link Presentation} instances. */
104- public static final class Builder {
105-
106- // Optional fields.
107- private int outputHeight ;
108- private float aspectRatio ;
109- private @ Layout int layout ;
100+ private static final float ASPECT_RATIO_UNSET = -1f ;
110101
111- /** Creates a builder with default values. */
112- public Builder () {
113- outputHeight = C .LENGTH_UNSET ;
114- aspectRatio = C .LENGTH_UNSET ;
115- }
102+ private static void checkLayout (@ Layout int layout ) {
103+ checkArgument (
104+ layout == LAYOUT_SCALE_TO_FIT
105+ || layout == LAYOUT_SCALE_TO_FIT_WITH_CROP
106+ || layout == LAYOUT_STRETCH_TO_FIT ,
107+ "invalid layout " + layout );
108+ }
116109
117- /**
118- * Sets the output resolution using the output height .
119- *
120- * <p>The default value, {@link C#LENGTH_UNSET}, corresponds to using the same height as the
121- * input. Output width of the displayed frame will scale to preserve the frame's aspect ratio
122- * after other transformations.
123- *
124- * <p>For example, a 1920x1440 frame can be scaled to 640x480 by calling {@code
125- * setResolution(480)}.
126- *
127- * @param height The output height of the displayed frame, in pixels.
128- * @return This builder.
129- */
130- public Builder setResolution ( int height ) {
131- this . outputHeight = height ;
132- return this ;
133- }
110+ /**
111+ * Creates a new {@link Presentation} instance .
112+ *
113+ * <p>The output frame will have the given aspect ratio (width/ height ratio). Width or height will
114+ * be resized to conform to this {@code aspectRatio}, given a {@link Layout}.
115+ *
116+ * @param aspectRatio The aspect ratio (width/height ratio) of the output frame. Must be positive.
117+ * @param layout The layout of the output frame.
118+ */
119+ public static Presentation createForAspectRatio ( float aspectRatio , @ Layout int layout ) {
120+ checkArgument (
121+ aspectRatio == C . LENGTH_UNSET || aspectRatio > 0 ,
122+ "aspect ratio " + aspectRatio + " must be positive or unset" );
123+ checkLayout ( layout );
124+ return new Presentation (
125+ /* width= */ C . LENGTH_UNSET , /* height= */ C . LENGTH_UNSET , aspectRatio , layout ) ;
126+ }
134127
135- /**
136- * Sets the aspect ratio (width/height ratio) for the output frame.
137- *
138- * <p>Resizes a frame's width or height to conform to an {@code aspectRatio}, given a {@link
139- * Layout}. {@code aspectRatio} defaults to {@link C#LENGTH_UNSET}, which corresponds to the
140- * same aspect ratio as the input frame. {@code layout} defaults to {@link #LAYOUT_SCALE_TO_FIT}
141- *
142- * <p>Width and height values set may be rescaled by {@link #setResolution(int)}, which is
143- * applied after aspect ratio changes.
144- *
145- * @param aspectRatio The aspect ratio (width/height ratio) of the output frame. Must be
146- * positive.
147- * @return This builder.
148- */
149- public Builder setAspectRatio (float aspectRatio , @ Layout int layout ) {
150- checkArgument (aspectRatio > 0 , "aspect ratio " + aspectRatio + " must be positive" );
151- checkArgument (
152- layout == LAYOUT_SCALE_TO_FIT
153- || layout == LAYOUT_SCALE_TO_FIT_WITH_CROP
154- || layout == LAYOUT_STRETCH_TO_FIT ,
155- "invalid layout " + layout );
156- this .aspectRatio = aspectRatio ;
157- this .layout = layout ;
158- return this ;
159- }
128+ /**
129+ * Creates a new {@link Presentation} instance.
130+ *
131+ * <p>The output frame will have the given height. Width will scale to preserve the input aspect
132+ * ratio.
133+ *
134+ * @param height The height of the output frame, in pixels.
135+ */
136+ public static Presentation createForHeight (int height ) {
137+ return new Presentation (
138+ /* width= */ C .LENGTH_UNSET , height , ASPECT_RATIO_UNSET , LAYOUT_SCALE_TO_FIT );
139+ }
160140
161- public Presentation build () {
162- return new Presentation (outputHeight , aspectRatio , layout );
163- }
141+ /**
142+ * Creates a new {@link Presentation} instance.
143+ *
144+ * <p>The output frame will have the given width and height, given a {@link Layout}.
145+ *
146+ * <p>Width and height must be positive integers representing the output frame's width and height.
147+ *
148+ * @param width The width of the output frame, in pixels.
149+ * @param height The height of the output frame, in pixels.
150+ * @param layout The layout of the output frame.
151+ */
152+ public static Presentation createForWidthAndHeight (int width , int height , @ Layout int layout ) {
153+ checkArgument (width > 0 , "width " + width + " must be positive" );
154+ checkArgument (height > 0 , "height " + height + " must be positive" );
155+ checkLayout (layout );
156+ return new Presentation (width , height , ASPECT_RATIO_UNSET , layout );
164157 }
165158
159+ private final int requestedWidthPixels ;
166160 private final int requestedHeightPixels ;
167- private final float requestedAspectRatio ;
161+ private float requestedAspectRatio ;
168162 private final @ Layout int layout ;
169163
170164 private float outputWidth ;
171165 private float outputHeight ;
172166 private @ MonotonicNonNull Matrix transformationMatrix ;
173167
174- /** Creates a new instance. */
175- private Presentation (int requestedHeightPixels , float requestedAspectRatio , @ Layout int layout ) {
176- this .requestedHeightPixels = requestedHeightPixels ;
177- this .requestedAspectRatio = requestedAspectRatio ;
168+ private Presentation (int width , int height , float aspectRatio , @ Layout int layout ) {
169+ checkArgument (
170+ (aspectRatio == C .LENGTH_UNSET ) || (width == C .LENGTH_UNSET ),
171+ "width and aspect ratio should not both be set" );
172+
173+ this .requestedWidthPixels = width ;
174+ this .requestedHeightPixels = height ;
175+ this .requestedAspectRatio = aspectRatio ;
178176 this .layout = layout ;
179177
180178 outputWidth = C .LENGTH_UNSET ;
@@ -191,13 +189,21 @@ public Size configure(int inputWidth, int inputHeight) {
191189 outputWidth = inputWidth ;
192190 outputHeight = inputHeight ;
193191
192+ if ((requestedWidthPixels != C .LENGTH_UNSET ) && (requestedHeightPixels != C .LENGTH_UNSET )) {
193+ requestedAspectRatio = (float ) requestedWidthPixels / requestedHeightPixels ;
194+ }
195+
194196 if (requestedAspectRatio != C .LENGTH_UNSET ) {
195197 applyAspectRatio ();
196198 }
197199
198- // Scale width and height to desired requestedHeightPixels, preserving aspect ratio.
199- if (requestedHeightPixels != C .LENGTH_UNSET && requestedHeightPixels != outputHeight ) {
200- outputWidth = requestedHeightPixels * outputWidth / outputHeight ;
200+ // Scale output width and height to requested values.
201+ if (requestedHeightPixels != C .LENGTH_UNSET ) {
202+ if (requestedWidthPixels != C .LENGTH_UNSET ) {
203+ outputWidth = requestedWidthPixels ;
204+ } else {
205+ outputWidth = requestedHeightPixels * outputWidth / outputHeight ;
206+ }
201207 outputHeight = requestedHeightPixels ;
202208 }
203209 return new Size (Math .round (outputWidth ), Math .round (outputHeight ));
0 commit comments