В настоящее время я создаю приложение для Android, чтобы применить фильтр на BMP. Я использую gpuimage lib. Как это делается, BMP отображается в ListView, который содержит 8 фильтров. При прокрутке вниз/вверх мы запрашиваем фильтрацию bmp (b & w, сепия ...). Поскольку рендеринг занимает время, я показываю в своем списке вид оригинала bmp и его заменяет отфильтрованное изображение, сделанное один разandroid gpu image rendering issue
Вот как это делается.
private ListView mFiltersView;
private void FiltersPreview(final Bitmap mBmp) {
boolean mPreview = true;
mPreviewBitmap = resizeBitmap(mBmp);
mCameraImageFiltersAdapter = new CameraImageFiltersAdapter(this, mPreviewBitmap, mPreview);
mFiltersView.setAdapter(mCameraImageFiltersAdapter);
mFiltersView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
mCameraImageFiltersAdapter.cancel();
mFiltersView.cancelPendingInputEvents();
mFiltersView.setAdapter(null);
final CameraFiltersFactory effect = (CameraFiltersFactory) v.findViewById(R.id.filteredImage).getTag();
BufferAnimationDrawable Loading = new BufferAnimationDrawable(getBaseContext());
Loading.setPrimaryColor(0xfffb633e);
LoadingScreen.setImageDrawable(Loading);
LoadingScreen.setVisibility(View.VISIBLE);
mFiltersView.setVisibility(View.GONE);
getActionBar().hide();
if(mBmp == null) Log.d(TAG,"mBitmap is null");
effect.save(mBmp, position, new GPUImage.OnPictureSavedListener() {
@Override
public void onPictureSaved(Uri uri) {
final Intent previewIntent = new Intent(FiltersSelectionActivity.this, PicturePreviewActivity.class);
previewIntent.setData(uri);
previewIntent.setAction(mActionTypes.toString());
previewIntent.putExtra("Type", "Filtered");
startActivityForResult(previewIntent, 0);
}
});
}
});
}
В mCameraImageFiltersAdapter определяется как:
public CameraImageFiltersAdapter(/*Activity activity, */Context c, Bitmap current, boolean isPreview) {
mContext = c;
mPreview = isPreview;
mCurrentBitmap = current;
mFilterIds = CAMERA_IMAGE_FILTERS == null
|| CAMERA_IMAGE_FILTERS.length == 0 ?
mFilterIds : CAMERA_IMAGE_FILTERS;
mFakeBitmap = mCurrentBitmap;
mFakeBitmap.setDensity(0);
mExecutorService = Executors.newFixedThreadPool(5);
}
private final Handler handler = new Handler();// handler to display images
public int getCount() { return mFilterIds.length; }
public long getItemId(int position) { return 0; }
public Object getItem(int position) { return null; }
@Override public int getViewTypeCount() { return mFilterIds.length; }
@Override public int getItemViewType(int position) { return position; }
final int stub_id = R.drawable.filter_preview_stub;
public ImageView filteredImage = null;
public TextView filteredText = null;
@SuppressLint("InflateParams")
public View getView(int position, View convertView, ViewGroup parent) {
mPosition = position;
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(R.layout.list_item_filter, null);
filteredImage = (ImageView) convertView.findViewById(R.id.filteredImage);
filteredImage.setImageBitmap(mFakeBitmap);
filteredText = (TextView) convertView.findViewById(R.id.textview);
queueFiltered(filteredImage, mPosition, filteredText);
}
return convertView;
}
private void queueFiltered(final ImageView view, final int position, final TextView text) {
final CameraFiltersFactory holder = new CameraFiltersFactory(mContext, view, text);
if(holder != null)
mExecutorService.submit(new FilterLoader(holder, position));
}
public void cancel() {
if(mExecutorService != null) mExecutorService.shutdownNow();
}
CameraFilterFactoy только простой в использовании класс для доступа к GPUImage
public class CameraFiltersFactory {
private static final String TAG = CameraFiltersFactory.class.getSimpleName();
private final ImageView mImageView;
private final GPUImage mCameraImage;
private Bitmap mFilteredBitmap;
private int mCurrentEffect;
private Context mContext;
private Activity mActivity = null;
private TextView mFiltersText;
public CameraFiltersFactory(Context c, ImageView filteredImage, TextView filteredText) {
mImageView = filteredImage;
mImageView.setTag(this);
mContext = c;
mCameraImage = new GPUImage(mContext);
if(filteredText != null) {
mFiltersText = filteredText;
mFiltersText.setVisibility(View.VISIBLE);
}
if(mImageView != null) mActivity = (Activity) mContext;
}
public void generateFilteredBitmap(Bitmap bmp, int filtertype, boolean isPreview) {
mCurrentEffect = filtertype;
switch (mCurrentEffect) {
case R.id.blackandwhite:
mCameraImage.setFilter(new GPUImagePlusGrayscaleFilter(isPreview));
break;
case R.id.cool:
mCameraImage.setFilter(new GPUImagePlusCoolFilter(isPreview));
break;
case R.id.cool2:
mCameraImage.setFilter(new GPUImagePlusCool2Filter(isPreview));
break;
case R.id.faded:
mCameraImage.setFilter(new GPUImagePlusFadedFilter(mContext, isPreview));
break;
case R.id.hipster:
mCameraImage.setFilter(new GPUImagePlusHipsterFilter(mContext, isPreview));
break;
case R.id.sepia:
mCameraImage.setFilter(new GPUImagePlusSepiaFilter(isPreview));
break;
case R.id.vivid:
mCameraImage.setFilter(new GPUImagePlusVividFilter(isPreview));
break;
case R.id.warm:
mCameraImage.setFilter(new GPUImagePlusWarmFilter(mContext, isPreview));
break;
default:
Log.d("NONE", "None FAIT CHIER");
break;
}
mCameraImage.deleteImage();
mCameraImage.setImage(bmp);
mFilteredBitmap = mCameraImage.getBitmapWithFilterApplied();
}
@SuppressLint("SimpleDateFormat")
public void save(Bitmap bitmap, int filter_id, GPUImage.OnPictureSavedListener ofsl) {
Log.d("NONE", "Save request with filter: "+filter_id);
generateFilteredBitmap(bitmap, filter_id, false);
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String fileName = timeStamp + ".jpg";
mCameraImage.saveToPictures(mFilteredBitmap, CameraSettings.CAMERA_ROLL_FOLDER, fileName, true, ofsl);
}
}
Этот код работает отлично в виде списка ,
Как только я нажимаю на изображение из списка ListView, я получаю его положение, останавливаю Executor от адаптера и спрашиваю FilterFactory для рендеринга.
Если в списке я ожидаю, что все изображение предварительного просмотра покажет рендеринг фильтра, а затем нажмите кнопку, фильтр будет правильно применен к исходному BMP.
В случае, если я быстро прокручиваюсь, и графический процессор находится в процессе рендеринга iamge, а затем щелкните, исходный BMP не фильтруется. У меня есть проверка, что в обоих случаях, когда я нажимаю на представление списка, дайте правильную позицию фильтра и этот случай. Кажется, что если выполняется рендеринг, я не могу отменить и попросить новый.
Любая идея, почему? Любая идея, если я могу отменить текущий рендеринг графического процессора и запустить новый. ?
Благодаря