Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add binary XML format to default image formats #2799

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,11 @@ public boolean supportsImageType(CloseableImage image) {
}

@Override
@Nullable
public Drawable createDrawable(CloseableImage image) {
if (!supportsImageType(image)) {
return null;
}
CloseableAnimatedImage closeable = ((CloseableAnimatedImage) image);
AnimatedImage animatedImage = closeable.getImage();
AnimationBackend animationBackend =
Expand All @@ -134,8 +138,12 @@ public Drawable createDrawable(CloseableImage image) {
}

@Override
@Nullable
public Drawable createDrawable(
Resources resources, CloseableImage closeableImage, ImageOptions imageOptions) {
if (!supportsImageType(closeableImage)) {
return null;
}
CloseableAnimatedImage closeable = ((CloseableAnimatedImage) closeableImage);
AnimatedImage animatedImage = closeable.getImage();
AnimationBackend animationBackend = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ class DefaultImageFormatChecker : FormatChecker {
GIF_HEADER_LENGTH,
BMP_HEADER_LENGTH,
ICO_HEADER_LENGTH,
HEIF_HEADER_LENGTH)
HEIF_HEADER_LENGTH,
BINARY_XML_HEADER_LENGTH,
)
.maxOrNull())

/**
Expand Down Expand Up @@ -61,6 +63,9 @@ class DefaultImageFormatChecker : FormatChecker {
if (isHeifHeader(headerBytes, headerSize)) {
return DefaultImageFormats.HEIF
}
if (isBinaryXmlHeader(headerBytes, headerSize)) {
return DefaultImageFormats.BINARY_XML
}
return if (isDngHeader(headerBytes, headerSize)) {
DefaultImageFormats.DNG
} else {
Expand Down Expand Up @@ -277,5 +282,27 @@ class DefaultImageFormatChecker : FormatChecker {
headerSize >= DNG_HEADER_LENGTH &&
(ImageFormatCheckerUtils.startsWithPattern(imageHeaderBytes, DNG_HEADER_II) ||
ImageFormatCheckerUtils.startsWithPattern(imageHeaderBytes, DNG_HEADER_MM))

/**
* These are the first 4 bytes of a binary XML file. We can only support binary XML files and
* not raw XML files because Android explicitly disallows raw XML files when inflating
* drawables. Binary XML files are created at build time by Android's AAPT.
*
* @see
* https://developer.android.com/reference/android/view/LayoutInflater#inflate(org.xmlpull.v1.XmlPullParser,%20android.view.ViewGroup)
*/
private val BINARY_XML_HEADER: ByteArray =
byteArrayOf(
3.toByte(),
0.toByte(),
8.toByte(),
0.toByte(),
)
private const val BINARY_XML_HEADER_LENGTH: Int = 4

private fun isBinaryXmlHeader(headerBytes: ByteArray, headerSize: Int): Boolean {
return headerSize >= BINARY_XML_HEADER_LENGTH &&
ImageFormatCheckerUtils.startsWithPattern(headerBytes, BINARY_XML_HEADER)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ object DefaultImageFormats {
@JvmField val WEBP_ANIMATED: ImageFormat = ImageFormat("WEBP_ANIMATED", "webp")
@JvmField val HEIF: ImageFormat = ImageFormat("HEIF", "heif")
@JvmField val DNG: ImageFormat = ImageFormat("DNG", "dng")
@JvmField val BINARY_XML: ImageFormat = ImageFormat("BINARY_XML", "xml")

/**
* Check if the given image format is a WebP image format (static or animated).
Expand Down Expand Up @@ -67,5 +68,6 @@ object DefaultImageFormats {
WEBP_EXTENDED_WITH_ALPHA,
WEBP_ANIMATED,
HEIF,
BINARY_XML,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ public class DefaultImageDecoder implements ImageDecoder {
return decodeGif(encodedImage, length, qualityInfo, options);
} else if (imageFormat == DefaultImageFormats.WEBP_ANIMATED) {
return decodeAnimatedWebp(encodedImage, length, qualityInfo, options);
} else if (imageFormat == DefaultImageFormats.BINARY_XML) {
throw new DecodeException("unsupported image format", encodedImage);
} else if (imageFormat == ImageFormat.UNKNOWN) {
throw new DecodeException("unknown image format", encodedImage);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ class KFrescoController(
drawableFactory?.createDrawable(r, a, b)?.let { createDrawableModel(it, b) }
}
}
?: run {
FLog.e(TAG, "Could not create Drawable for CloseableImage: $b")
null
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import com.facebook.fresco.vito.options.ImageOptionsDrawableFactory
import com.facebook.imagepipeline.drawable.DrawableFactory
import com.facebook.imagepipeline.image.CloseableImage

class DrawableFactoryWrapper(private val drawableFactory: DrawableFactory) :
class DrawableFactoryWrapper private constructor(private val drawableFactory: DrawableFactory) :
ImageOptionsDrawableFactory {
override fun createDrawable(
resources: Resources,
Expand All @@ -30,4 +30,15 @@ class DrawableFactoryWrapper(private val drawableFactory: DrawableFactory) :
} else {
null
}

companion object {
@JvmStatic
fun wrap(drawableFactory: DrawableFactory): ImageOptionsDrawableFactory {
return if (drawableFactory is ImageOptionsDrawableFactory) {
drawableFactory
} else {
DrawableFactoryWrapper(drawableFactory)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,8 @@ class DefaultFrescoVitoProvider(
return if (animatedDrawableFactory == null) {
bitmapFactory
} else {
if (animatedDrawableFactory is ImageOptionsDrawableFactory) {
ArrayVitoDrawableFactory(bitmapFactory, animatedDrawableFactory)
} else {
ArrayVitoDrawableFactory(bitmapFactory, DrawableFactoryWrapper(animatedDrawableFactory))
}
ArrayVitoDrawableFactory(
bitmapFactory, DrawableFactoryWrapper.wrap(animatedDrawableFactory))
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ class KFrescoVitoProvider(
override fun getConfig(): FrescoVitoConfig = vitoConfig

private fun getFactory(): ImageOptionsDrawableFactory? {
return ImagePipelineFactory.getInstance().getAnimatedDrawableFactory(null)?.let {
DrawableFactoryWrapper(it)
}
return ImagePipelineFactory.getInstance()
.getAnimatedDrawableFactory(null)
?.let(DrawableFactoryWrapper::wrap)
}
}