2015-12-22 8 views
0

В настоящее время я создаю приложение для 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 не фильтруется. У меня есть проверка, что в обоих случаях, когда я нажимаю на представление списка, дайте правильную позицию фильтра и этот случай. Кажется, что если выполняется рендеринг, я не могу отменить и попросить новый.

Любая идея, почему? Любая идея, если я могу отменить текущий рендеринг графического процессора и запустить новый. ?

Благодаря

ответ

0

Использование gpuImage.deleteImage(); метод в вашем классе адаптера после получения растрового изображения из изображения gpu.

Прежде чем настроить изображение на GPUImage, создайте миниатюру изображения. Таким образом, он будет загружаться быстро.

GPUImaage gpuImage=new GPUImage(context); 
gpuImage.setImage(your image); 
gpuImage.setFilter(choose your filter); 
gpuImage.requestRender(); 

imageView.setImageBitmap(gpuImage.getBitmapWithFilterApplied()); 

gpuImage.deleteImage();