android gpu image rendering issue <p>I'm currently building an android app to apply filter on a bmp. I'm using the gpuimage lib. How it's done is that the bmp is show in a ListView which contain 8 filters. When scrolling down/up, we request the filtering of the bmp (b&amp;w, sepia...). As the rendering take times, I display in my listview the original bmp and it's replace by the filtered image once done</p> <p>Here is how the activity do it.</p> <pre><code>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&lt;?&gt; 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); } }); } }); } </code></pre> <p>The mCameraImageFiltersAdapter is defined as :</p> <pre><code> 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(); } </code></pre> <p>The CameraFilterFactoy is just a easy to use class to access to the GPUImage</p> <pre><code> 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); } } </code></pre> <p>This code is working fine in the List view.</p> <p>Once I click on a picture from the ListView, I get his position, stop Executor from the adapter and ask to the FilterFactory for a rendering.</p> <p>If In the listview I wait that all the preview list image are showing the filter rendering, and then I click, the filter is correctly applied on the original bmp.</p> <p>In case, I'm scrolling quickly down and the GPU is in progress to render the preview iamge and then click, the original bmp is not filtered. I have check that in both case, when I click the list view give the right filter position and that the case. It seems that if a rendering is in progress, I'm not able to cancel and ask for a new one.</p> <p>Any idea why ? Any idea if I can cancel the current GPU rendering and start a new one. ?</p> <p>Thanks</p>