/* == This file is part of Tomahawk Player - <http://tomahawk-player.org> === * * Copyright 2016, Enno Gottschalk <mrmaffen@googlemail.com> * * Tomahawk is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Tomahawk is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Tomahawk. If not, see <http://www.gnu.org/licenses/>. */ package org.tomahawk.libtomahawk.utils; import com.squareup.picasso.Callback; import com.squareup.picasso.Picasso; import com.squareup.picasso.RequestCreator; import com.squareup.picasso.Target; import org.tomahawk.libtomahawk.collection.Image; import org.tomahawk.libtomahawk.infosystem.User; import org.tomahawk.tomahawk_android.R; import org.tomahawk.tomahawk_android.TomahawkApp; import org.tomahawk.tomahawk_android.utils.BlurTransformation; import org.tomahawk.tomahawk_android.utils.ColorTintTransformation; import org.tomahawk.tomahawk_android.utils.CropCircleTransformation; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.widget.ImageView; import android.widget.TextView; public class ImageUtils { public static final String TAG = ImageUtils.class.getSimpleName(); /** * Load a {@link android.graphics.Bitmap} asynchronously * * @param context the context needed for fetching resources * @param imageView the {@link ImageView}, which will be used to show the {@link * android.graphics.Bitmap} * @param image the path to load the image from * @param width the width in density independent pixels to scale the image down to */ public static void loadImageIntoImageView(Context context, ImageView imageView, Image image, int width, boolean isArtistImage) { loadImageIntoImageView(context, imageView, image, width, true, isArtistImage); } /** * Load a {@link android.graphics.Bitmap} asynchronously * * @param context the context needed for fetching resources * @param imageView the {@link ImageView}, which will be used to show the {@link * android.graphics.Bitmap} * @param image the path to load the image from * @param width the width in density independent pixels to scale the image down to */ public static void loadBlurredImageIntoImageView(Context context, ImageView imageView, Image image, int width, int placeHolderResId) { loadBlurredImageIntoImageView(context, imageView, image, width, placeHolderResId, null); } /** * Load a {@link android.graphics.Bitmap} asynchronously * * @param context the context needed for fetching resources * @param imageView the {@link ImageView}, which will be used to show the {@link * android.graphics.Bitmap} * @param image the path to load the image from * @param width the width in density independent pixels to scale the image down to */ public static void loadBlurredImageIntoImageView(Context context, ImageView imageView, Image image, int width, int placeHolderResId, Callback callback) { RequestCreator creator; if (image != null && !TextUtils.isEmpty(image.getImagePath())) { String imagePath = buildImagePath(image, width); creator = Picasso.with(context) .load(ImageUtils.preparePathForPicasso(imagePath)) .resize(width, width) .transform(new BlurTransformation(context, 16)); } else { creator = Picasso.with(context).load(placeHolderResId); } if (placeHolderResId > 0) { creator.error(placeHolderResId); } if (callback != null) { creator.noFade(); } creator.into(imageView, callback); } /** * Load a {@link android.graphics.Bitmap} asynchronously * * @param context the context needed for fetching resources * @param imageView the {@link ImageView}, which will be used to show the {@link * android.graphics.Bitmap} * @param image the path to load the image from * @param width the width in pixels to scale the image down to */ public static void loadImageIntoImageView(Context context, ImageView imageView, Image image, int width, boolean fit, boolean isArtistImage) { int placeHolder = isArtistImage ? R.drawable.artist_placeholder : R.drawable.album_placeholder; if (image != null && !TextUtils.isEmpty(image.getImagePath())) { String imagePath = buildImagePath(image, width); RequestCreator creator = Picasso.with(context).load( ImageUtils.preparePathForPicasso(imagePath)) .placeholder(placeHolder) .error(placeHolder); if (fit) { creator.resize(width, width); } creator.into(imageView); } else { RequestCreator creator = Picasso.with(context).load(placeHolder) .placeholder(placeHolder) .error(placeHolder); if (fit) { creator.resize(width, width); } creator.into(imageView); } } /** * Load a circle-shaped {@link android.graphics.Bitmap} asynchronously * * @param context the context needed for fetching resources * @param imageView the {@link ImageView}, which will be used to show the {@link * android.graphics.Bitmap} * @param user the user of which to load the data into the views * @param width the width in pixels to scale the image down to * @param textView the textview which is being used to display the first letter of the user's * name in the placeholder image */ public static void loadUserImageIntoImageView(Context context, ImageView imageView, User user, int width, TextView textView) { int placeHolder = R.drawable.circle_black; if (user.getImage() != null && !TextUtils.isEmpty(user.getImage().getImagePath())) { textView.setVisibility(View.GONE); String imagePath = buildImagePath(user.getImage(), width); Picasso.with(context).load(ImageUtils.preparePathForPicasso(imagePath)) .transform(new CropCircleTransformation()) .placeholder(placeHolder) .error(placeHolder) .fit() .into(imageView); } else { textView.setVisibility(View.VISIBLE); textView.setText(user.getName().substring(0, 1).toUpperCase()); Picasso.with(context).load(placeHolder) .placeholder(placeHolder) .error(placeHolder) .fit() .into(imageView); } } /** * Load a {@link android.graphics.Bitmap} asynchronously * * @param context the context needed for fetching resources * @param imageView the {@link ImageView}, which will be used to show the {@link * android.graphics.Bitmap} * @param path the path to the image */ public static void loadDrawableIntoImageView(Context context, ImageView imageView, String path) { loadDrawableIntoImageView(context, imageView, path, 0); } /** * Load a {@link android.graphics.Bitmap} asynchronously * * @param context the context needed for fetching resources * @param imageView the {@link ImageView}, which will be used to show the {@link * android.graphics.Bitmap} * @param path the path to the image * @param colorResId the color with which to tint the imageview drawable */ public static void loadDrawableIntoImageView(Context context, ImageView imageView, String path, int colorResId) { RequestCreator creator = Picasso.with(context).load(path); if (colorResId > 0) { creator.transform(new ColorTintTransformation(colorResId)); } creator.error(R.drawable.ic_alert_error).into(imageView); } /** * Load a {@link android.graphics.Bitmap} asynchronously * * @param context the context needed for fetching resources * @param view the {@link View}, which will be used to show the {@link * android.graphics.Bitmap} in its background * @param path the path to the image * @param colorResId the color with which to tint the imageview drawable */ public static void loadDrawableIntoView(final Context context, final View view, final String path, int colorResId) { RequestCreator creator = Picasso.with(context).load(path); if (colorResId > 0) { creator.transform(new ColorTintTransformation(colorResId)); } Target target = new Target() { @Override public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) { view.setBackgroundDrawable(new BitmapDrawable(context.getResources(), bitmap)); } @Override public void onBitmapFailed(Drawable errorDrawable) { Log.d(TAG, "loadDrawableIntoView onBitmapFailed for path: " + path); } @Override public void onPrepareLoad(Drawable placeHolderDrawable) { } }; view.setTag(target); creator.error(R.drawable.ic_alert_error).into(target); } /** * Load a {@link Drawable} asynchronously (convenience method) * * @param context the context needed for fetching resources * @param imageView the {@link ImageView}, which will be used to show the {@link Drawable} * @param drawableResId the resource id of the drawable to load into the imageview */ public static void loadDrawableIntoImageView(Context context, ImageView imageView, int drawableResId) { loadDrawableIntoImageView(context, imageView, drawableResId, 0); } /** * Load a {@link Drawable} asynchronously * * @param context the context needed for fetching resources * @param imageView the {@link ImageView}, which will be used to show the {@link Drawable} * @param drawableResId the resource id of the drawable to load into the imageview * @param colorResId the color with which to tint the imageview drawable */ public static void loadDrawableIntoImageView(Context context, ImageView imageView, int drawableResId, int colorResId) { RequestCreator creator = Picasso.with(context).load(drawableResId); if (colorResId > 0) { creator.transform(new ColorTintTransformation(colorResId)); } creator.error(R.drawable.ic_alert_error).into(imageView); } /** * Load a {@link android.graphics.Bitmap} asynchronously * * @param context the context needed for fetching resources * @param image the path to load the image from * @param target the Target which the loaded image will be pushed to * @param width the width in pixels to scale the image down to */ public static void loadImageIntoBitmap(Context context, Image image, Target target, int width, boolean isArtistImage) { int placeHolder = isArtistImage ? R.drawable.artist_placeholder : R.drawable.album_placeholder; if (image != null && !TextUtils.isEmpty(image.getImagePath())) { String imagePath = buildImagePath(image, width); Picasso.with(context).load(ImageUtils.preparePathForPicasso(imagePath)) .resize(width, width) .into(target); } else { Picasso.with(context).load(placeHolder) .resize(width, width) .into(target); } } public static String preparePathForPicasso(String path) { if (TextUtils.isEmpty(path) || path.contains("https://") || path.contains("http://")) { return path; } return path.startsWith("file:") ? path : "file:" + path; } private static String buildImagePath(Image image, int width) { if (image.isHatchetImage()) { int imageSize = Math.min(image.getHeight(), image.getWidth()); int actualWidth; if (NetworkUtils.isWifiAvailable()) { actualWidth = Math.min(imageSize, width); } else { actualWidth = Math.min(imageSize, width * 2 / 3); } return image.getImagePath() + "?width=" + actualWidth + "&height=" + actualWidth; } return image.getImagePath(); } @SuppressLint("NewApi") public static void setTint(final Drawable drawable, final int colorResId) { int color = TomahawkApp.getContext().getResources().getColor(colorResId); drawable.setColorFilter(color, android.graphics.PorterDuff.Mode.SRC_ATOP); } @SuppressLint("NewApi") public static void clearTint(final Drawable drawable) { drawable.clearColorFilter(); } public static Bitmap drawableToBitmap(Drawable drawable) { if (drawable instanceof BitmapDrawable) { return ((BitmapDrawable) drawable).getBitmap(); } Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); return bitmap; } }