Improve support of SSA (V4+) PrimaryColour style
This commit is contained in:
parent
0ead2af22c
commit
1364c01e09
@ -308,8 +308,8 @@ public final class SsaDecoder extends SimpleSubtitleDecoder {
|
|||||||
|
|
||||||
// Apply primary color.
|
// Apply primary color.
|
||||||
if (style != null) {
|
if (style != null) {
|
||||||
if (style.primaryColor != SsaStyle.SSA_COLOR_UNKNOWN) {
|
if (style.primaryColor.isSet) {
|
||||||
spannableText.setSpan(new ForegroundColorSpan(style.primaryColor),
|
spannableText.setSpan(new ForegroundColorSpan(style.primaryColor.value),
|
||||||
0, spannableText.length(), SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
|
0, spannableText.length(), SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,9 +89,9 @@ import java.util.regex.Pattern;
|
|||||||
|
|
||||||
public final String name;
|
public final String name;
|
||||||
@SsaAlignment public final int alignment;
|
@SsaAlignment public final int alignment;
|
||||||
@ColorInt public int primaryColor;
|
public SsaColor primaryColor;
|
||||||
|
|
||||||
private SsaStyle(String name, @SsaAlignment int alignment, @ColorInt int primaryColor) {
|
private SsaStyle(String name, @SsaAlignment int alignment, SsaColor primaryColor) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.alignment = alignment;
|
this.alignment = alignment;
|
||||||
this.primaryColor = primaryColor;
|
this.primaryColor = primaryColor;
|
||||||
@ -152,14 +152,33 @@ import java.util.regex.Pattern;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ColorInt
|
private static SsaColor parsePrimaryColor(String primaryColorStr) {
|
||||||
private static int parsePrimaryColor(String primaryColorStr) {
|
|
||||||
try {
|
try {
|
||||||
return ColorParser.parseSsaColor(primaryColorStr);
|
return SsaColor.from(ColorParser.parseSsaColor(primaryColorStr.trim()));
|
||||||
} catch (IllegalArgumentException ex) {
|
} catch (IllegalArgumentException ex) {
|
||||||
Log.w(TAG, "Failed parsing color value: " + primaryColorStr);
|
Log.w(TAG, "Failed parsing color value: " + primaryColorStr);
|
||||||
}
|
}
|
||||||
return SSA_COLOR_UNKNOWN;
|
return SsaColor.UNSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an SSA V4+ style color in ARGB format.
|
||||||
|
*/
|
||||||
|
/* package */ static final class SsaColor {
|
||||||
|
|
||||||
|
public static SsaColor UNSET = new SsaColor(0, false);
|
||||||
|
|
||||||
|
public final @ColorInt int value;
|
||||||
|
public final boolean isSet;
|
||||||
|
|
||||||
|
private SsaColor(@ColorInt int value, boolean isSet) {
|
||||||
|
this.value = value;
|
||||||
|
this.isSet = isSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SsaColor from(@ColorInt int value) {
|
||||||
|
return new SsaColor(value, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -75,17 +75,35 @@ public final class ColorParser {
|
|||||||
*/
|
*/
|
||||||
@ColorInt
|
@ColorInt
|
||||||
public static int parseSsaColor(String colorExpression) {
|
public static int parseSsaColor(String colorExpression) {
|
||||||
// SSA V4+ color format is &HAABBGGRR.
|
// The SSA V4+ color can be represented in hex (&HAABBGGRR) or in decimal format (byte order
|
||||||
if (colorExpression.length() != 10 || !"&H".equals(colorExpression.substring(0, 2))) {
|
// AABBGGRR) and in both cases the alpha channel's value needs to be inverted as in case of SSA
|
||||||
throw new IllegalArgumentException();
|
// the 0xFF alpha value means transparent and 0x00 means opaque which is the opposite from the
|
||||||
|
// @ColorInt representation.
|
||||||
|
int abgr;
|
||||||
|
try {
|
||||||
|
// Parse color from hex format (&HAABBGGRR).
|
||||||
|
if (colorExpression.startsWith("&H")) {
|
||||||
|
StringBuilder rgbaStringBuilder = new StringBuilder(colorExpression);
|
||||||
|
if (colorExpression.length() < 10) {
|
||||||
|
// Add leading zeros if necessary.
|
||||||
|
while (rgbaStringBuilder.length() != 10) {
|
||||||
|
rgbaStringBuilder.insert(2, "0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
abgr = (int) Long.parseLong(colorExpression.substring(2), 16);
|
||||||
|
} else {
|
||||||
|
// Parse color from decimal format (bytes order AABBGGRR).
|
||||||
|
abgr = (int) Long.parseLong(colorExpression);
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
throw new IllegalArgumentException(ex);
|
||||||
}
|
}
|
||||||
// Convert &HAABBGGRR to #RRGGBBAA.
|
// Convert ABGR to ARGB.
|
||||||
String rgba = new StringBuilder()
|
int a = ((abgr >> 24) & 0xFF) ^ 0xFF; // Flip alpha.
|
||||||
.append(colorExpression.substring(2))
|
int b = (abgr >> 16) & 0xFF;
|
||||||
.append("#")
|
int g = (abgr >> 8) & 0xFF;
|
||||||
.reverse()
|
int r = abgr & 0xff;
|
||||||
.toString();
|
return Color.argb(a, r, g, b);
|
||||||
return parseColorInternal(rgba, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ColorInt
|
@ColorInt
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
package com.google.android.exoplayer2.util;
|
package com.google.android.exoplayer2.util;
|
||||||
|
|
||||||
import static android.graphics.Color.BLACK;
|
import static android.graphics.Color.BLACK;
|
||||||
|
import static android.graphics.Color.BLUE;
|
||||||
|
import static android.graphics.Color.GREEN;
|
||||||
import static android.graphics.Color.RED;
|
import static android.graphics.Color.RED;
|
||||||
import static android.graphics.Color.WHITE;
|
import static android.graphics.Color.WHITE;
|
||||||
import static android.graphics.Color.YELLOW;
|
import static android.graphics.Color.YELLOW;
|
||||||
@ -66,9 +68,21 @@ public final class ColorParserTest {
|
|||||||
// Hex colors in ColorParser are RGBA, where-as {@link Color#parseColor} takes ARGB.
|
// Hex colors in ColorParser are RGBA, where-as {@link Color#parseColor} takes ARGB.
|
||||||
assertThat(parseTtmlColor("#FFFFFF00")).isEqualTo(parseColor("#00FFFFFF"));
|
assertThat(parseTtmlColor("#FFFFFF00")).isEqualTo(parseColor("#00FFFFFF"));
|
||||||
assertThat(parseTtmlColor("#12345678")).isEqualTo(parseColor("#78123456"));
|
assertThat(parseTtmlColor("#12345678")).isEqualTo(parseColor("#78123456"));
|
||||||
// SSA colors are in &HAABBGGRR format.
|
}
|
||||||
assertThat(parseSsaColor("&HFF0000FF")).isEqualTo(RED);
|
|
||||||
assertThat(parseSsaColor("&HFF00FFFF")).isEqualTo(YELLOW);
|
@Test
|
||||||
|
public void ssaColorParsing() {
|
||||||
|
// Hex format (&HAABBGGRR).
|
||||||
|
assertThat(parseSsaColor("&H000000FF")).isEqualTo(RED);
|
||||||
|
assertThat(parseSsaColor("&H0000FFFF")).isEqualTo(YELLOW);
|
||||||
|
assertThat(parseSsaColor("&H400000FF")).isEqualTo(parseColor("#BFFF0000"));
|
||||||
|
// Leading zeros.
|
||||||
|
assertThat(parseSsaColor("&HFF")).isEqualTo(RED);
|
||||||
|
assertThat(parseSsaColor("&HFF00")).isEqualTo(GREEN);
|
||||||
|
assertThat(parseSsaColor("&HFF0000")).isEqualTo(BLUE);
|
||||||
|
// Decimal format (AABBGGRR byte order).
|
||||||
|
assertThat(parseSsaColor(/*#000000FF*/"255")).isEqualTo(parseColor("#FFFF0000"));
|
||||||
|
assertThat(parseSsaColor(/*#FF0000FF*/"4278190335")).isEqualTo(parseColor("#00FF0000"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Loading…
x
Reference in New Issue
Block a user