Fill empty space with blurred cover art

This commit is contained in:
Andrew Rabert 2018-03-28 01:35:49 -04:00
parent be1dc7d8c9
commit b1d0e91b8a
4 changed files with 85 additions and 27 deletions

View File

@ -87,6 +87,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
private TextView emptyTextView;
private TextView songTitleTextView;
private ImageView albumArtImageView;
private ImageView albumArtBackgroundView;
private RecyclerView playlistView;
private TextView positionTextView;
private TextView durationTextView;
@ -151,6 +152,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
emptyTextView = rootView.findViewById(R.id.download_empty);
songTitleTextView = rootView.findViewById(R.id.download_song_title);
albumArtImageView = rootView.findViewById(R.id.download_album_art_image);
albumArtBackgroundView = rootView.findViewById(R.id.download_album_art_background);
positionTextView = rootView.findViewById(R.id.download_position);
durationTextView = rootView.findViewById(R.id.download_duration);
statusTextView = rootView.findViewById(R.id.download_status);
@ -516,6 +518,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
}
if (currentPlaying == null && downloadService != null && currentPlaying == downloadService.getCurrentPlaying()) {
getImageLoader().loadBlurImage(albumArtBackgroundView, null, true, false);
getImageLoader().loadImage(albumArtImageView, null, true, false);
}
@ -804,6 +807,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
if (currentPlaying != null) {
Entry song = currentPlaying.getSong();
songTitleTextView.setText(song.getTitle());
getImageLoader().loadBlurImage(albumArtBackgroundView, song, true, true);
getImageLoader().loadImage(albumArtImageView, song, true, true);
DownloadService downloadService = getDownloadService();
@ -814,6 +818,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
}
} else {
songTitleTextView.setText(null);
getImageLoader().loadBlurImage(albumArtBackgroundView, null, true, false);
getImageLoader().loadImage(albumArtImageView, null, true, false);
setSubtitle(null);
}
@ -939,6 +944,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
@Override
public void onMetadataUpdate(Entry song, int fieldChange) {
if (song != null && albumArtImageView != null && fieldChange == DownloadService.METADATA_UPDATED_COVER_ART) {
getImageLoader().loadBlurImage(albumArtBackgroundView, song, true, true);
getImageLoader().loadImage(albumArtImageView, song, true, true);
}
}

View File

@ -0,0 +1,32 @@
package net.nullsum.audinaut.util;
import android.content.Context;
import android.graphics.Bitmap;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicBlur;
class BlurBuilder {
private static final float BITMAP_SCALE = 0.4f;
private static final float BLUR_RADIUS = 25f;
public static Bitmap blur(Context context, Bitmap image) {
int width = Math.round(image.getWidth() * BITMAP_SCALE);
int height = Math.round(image.getHeight() * BITMAP_SCALE);
Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height, false);
Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);
RenderScript rs = RenderScript.create(context);
ScriptIntrinsicBlur theIntrinsic = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);
Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);
theIntrinsic.setRadius(BLUR_RADIUS);
theIntrinsic.setInput(tmpIn);
theIntrinsic.forEach(tmpOut);
tmpOut.copyTo(outputBitmap);
return outputBitmap;
}
}

View File

@ -209,10 +209,19 @@ public class ImageLoader {
public SilentBackgroundTask loadImage(View view, MusicDirectory.Entry entry, boolean large, boolean crossfade) {
int size = large ? imageSizeLarge : imageSizeDefault;
return loadImage(view, entry, large, size, crossfade);
return loadImage(view, entry, large, size, crossfade, false);
}
public SilentBackgroundTask loadImage(View view, MusicDirectory.Entry entry, boolean large, int size, boolean crossfade) {
public void loadBlurImage(View view, MusicDirectory.Entry entry, boolean large, boolean crossfade) {
int size = large ? imageSizeLarge : imageSizeDefault;
loadImage(view, entry, large, size, crossfade, true);
}
public void loadImage(View view, MusicDirectory.Entry entry, boolean large, int size, boolean crossfade) {
loadImage(view, entry, large, size, crossfade, false);
}
private SilentBackgroundTask loadImage(View view, MusicDirectory.Entry entry, boolean large, int size, boolean crossfade, boolean blur) {
// If we know this a artist, try to load artist info instead
if (entry != null && !entry.isAlbum() && !Util.isOffline(context)) {
SilentBackgroundTask task = new ArtistImageTask(view.getContext(), entry, size, large, view, crossfade);
@ -229,12 +238,18 @@ public class ImageLoader {
Bitmap bitmap;
if (entry == null || entry.getCoverArt() == null) {
bitmap = getUnknownImage(entry, size);
if (blur) {
bitmap = BlurBuilder.blur(context, bitmap);
}
setImage(view, Util.createDrawableFromBitmap(context, bitmap), crossfade);
return null;
}
bitmap = cache.get(getKey(entry.getCoverArt(), size));
if (bitmap != null && !bitmap.isRecycled()) {
if (blur) {
bitmap = BlurBuilder.blur(context, bitmap);
}
final Drawable drawable = Util.createDrawableFromBitmap(this.context, bitmap);
setImage(view, drawable, crossfade);
if (large) {
@ -246,7 +261,7 @@ public class ImageLoader {
if (!large) {
setImage(view, null, false);
}
ImageTask task = new ViewImageTask(view.getContext(), entry, size, large, view, crossfade);
ImageTask task = new ViewImageTask(view.getContext(), entry, size, large, view, crossfade, blur);
task.execute();
return task;
}
@ -322,14 +337,16 @@ public class ImageLoader {
private final Context mContext;
private final int mSize;
private final boolean mIsNowPlaying;
private final boolean mBlur;
Drawable mDrawable;
public ImageTask(Context context, MusicDirectory.Entry entry, int size, boolean isNowPlaying) {
public ImageTask(Context context, MusicDirectory.Entry entry, int size, boolean isNowPlaying, boolean blur) {
super(context);
mContext = context;
mEntry = entry;
mSize = size;
mIsNowPlaying = isNowPlaying;
mBlur = blur;
}
@Override
@ -348,7 +365,9 @@ public class ImageLoader {
} else {
bitmap = getUnknownImage(mEntry, mSize);
}
if (mBlur) {
bitmap = BlurBuilder.blur(context, bitmap);
}
mDrawable = Util.createDrawableFromBitmap(mContext, bitmap);
} catch (Throwable x) {
Log.e(TAG, "Failed to download album art.", x);
@ -363,8 +382,8 @@ public class ImageLoader {
final boolean mCrossfade;
private final View mView;
public ViewImageTask(Context context, MusicDirectory.Entry entry, int size, boolean isNowPlaying, View view, boolean crossfade) {
super(context, entry, size, isNowPlaying);
public ViewImageTask(Context context, MusicDirectory.Entry entry, int size, boolean isNowPlaying, View view, boolean crossfade, boolean blur) {
super(context, entry, size, isNowPlaying, blur);
mView = view;
mCrossfade = crossfade;
@ -409,7 +428,7 @@ public class ImageLoader {
}
if (mEntry != null && mEntry.getCoverArt() != null) {
subTask = new ViewImageTask(mContext, mEntry, mSize, mIsNowPlaying, mView, mCrossfade);
subTask = new ViewImageTask(mContext, mEntry, mSize, mIsNowPlaying, mView, mCrossfade, false);
} else {
// If entry is null as well, we need to just set as a blank image
Bitmap bitmap = getUnknownImage(mEntry, mSize);

View File

@ -20,33 +20,34 @@
android:background="@android:color/transparent"
android:orientation="vertical">
<FrameLayout
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<FrameLayout
<net.nullsum.audinaut.view.RecyclingImageView
android:id="@+id/download_album_art_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:scaleType="centerCrop" />
<net.nullsum.audinaut.view.RecyclingImageView
android:id="@+id/download_album_art_image"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:scaleType="fitCenter" />
<net.nullsum.audinaut.view.RecyclingImageView
android:id="@+id/download_album_art_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitCenter" />
<LinearLayout
android:id="@+id/download_overlay_buttons"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom"
android:background="@color/overlayColor"
android:gravity="center"
android:orientation="horizontal"
android:visibility="invisible" />
</FrameLayout>
</FrameLayout>
</RelativeLayout>
<LinearLayout
android:id="@+id/download_overlay_buttons"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom"
android:background="@color/overlayColor"
android:gravity="center"
android:orientation="horizontal"
android:visibility="invisible" />
<TextView
android:id="@+id/download_status"