Increased album cover quality and loading time when loading them directly from the song files.
This commit is contained in:
parent
92159797f5
commit
1350454484
5 changed files with 36 additions and 101 deletions
|
|
@ -1,7 +1,6 @@
|
||||||
package com.kabouzeid.gramophone.imageloader;
|
package com.kabouzeid.gramophone.imageloader;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
|
@ -9,14 +8,15 @@ import com.kabouzeid.gramophone.lastfm.rest.LastFMRestClient;
|
||||||
import com.kabouzeid.gramophone.lastfm.rest.model.artistinfo.ArtistInfo;
|
import com.kabouzeid.gramophone.lastfm.rest.model.artistinfo.ArtistInfo;
|
||||||
import com.kabouzeid.gramophone.loader.AlbumSongLoader;
|
import com.kabouzeid.gramophone.loader.AlbumSongLoader;
|
||||||
import com.kabouzeid.gramophone.model.Song;
|
import com.kabouzeid.gramophone.model.Song;
|
||||||
import com.kabouzeid.gramophone.util.ImageUtil;
|
|
||||||
import com.kabouzeid.gramophone.util.LastFMUtil;
|
import com.kabouzeid.gramophone.util.LastFMUtil;
|
||||||
import com.kabouzeid.gramophone.util.MusicUtil;
|
import com.kabouzeid.gramophone.util.MusicUtil;
|
||||||
import com.kabouzeid.gramophone.util.PreferenceUtil;
|
import com.kabouzeid.gramophone.util.PreferenceUtil;
|
||||||
import com.nostra13.universalimageloader.core.download.BaseImageDownloader;
|
import com.nostra13.universalimageloader.core.download.BaseImageDownloader;
|
||||||
|
|
||||||
|
import org.jaudiotagger.audio.AudioFile;
|
||||||
|
import org.jaudiotagger.audio.AudioFileIO;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
@ -73,12 +73,16 @@ public class PhonographImageDownloader extends BaseImageDownloader {
|
||||||
if (PreferenceUtil.getInstance(context).ignoreMediaStoreArtwork()) {
|
if (PreferenceUtil.getInstance(context).ignoreMediaStoreArtwork()) {
|
||||||
ArrayList<Song> songs = AlbumSongLoader.getAlbumSongList(context, albumId);
|
ArrayList<Song> songs = AlbumSongLoader.getAlbumSongList(context, albumId);
|
||||||
for (Song song : songs) {
|
for (Song song : songs) {
|
||||||
Bitmap bitmap = ImageUtil.getEmbeddedSongArt(new File(song.data), context);
|
try {
|
||||||
if (bitmap != null) {
|
AudioFile audioFile = AudioFileIO.read(new File(song.data));
|
||||||
return getBitmapInputStream(bitmap);
|
byte[] albumCover = audioFile.getTagOrCreateAndSetDefault().getFirstArtwork().getBinaryData();
|
||||||
|
if (albumCover != null) {
|
||||||
|
return new ByteArrayInputStream(albumCover);
|
||||||
|
}
|
||||||
|
} catch (@NonNull Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
return getMediaProviderAlbumArtInputStream(albumId);
|
return getMediaProviderAlbumArtInputStream(albumId);
|
||||||
}
|
}
|
||||||
|
|
@ -88,25 +92,22 @@ public class PhonographImageDownloader extends BaseImageDownloader {
|
||||||
String[] data = imageUri.substring(SCHEME_SONG.length()).split("#", 2);
|
String[] data = imageUri.substring(SCHEME_SONG.length()).split("#", 2);
|
||||||
|
|
||||||
if (PreferenceUtil.getInstance(context).ignoreMediaStoreArtwork()) {
|
if (PreferenceUtil.getInstance(context).ignoreMediaStoreArtwork()) {
|
||||||
Bitmap bitmap = ImageUtil.getEmbeddedSongArt(new File(data[1]), context);
|
try {
|
||||||
if (bitmap != null) {
|
AudioFile audioFile = AudioFileIO.read(new File(data[1]));
|
||||||
return getBitmapInputStream(bitmap);
|
byte[] albumCover = audioFile.getTagOrCreateAndSetDefault().getFirstArtwork().getBinaryData();
|
||||||
|
if (albumCover != null) {
|
||||||
|
return new ByteArrayInputStream(albumCover);
|
||||||
|
}
|
||||||
|
} catch (@NonNull Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int id = Integer.parseInt(data[0]);
|
int id = Integer.parseInt(data[0]);
|
||||||
return getMediaProviderAlbumArtInputStream(id);
|
return getMediaProviderAlbumArtInputStream(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@Nullable
|
||||||
private static ByteArrayInputStream getBitmapInputStream(@NonNull Bitmap bitmap) {
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
|
||||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
|
|
||||||
return new ByteArrayInputStream(bos.toByteArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private InputStream getMediaProviderAlbumArtInputStream(int albumId) throws
|
private InputStream getMediaProviderAlbumArtInputStream(int albumId) throws
|
||||||
FileNotFoundException {
|
FileNotFoundException {
|
||||||
return context.getContentResolver().openInputStream(MusicUtil.getAlbumArtUri(albumId));
|
return context.getContentResolver().openInputStream(MusicUtil.getAlbumArtUri(albumId));
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ import com.afollestad.materialdialogs.MaterialDialog;
|
||||||
import com.afollestad.materialdialogs.util.DialogUtils;
|
import com.afollestad.materialdialogs.util.DialogUtils;
|
||||||
import com.github.ksoichiro.android.observablescrollview.ObservableScrollView;
|
import com.github.ksoichiro.android.observablescrollview.ObservableScrollView;
|
||||||
import com.kabouzeid.gramophone.R;
|
import com.kabouzeid.gramophone.R;
|
||||||
import com.kabouzeid.gramophone.misc.LagTracker;
|
|
||||||
import com.kabouzeid.gramophone.misc.SimpleObservableScrollViewCallbacks;
|
import com.kabouzeid.gramophone.misc.SimpleObservableScrollViewCallbacks;
|
||||||
import com.kabouzeid.gramophone.ui.activities.base.AbsBaseActivity;
|
import com.kabouzeid.gramophone.ui.activities.base.AbsBaseActivity;
|
||||||
import com.kabouzeid.gramophone.util.ColorUtil;
|
import com.kabouzeid.gramophone.util.ColorUtil;
|
||||||
|
|
@ -99,9 +98,7 @@ public abstract class AbsTagEditorActivity extends AbsBaseActivity {
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
LagTracker.get().start("setContentView");
|
|
||||||
setContentView(getContentViewLayout());
|
setContentView(getContentViewLayout());
|
||||||
LagTracker.get().end("setContentView");
|
|
||||||
ButterKnife.bind(this);
|
ButterKnife.bind(this);
|
||||||
|
|
||||||
getIntentExtras();
|
getIntentExtras();
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package com.kabouzeid.gramophone.ui.activities.tageditor;
|
package com.kabouzeid.gramophone.ui.activities.tageditor;
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Point;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
|
@ -24,7 +23,6 @@ import com.kabouzeid.gramophone.util.Util;
|
||||||
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
||||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||||
import com.nostra13.universalimageloader.core.assist.FailReason;
|
import com.nostra13.universalimageloader.core.assist.FailReason;
|
||||||
import com.nostra13.universalimageloader.core.assist.ImageSize;
|
|
||||||
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
|
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
|
||||||
import com.nostra13.universalimageloader.core.process.BitmapProcessor;
|
import com.nostra13.universalimageloader.core.process.BitmapProcessor;
|
||||||
|
|
||||||
|
|
@ -107,15 +105,13 @@ public class AlbumTagEditorActivity extends AbsTagEditorActivity implements Text
|
||||||
@Override
|
@Override
|
||||||
public void success(@NonNull AlbumInfo albumInfo, Response response) {
|
public void success(@NonNull AlbumInfo albumInfo, Response response) {
|
||||||
if (albumInfo.getAlbum() != null) {
|
if (albumInfo.getAlbum() != null) {
|
||||||
Point size = Util.getScreenSize(AlbumTagEditorActivity.this);
|
final int smallerScreenSize = Util.getSmallerScreenSize(AlbumTagEditorActivity.this);
|
||||||
final int screenWidth = Math.min(size.x, size.y);
|
|
||||||
ImageLoader.getInstance().loadImage(LastFMUtil.getLargestAlbumImageUrl(albumInfo.getAlbum().getImage()),
|
ImageLoader.getInstance().loadImage(LastFMUtil.getLargestAlbumImageUrl(albumInfo.getAlbum().getImage()),
|
||||||
new DisplayImageOptions.Builder()
|
new DisplayImageOptions.Builder()
|
||||||
.preProcessor(new BitmapProcessor() {
|
.preProcessor(new BitmapProcessor() {
|
||||||
@Override
|
@Override
|
||||||
public Bitmap process(Bitmap bitmap) {
|
public Bitmap process(Bitmap bitmap) {
|
||||||
//noinspection SuspiciousNameCombination
|
return ImageUtil.getResizedBitmap(bitmap, smallerScreenSize, smallerScreenSize, true);
|
||||||
return ImageUtil.getResizedBitmap(bitmap, screenWidth, screenWidth, true);
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.build(),
|
.build(),
|
||||||
|
|
@ -213,8 +209,16 @@ public class AlbumTagEditorActivity extends AbsTagEditorActivity implements Text
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void loadImageFromFile(@NonNull final Uri selectedFileUri) {
|
protected void loadImageFromFile(@NonNull final Uri selectedFileUri) {
|
||||||
|
final int smallerScreenSize = Util.getSmallerScreenSize(AlbumTagEditorActivity.this);
|
||||||
ImageLoader.getInstance().loadImage(selectedFileUri.toString(),
|
ImageLoader.getInstance().loadImage(selectedFileUri.toString(),
|
||||||
new ImageSize(500, 500),
|
new DisplayImageOptions.Builder()
|
||||||
|
.preProcessor(new BitmapProcessor() {
|
||||||
|
@Override
|
||||||
|
public Bitmap process(Bitmap bitmap) {
|
||||||
|
return ImageUtil.getResizedBitmap(bitmap, smallerScreenSize, smallerScreenSize, true);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.build(),
|
||||||
new SimpleImageLoadingListener() {
|
new SimpleImageLoadingListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
|
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,8 @@
|
||||||
package com.kabouzeid.gramophone.util;
|
package com.kabouzeid.gramophone.util;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
|
||||||
import android.graphics.Matrix;
|
import android.graphics.Matrix;
|
||||||
import android.graphics.Point;
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.jaudiotagger.audio.AudioFile;
|
|
||||||
import org.jaudiotagger.audio.AudioFileIO;
|
|
||||||
import org.jaudiotagger.audio.exceptions.CannotReadException;
|
|
||||||
import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException;
|
|
||||||
import org.jaudiotagger.audio.exceptions.ReadOnlyFileException;
|
|
||||||
import org.jaudiotagger.tag.TagException;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Karim Abou Zeid (kabouzeid)
|
* @author Karim Abou Zeid (kabouzeid)
|
||||||
|
|
@ -36,62 +22,4 @@ public class ImageUtil {
|
||||||
}
|
}
|
||||||
return resizedBitmap;
|
return resizedBitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public static Bitmap getEmbeddedSongArt(File songFile, @NonNull Context context) {
|
|
||||||
try {
|
|
||||||
AudioFile audioFile = AudioFileIO.read(songFile);
|
|
||||||
byte[] data = audioFile.getTag().getFirstArtwork().getBinaryData();
|
|
||||||
if (data != null) {
|
|
||||||
final BitmapFactory.Options options = new BitmapFactory.Options();
|
|
||||||
options.inPreferredConfig = Bitmap.Config.RGB_565;
|
|
||||||
options.inJustDecodeBounds = true;
|
|
||||||
BitmapFactory.decodeByteArray(data, 0, data.length, options);
|
|
||||||
// Calculate inSampleSize
|
|
||||||
options.inSampleSize = calculateInSampleSize(options, context);
|
|
||||||
// Decode bitmap with inSampleSize set
|
|
||||||
options.inJustDecodeBounds = false;
|
|
||||||
return BitmapFactory.decodeByteArray(data, 0, data.length, options);
|
|
||||||
}
|
|
||||||
} catch (@NonNull CannotReadException | TagException | IOException | ReadOnlyFileException | InvalidAudioFrameException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int calculateInSampleSize(@NonNull BitmapFactory.Options options, @NonNull Context context) {
|
|
||||||
|
|
||||||
// Raw height and width of image
|
|
||||||
final int height = options.outHeight;
|
|
||||||
final int width = options.outWidth;
|
|
||||||
int reqLength = Math.round(getSmallerScreenSize(context) * 1.5f); // absolute maximum size the album art will ever have
|
|
||||||
|
|
||||||
// setting reqWidth matching to desired 1:1 ratio and screen-size
|
|
||||||
if (width < height) {
|
|
||||||
reqLength = (height / width) * reqLength;
|
|
||||||
} else {
|
|
||||||
reqLength = (width / height) * reqLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
int inSampleSize = 1;
|
|
||||||
|
|
||||||
if (height > reqLength || width > reqLength) {
|
|
||||||
final int halfHeight = height / 2;
|
|
||||||
final int halfWidth = width / 2;
|
|
||||||
|
|
||||||
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
|
|
||||||
// height and width larger than the requested height and width.
|
|
||||||
while ((halfHeight / inSampleSize) > reqLength
|
|
||||||
&& (halfWidth / inSampleSize) > reqLength) {
|
|
||||||
inSampleSize *= 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return inSampleSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int getSmallerScreenSize(@NonNull Context c) {
|
|
||||||
Point size = Util.getScreenSize(c);
|
|
||||||
return Math.min(size.x, size.y);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,11 @@ public class Util {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int getSmallerScreenSize(@NonNull Context c) {
|
||||||
|
Point size = Util.getScreenSize(c);
|
||||||
|
return Math.min(size.x, size.y);
|
||||||
|
}
|
||||||
|
|
||||||
@TargetApi(19)
|
@TargetApi(19)
|
||||||
public static void setStatusBarTranslucent(@NonNull Window window) {
|
public static void setStatusBarTranslucent(@NonNull Window window) {
|
||||||
window.setFlags(
|
window.setFlags(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue