/*
* Copyright (C) 2014 Andrew Reitz
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.andrewreitz.encryptedcamera.ui.adapter;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.os.AsyncTask;
import android.support.annotation.NonNull;
import android.support.v4.util.LruCache;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import butterknife.ButterKnife;
import com.andrewreitz.encryptedcamera.R;
import com.andrewreitz.encryptedcamera.image.ImageRotation;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import timber.log.Timber;
public class GalleryAdapter extends BindableAdapter<File> {
private final int viewSize;
private final LruCache<String, Bitmap> cache;
private final List<File> images;
public GalleryAdapter(@NonNull Context context, @NonNull List<File> images,
@NonNull LruCache<String, Bitmap> cache) {
super(context);
this.viewSize = context.getResources().getDimensionPixelSize(R.dimen.gridview_image);
this.images = images;
this.cache = cache;
}
@Override public int getCount() {
return images.size();
}
@Override public File getItem(int position) {
return images.get(position);
}
@Override public long getItemId(int position) {
return position;
}
@Override public View newView(LayoutInflater inflater, int position, ViewGroup container) {
return inflater.inflate(R.layout.gallery_item, container, false);
}
@Override public void bindView(File file, int position, View view) {
ImageView imageView = ButterKnife.findById(view, R.id.gallery_imageview);
// Cancel any pending thumbnail task, since this view is now bound
// to new thumbnail
final ThumbnailAsyncTask oldTask = (ThumbnailAsyncTask) view.getTag();
if (oldTask != null) {
oldTask.cancel(false);
}
// Cache enabled, try looking for cache hit
final Bitmap cachedResult = cache.get(file.getName());
if (cachedResult != null) {
imageView.setImageBitmap(cachedResult);
return;
}
int rotation = 0;
try {
rotation = ImageRotation.getRotation(file);
} catch (IOException e) {
Timber.e(e, "Error using exif data");
}
// If we arrived here, either cache is disabled or cache miss, so we
// need to kick task to load manually
final ThumbnailAsyncTask task = new ThumbnailAsyncTask(imageView, viewSize, cache, rotation);
imageView.setImageBitmap(null);
task.execute(file);
}
private static class ThumbnailAsyncTask extends AsyncTask<File, Void, Bitmap> {
private final static Matrix matrix = new Matrix();
private final ImageView target;
private final int viewSize;
private final int rotation;
private final LruCache<String, Bitmap> cache;
ThumbnailAsyncTask(ImageView target, int viewSize, LruCache<String, Bitmap> cache,
int rotation) {
this.target = target;
this.viewSize = viewSize;
this.cache = cache;
this.rotation = rotation;
}
@Override protected void onPreExecute() {
target.setTag(this);
}
@Override protected Bitmap doInBackground(File... params) {
Bitmap result = null;
File file = params[0];
try {
FileInputStream fis = new FileInputStream(file.getAbsolutePath());
Bitmap imageBitmap = BitmapFactory.decodeStream(fis);
final int width = imageBitmap.getWidth();
final int height = imageBitmap.getHeight();
final float sx = viewSize / (float) width;
final float sy = viewSize / (float) height;
matrix.setScale(sx, sy);
matrix.postRotate(rotation);
result = Bitmap.createBitmap(imageBitmap, 0, 0, width, height, matrix, false);
cache.put(file.getName(), result);
} catch (Exception e) {
Timber.e(e, "Error resizing image");
}
return result;
}
@Override protected void onPostExecute(Bitmap result) {
if (target.getTag() == this) {
target.setImageBitmap(result);
target.setTag(null);
}
}
}
}