I have been researching on how to recreate the background effect of Apple music and how it extracts colors and makes this dynamic slow moving fluid like with colors of extracted album art and animate background and the effect is blurred.
this is the code that extracts colors from album cover the deal is to make that animated
image example :Screenshot
So i made this class that extracts colors so far and i have no idea on how to create this effect :
public class ColorExtractor {
private int previousColor; // Initial fallback color (black)
private long animationDuration; // Duration in milliseconds
private Interpolator interpolator; // Interpolator for animation
public ColorExtractor(Context context) {
this.animationDuration = 300; // Default duration
this.interpolator = new DecelerateInterpolator(); // Default interpolator
}
public interface ColorCallback {
void onColorExtracted(int animatedColor);
}
/**
* Set the animation duration for the color transition.
* @param duration Animation duration in milliseconds.
*/
public void setAnimationDuration(long duration) {
this.animationDuration = duration;
}
/**
* Set a custom interpolator for the color transition.
* @param interpolator Custom interpolator for the animation.
*/
public void setInterpolator(Interpolator interpolator) {
this.interpolator = interpolator;
}
public void extractDominantColor(byte[] imageData, ColorCallback callback) {
Bitmap bitmap = BitmapFactory.decodeByteArray(imageData, 0, imageData.length);
if (bitmap != null) {
Palette.from(bitmap).generate(palette -> {
if (palette != null) {
int newColor = getColorFromPalette(palette);
if (newColor != previousColor) { // Only animate if the color changes
animateColorChange(previousColor, newColor, callback);
previousColor = newColor; // Update previous color to the new one
} else {
callback.onColorExtracted(previousColor); // No animation if colors are the same
}
bitmap.recycle(); // Clean up bitmap to free memory
} else {
callback.onColorExtracted(previousColor); // Fallback to previous color
}
});
} else {
callback.onColorExtracted(previousColor); // Fallback to previous color
}
}
private int getColorFromPalette(Palette palette) {
// Create a list of swatch providers
List<Palette.Swatch> swatches = new ArrayList<>();
swatches.add(palette.getLightMutedSwatch());
swatches.add(palette.getMutedSwatch());
swatches.add(palette.getLightVibrantSwatch());
swatches.add(palette.getVibrantSwatch());
// Shuffle the list for random selection order
Collections.shuffle(swatches);
// Iterate over shuffled swatches and return the first available color
for (Palette.Swatch swatch : swatches) {
if (swatch != null) {
return swatch.getRgb();
}
}
// If no suitable swatch is found, use the last known color instead
return previousColor;
}
private void animateColorChange(int startColor, int endColor, ColorCallback callback) {
ValueAnimator colorAnimator = ValueAnimator.ofArgb(startColor, endColor);
colorAnimator.setDuration(animationDuration); // Use the dynamic duration
colorAnimator.setInterpolator(interpolator); // Use the dynamic interpolator
colorAnimator.addUpdateListener(animation -> {
int animatedColor = (int) animation.getAnimatedValue();
callback.onColorExtracted(animatedColor); // Provide the smooth interpolated color
});
colorAnimator.start();
}
}
lang-java