Skip to content

Commit 3882abd

Browse files
committed
video transformation parameters and zoom transformation
1 parent 5839c0b commit 3882abd

File tree

2 files changed

+425
-52
lines changed

2 files changed

+425
-52
lines changed

cloudinary-core/src/main/java/com/cloudinary/Transformation.java

Lines changed: 250 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import java.util.Map;
77
import java.util.SortedMap;
88
import java.util.TreeMap;
9+
import java.util.regex.Matcher;
10+
import java.util.regex.Pattern;
911

1012
import com.cloudinary.utils.ObjectUtils;
1113
import com.cloudinary.utils.StringUtils;
@@ -23,6 +25,8 @@ public class Transformation {
2325

2426
private static final Map DEFAULT_RESPONSIVE_WIDTH_TRANSFORMATION = ObjectUtils.asMap("width", "auto", "crop", "limit");
2527
protected static Map responsiveWidthTransformation = null;
28+
private static final Pattern RANGE_VALUE_RE = Pattern.compile("^((?:\\d+\\.)?\\d+)([%pP])?$");
29+
private static final Pattern RANGE_RE = Pattern.compile("^(\\d+\\.)?\\d+[%pP]?\\.\\.(\\d+\\.)?\\d+[%pP]?$");
2630

2731
public Transformation(Transformation transformation) {
2832
this(dup(transformation.transformations));
@@ -172,6 +176,156 @@ public Transformation dpr(int value) {
172176
public Transformation dpr(String value) {
173177
return param("dpr", value);
174178
}
179+
180+
public Transformation duration(String value) {
181+
return param("duration", value);
182+
}
183+
184+
public Transformation duration(float value) {
185+
return param("duration", new Float(value));
186+
}
187+
188+
public Transformation duration(double value) {
189+
return param("duration", new Double(value));
190+
}
191+
192+
public Transformation durationPercent(float value) {
193+
return param("duration", new Float(value).toString() + "p");
194+
}
195+
196+
public Transformation durationPercent(double value) {
197+
return param("duration", new Double(value).toString() + "p");
198+
}
199+
200+
public Transformation startOffset(String value) {
201+
return param("start_offset", value);
202+
}
203+
204+
public Transformation startOffset(float value) {
205+
return param("start_offset", new Float(value));
206+
}
207+
208+
public Transformation startOffset(double value) {
209+
return param("start_offset", new Double(value));
210+
}
211+
212+
public Transformation startOffsetPercent(float value) {
213+
return param("start_offset", new Float(value).toString() + "p");
214+
}
215+
216+
public Transformation startOffsetPercent(double value) {
217+
return param("start_offset", new Double(value).toString() + "p");
218+
}
219+
220+
public Transformation endOffset(String value) {
221+
return param("end_offset", value);
222+
}
223+
224+
public Transformation endOffset(float value) {
225+
return param("end_offset", new Float(value));
226+
}
227+
228+
public Transformation endOffset(double value) {
229+
return param("end_offset", new Double(value));
230+
}
231+
232+
public Transformation endOffsetPercent(float value) {
233+
return param("end_offset", new Float(value).toString() + "p");
234+
}
235+
236+
public Transformation endOffsetPercent(double value) {
237+
return param("end_offset", new Double(value).toString() + "p");
238+
}
239+
240+
public Transformation offset(String value) {
241+
return param("offset", value);
242+
}
243+
244+
public Transformation offset(String[] value) {
245+
if (value.length < 2) throw new IllegalArgumentException("Offset range must include at least 2 items");
246+
return param("offset", value);
247+
}
248+
249+
public Transformation offset(float[] value) {
250+
if (value.length < 2) throw new IllegalArgumentException("Offset range must include at least 2 items");
251+
Number[] numberArray = new Number[]{value[0], value[1]};
252+
return offset(numberArray);
253+
}
254+
255+
public Transformation offset(double[] value) {
256+
if (value.length < 2) throw new IllegalArgumentException("Offset range must include at least 2 items");
257+
Number[] numberArray = new Number[]{value[0], value[1]};
258+
return offset(numberArray);
259+
}
260+
261+
public Transformation offset(Number[] value) {
262+
if (value.length < 2) throw new IllegalArgumentException("Offset range must include at least 2 items");
263+
return param("offset", value);
264+
}
265+
266+
public Transformation videoCodec(String value) {
267+
return param("video_codec", value);
268+
}
269+
270+
public Transformation videoCodec(Map<String, String> value) {
271+
return param("video_codec", value);
272+
}
273+
274+
public Transformation audioCodec(String value) {
275+
return param("audio_codec", value);
276+
}
277+
278+
public Transformation audioFrequency(String value) {
279+
return param("audio_frequency", value);
280+
}
281+
282+
public Transformation audioFrequency(int value) {
283+
return param("audio_frequency", value);
284+
}
285+
286+
public Transformation bitRate(String value) {
287+
return param("bit_rate", value);
288+
}
289+
290+
public Transformation bitRate(int value) {
291+
return param("bit_rate", new Integer(value));
292+
}
293+
294+
public Transformation videoSampling(String value) {
295+
return param("video_sampling", value);
296+
}
297+
298+
public Transformation videoSamplingFrames(int value) {
299+
return param("video_sampling", value);
300+
}
301+
302+
public Transformation videoSamplingSeconds(Number value) {
303+
return param("video_sampling", value.toString() + "s");
304+
}
305+
306+
public Transformation videoSamplingSeconds(int value) {
307+
return videoSamplingSeconds(new Integer(value));
308+
}
309+
310+
public Transformation videoSamplingSeconds(float value) {
311+
return videoSamplingSeconds(new Float(value));
312+
}
313+
314+
public Transformation videoSamplingSeconds(double value) {
315+
return videoSamplingSeconds(new Double(value));
316+
}
317+
318+
public Transformation zoom(String value) {
319+
return param("zoom", value);
320+
}
321+
322+
public Transformation zoom(float value) {
323+
return param("zoom", new Float(value));
324+
}
325+
326+
public Transformation zoom(double value) {
327+
return param("zoom", new Double(value));
328+
}
175329

176330
public Transformation responsiveWidth(boolean value) {
177331
return param("responsive_width", value);
@@ -279,22 +433,57 @@ public String generate(Map options) {
279433

280434
String flags = StringUtils.join(ObjectUtils.asArray(options.get("flags")), ".");
281435

436+
String duration = normRangeValue(options.get("duration"));
437+
String startOffset = normRangeValue(options.get("start_offset"));
438+
String endOffset = normRangeValue(options.get("end_offset"));
439+
String[] offset = splitRange(options.get("offset"));
440+
if (offset != null) {
441+
startOffset = normRangeValue(offset[0]);
442+
endOffset = normRangeValue(offset[1]);
443+
}
444+
445+
String videoCodec = processVideoCodecParam(options.get("video_codec"));
446+
String dpr = ObjectUtils.asString(options.get("dpr"), null == defaultDPR ? null : defaultDPR.toString());
447+
282448
SortedMap<String, String> params = new TreeMap<String, String>();
283-
params.put("w", width);
284-
params.put("h", height);
285-
params.put("t", namedTransformation);
286-
params.put("c", crop);
449+
params.put("a", angle);
287450
params.put("b", background);
451+
params.put("c", crop);
288452
params.put("co", color);
289-
params.put("a", angle);
290-
params.put("fl", flags);
291-
String dpr = ObjectUtils.asString(options.get("dpr"), null == defaultDPR ? null : defaultDPR.toString());
292453
params.put("dpr", dpr);
293-
294-
String[] simple_params = new String[] { "x", "x", "y", "y", "r", "radius", "d", "default_image", "g",
295-
"gravity", "cs", "color_space", "p", "prefix", "l", "overlay", "u", "underlay", "f", "fetch_format",
296-
"dn", "density", "pg", "page", "dl", "delay", "e", "effect", "bo", "border", "q", "quality", "o",
297-
"opacity" };
454+
params.put("du", duration);
455+
params.put("eo", endOffset);
456+
params.put("fl", flags);
457+
params.put("h", height);
458+
params.put("so", startOffset);
459+
params.put("t", namedTransformation);
460+
params.put("vc", videoCodec);
461+
params.put("w", width);
462+
463+
String[] simple_params = new String[] {
464+
"ac", "audio_codec",
465+
"af", "audio_frequency",
466+
"bo", "border",
467+
"br", "bit_rate",
468+
"cs", "color_space",
469+
"d", "default_image",
470+
"dl", "delay",
471+
"dn", "density",
472+
"e", "effect",
473+
"f", "fetch_format",
474+
"g", "gravity",
475+
"l", "overlay",
476+
"o", "opacity",
477+
"p", "prefix",
478+
"pg", "page",
479+
"q", "quality",
480+
"r", "radius",
481+
"u", "underlay",
482+
"vs", "video_sampling",
483+
"x", "x",
484+
"y", "y",
485+
"z", "zoom" };
486+
298487
for (int i = 0; i < simple_params.length; i += 2) {
299488
params.put(simple_params[i], ObjectUtils.asString(options.get(simple_params[i + 1])));
300489
}
@@ -364,5 +553,54 @@ public static void setDefaultIsResponsive(boolean isResponsive) {
364553
public static void setDefaultDPR(Object dpr) {
365554
defaultDPR = dpr;
366555
}
556+
557+
private static String[] splitRange(Object range) {
558+
if (range instanceof String[] && ((String[]) range).length >= 2) {
559+
String[] stringArrayRange = ((String[]) range);
560+
return new String[]{stringArrayRange[0], stringArrayRange[1]};
561+
} else if (range instanceof Number[] && ((Number[]) range).length >= 2) {
562+
Number[] numberArrayRange = ((Number[]) range);
563+
return new String[]{numberArrayRange[0].toString(), numberArrayRange[1].toString()};
564+
} else if (range instanceof String && RANGE_RE.matcher((String) range).matches()) {
565+
return ((String) range).split("\\.\\.", 2);
566+
} else {
567+
return null;
568+
}
569+
}
570+
571+
private static String normRangeValue(Object objectValue) {
572+
if (objectValue == null) return null;
573+
String value = objectValue.toString();
574+
if (StringUtils.isEmpty(value)) return null;
575+
576+
Matcher matcher = RANGE_VALUE_RE.matcher(value);
577+
578+
if (!matcher.matches()) {
579+
return null;
580+
}
581+
582+
String modifier = "";
583+
if (matcher.groupCount() == 2 && !StringUtils.isEmpty(matcher.group(2))) {
584+
modifier = "p";
585+
}
586+
return matcher.group(1) + modifier;
587+
}
588+
589+
private static String processVideoCodecParam(Object param) {
590+
StringBuilder outParam = new StringBuilder();
591+
if (param instanceof String) {
592+
outParam.append(param);
593+
} if (param instanceof Map<?, ?>) {
594+
Map<String, String> paramMap = ( Map<String, String> ) param;
595+
outParam.append(paramMap.get("codec"));
596+
if (paramMap.containsKey("profile")) {
597+
outParam.append(":").append(paramMap.get("profile"));
598+
if (paramMap.containsKey("level")) {
599+
outParam.append(":").append(paramMap.get("level"));
600+
}
601+
}
602+
}
603+
return outParam.toString();
604+
}
367605

368606
}

0 commit comments

Comments
 (0)