2017-07-18 10 views
9

Używam przesuwania, aby wyodrębnić bitmapę z pamięci podręcznej i zapisać ją w innym miejscu. Odpowiednia funkcja poniżej (oparta na tym post :) nie uruchamia ekstrakcji. W rzeczywistości linia dziennika "Log.d (TAG," O, aby rozpocząć ekstrakcję ");" poniżej nigdy się nie uruchamia.Ekstrakcja obrazu poślizgowego

Jakieś pomysły na pytanie, dlaczego prosta funkcja docelowa nigdy nie zostanie wywołana?

public byte[] extractImageFromCache(Context context, String pictureURL) { 

    byte[] byteArray = new byte[0]; 
    if (context != null && pictureURL != null && !pictureURL.isEmpty()) { 

     final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 

     Glide.with(context) 
      .load(pictureURL) 
      .asBitmap() 
      .toBytes() 
      .diskCacheStrategy(DiskCacheStrategy.SOURCE) // Load the original hires image 
      .into(new SimpleTarget<byte[]>() { 
       @Override public void onResourceReady(final byte[] resource, GlideAnimation<? super byte[]> glideAnimation) { 
        Log.d(TAG, "About to start extraction"); 
        new AsyncTask<Void, Void, Void>() { 
         @Override protected Void doInBackground(Void... params) { 
          Log.d(TAG, "Start extraction"); 
          try { 
           Log.d(TAG, "Image bytes len: " + resource.length); 
           byteArrayOutputStream.write(resource); 
           byteArrayOutputStream.flush(); 
          } catch (IOException e) { 
           e.printStackTrace(); 
           Log.i(TAG, "Unable to load image: " + pictureURL); 
           e.printStackTrace(); 
          } 
          return null; 
         } 
        }.execute(); 

       } 
      }); 
     Log.d(TAG, String.format("Got image bytes: %d for %s", byteArrayOutputStream.size(), pictureURL)); 
     return byteArrayOutputStream.toByteArray(); 
    } 
    return null; 
} 
+0

Czy możesz opublikować logcat? – azizbekian

+0

Gdzie nazywasz tę funkcję? – rom4ek

+0

Wzmianka o wersji Glide, próbowałem twojego kodu i działa idealnie w 'glide: 3.7.0' – Maddy

Odpowiedz

1

Po pierwsze, twój powrót jest nieważny, ponieważ Glide wykonuje żądanie w asynchronicznym wątku. Tak więc byteArrayOutputStream nigdy nie jest zapełniane w czasie przed powrotem funkcji. Oznacza to, że twoja funkcja zawsze zwraca pustą tablicę bajtów. Oznacza to również, że Twoje oświadczenie dziennika Log.d(TAG, String.format("Got image bytes: %d for %s", byteArrayOutputStream.size(), pictureURL)); będzie nieprawidłowe. Znając to, twój About to start extraction pojawi się po Got image bytes.... Konieczne będzie ponowne sformatowanie kodu w celu użycia wywołań zwrotnych w celu powiadomienia osoby dzwoniącej o funkcji, z której kod odczytał tablicę. Coś takiego:

public interface GlideByteLoadCallback { 
    void onBytesExtracted(byte[] bytes); 
    void onFail(String message); 
} 

public void extractImageFromCache(Context context, String pictureURL, GlideByteLoadCallback callback) { 

    if (context != null && pictureURL != null && !pictureURL.isEmpty()) { 

     final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 

     Glide.with(context) 
      .load(pictureURL) 
      .asBitmap() 
      .toBytes() 
      .diskCacheStrategy(DiskCacheStrategy.SOURCE) // Load the original hires image 
      .into(new SimpleTarget<byte[]>() { 
       @Override public void onResourceReady(final byte[] resource, GlideAnimation<? super byte[]> glideAnimation) { 
        Log.d(TAG, "About to start extraction"); 
        new AsyncTask<Void, Void, Void>() { 
         @Override protected Void doInBackground(Void... params) { 
          Log.d(TAG, "Start extraction"); 
          try { 
           Log.d(TAG, "Image bytes len: " + resource.length); 
           byteArrayOutputStream.write(resource); 

           byteArrayOutputStream.flush(); 
           if (callback != null) callback.onBytesExtracted(byteArrayOutputStream.toByteArray()); 
          } catch (IOException e) { 
           e.printStackTrace(); 
           Log.i(TAG, "Unable to load image: " + pictureURL); 
           e.printStackTrace(); 
           if (callback != null) callback.onFail("Extraction failed"); 
          } 
         } 
        }.execute(); 
       } 
      }); 
    } 
    if (callback != null) callback.onFail("Invalid url"); 
} 

następnie wywołać ją z:

extractImageFromCache(context, picture, new GlideByteLoadCallback() { 
       @Override 
       public void onFail(String message) { 
        // handle failure here 
       } 

       @Override 
       public void onBytesExtracted(byte[] bytes) { 
        // do stuff with bytes here 
       } 
      }); 
0

To jest to, co chciałbym robić.

Podczas korzystania z przesuwania umieść załadowany obraz w widoku obrazu.

z kodu, ustaw:

imageView = (ImageView) view.findViewById(R.id.image_view); 
imageViewProfile.setDrawingCacheEnabled(true); 
imageViewProfile.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH); 

następnie uzyskać bitmapy z tego widoku obrazu można użyć

imageView.getDrawingCache() //This returns a Bitmap 

Jedyną rzeczą, jaką należy martwić się o to, aby sprawdzić, czy Glide zakończeniu ładowania swoimi obraz czy nie - nie jestem pewien, jak to osiągnąć - ale spróbuj i oddaj głos, jeśli ci to pomoże.

2

Za pomocą obiektu SimpleTarget możemy łatwo uzyskać Bitmapę, którą próbujemy wyodrębnić z pamięci podręcznej lub sieci, ponieważ domyślnie poślizg szuka trafienia w pamięci podręcznej.

Modyfikowanie Glide kod załadunku do tego:

 Glide.with(this) 
      .load("https://cdn-images-1.medium.com/max/1200/1*hcfIq_37pabmAOnw3rhvGA.png") 
      .asBitmap() 
      .diskCacheStrategy(DiskCacheStrategy.SOURCE) 
      .into(new SimpleTarget<Bitmap>() { 
       @Override 
       public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) { 
        Log.d("Size ", "width :"+resource.getWidth() + " height :"+resource.getHeight()); 
        imageView.setImageBitmap(resource); 
        storeImage(resource); 
       } 
      }); 

I Używanie tego lub jakiegokolwiek innego mechanizmu przechowywania bitmapy w pamięci zewnętrznej/wewnętrznej.

private void storeImage(Bitmap image) { 
     File pictureFile = getOutputMediaFile(); 
     if (pictureFile == null) { 
      Log.d(TAG, 
        "Error creating media file, check storage permissions: ");// e.getMessage()); 
      return; 
     } 
     try { 
      FileOutputStream fos = new FileOutputStream(pictureFile); 
      image.compress(Bitmap.CompressFormat.PNG, 90, fos); 
      fos.close(); 
      Log.d(TAG, "img dir: " + pictureFile); 
     } catch (FileNotFoundException e) { 
      Log.d(TAG, "File not found: " + e.getMessage()); 
     } catch (IOException e) { 
      Log.d(TAG, "Error accessing file: " + e.getMessage()); 
     } 
    } 


private File getOutputMediaFile(){ 
    // To be safe, you should check that the SDCard is mounted 
    // using Environment.getExternalStorageState() before doing this. 
    File mediaStorageDir = new File(Environment.getExternalStorageDirectory() 
      + "/Android/data/" 
      + getApplicationContext().getPackageName() 
      + "/Files"); 

    if (! mediaStorageDir.exists()){ 
     if (! mediaStorageDir.mkdirs()){ 
      return null; 
     } 
    } 

    File mediaFile; 
    Random generator = new Random(); 
    int n = 1000; 
    n = generator.nextInt(n); 
    String mImageName = "Image-"+ n +".jpg"; 

    mediaFile = new File(mediaStorageDir.getPath() + File.separator + mImageName); 
    return mediaFile; 
} 

Używam Glide ver 3.7

compile "com.github.bumptech.glide:glide:3.7.0" 

Oto pełny przykład roboczych: https://github.com/nieldeokar/GlideApp

3

Jak już wspomniano, Log.d (TAG, "O, aby rozpocząć wydobycie") nigdy zostanie wywołany, co oznacza, że ​​onResourceReady nigdy nie zostanie wywołany. To może się zdarzyć z powodu jakiegoś błędu. Spróbuj zastąpić wywołania zwrotne błędu.

Aby zidentyfikować problem, polecam zastąpić inne wywołania zwrotne z SimpleTarget do debugowania problemu.

@Override 
    public void onLoadCleared(@Nullable Drawable placeholder) { 
    // load has been cleared 
    } 

    @Override 
    public void onLoadStarted(@Nullable Drawable placeholder) { 
    // load has started 
    } 

    @Override 
    public void onLoadFailed(@Nullable Drawable errorDrawable) { 
    // load failed due to some reason, notify callers here about the same 
    } 
Powiązane problemy