2016-05-24 63 views
0

我建立一個應用程序上,當我試圖在ImageView的顯示圖像等我處理超大相似圖片的10000X5000像素 .The應用程序崩潰。 我無法去位圖採樣,因爲我無法更改圖像的大小。處理大量圖像

一個簡單的工作是選擇10000X5000像素的圖像並將其顯示在ImageView中。

目前,我正在爲此使用簡單的代碼,並且應用程序正在崩潰。

  Uri selectedImage = data.getData(); 
      String[] filePathColumn = { MediaStore.Images.Media.DATA }; 

      // Get the cursor 
      Cursor cursor = getContentResolver().query(selectedImage, 
        filePathColumn, null, null, null); 
      // Move to first row 
      cursor.moveToFirst(); 

      int columnIndex = cursor.getColumnIndex(filePathColumn[0]); 
      imgDecodableString = cursor.getString(columnIndex); 
      cursor.close(); 
      ImageView imgView = (ImageView) findViewById(R.id.imgView); 
      // Set the Image in ImageView after decoding the String 



      imgView.setImageBitmap(BitmapFactory 
        .decodeFile(imgDecodableString)); 

唯一的例外是內存不足

E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.star.largeiamgesdemo,

PID: 21155 java.lang.OutOfMemoryError: Failed to allocate a 200000012 byte allocation with 4194208 free bytes and 123MB until OOM

MemoryMapFile東西可以做的伎倆,但它是文件FileChannel

更新未得到圖像什麼

我不能在顯示原因時縮小圖像,因爲我必須對其進行編輯(即用戶可以修改ITE東西在圖像上,或者作爲水印地方其他圖像對他們)

感謝

+0

降低圖像分辨率和尺寸 –

+1

**我無法去位圖採樣,因爲我無法更改圖像的大小。您需要縮小圖像。圖像的格式是什麼?是.png,.jpeg還是webp。 – Raghunandan

+0

正如IntelliJ Amiya所說,但首先嚐試設置'useLargeHeap = true;',這不是推薦的方法,但它有時可能有用。 – Stanojkovic

回答

3

至於你說:

I can't go for bitmap sampling as I can't change the size of images.

因此,減小圖像大小或對它進行採樣礦石秀,不好。我認爲在我的下面是一個解決方案。

由於Android的dalvik限制,您可以使用最大堆大小。當超過它時,發生崩潰。

爲了繞過達爾維克限制,您可以使用jni從本地堆申請內存。您必須在jni中使用libjpeg。您可以在SurfaceView上選擇顯示圖像,然後通過holder.getSurface()獲取Surface對象,將其傳遞給jni,然後使用libjpeg lib來解碼圖像並顯示它。接下來是一些示例代碼,請撥打showJPG()函數來顯示大圖。

JNIEXPORT void JNICALL Java_com_example_photoprocessing_activity_SurfaceProcessingActivity_showJPG(
     JNIEnv * env, jobject activity, jobject surface, jstring img) { 
    const char * imgChar; 
    jboolean * isCopy; 
    imgChar = env->GetStringUTFChars(img, 0); 
    ANativeWindow_Buffer nwBuffer; 

    LOGI("img path : %s ",imgChar); 

    LOGI("ANativeWindow_fromSurface "); 
    ANativeWindow * mANativeWindow = ANativeWindow_fromSurface(env, surface); 

    if (mANativeWindow == NULL) { 
     LOGE("ANativeWindow_fromSurface error"); 
     return; 
    } 

    LOGI("ANativeWindow_lock "); 
    if (0 != ANativeWindow_lock(mANativeWindow, &nwBuffer, 0)) { 
     LOGE("ANativeWindow_lock error"); 
     return; 
    } 

    read_jpeg_file_show(imgChar, nwBuffer); 

    if (nwBuffer.format == WINDOW_FORMAT_RGBA_8888) { 
     LOGI("nwBuffer->format == WINDOW_FORMAT_RGBA_8888 "); 
    } 

    LOGI("ANativeWindow_unlockAndPost "); 
    if (0 != ANativeWindow_unlockAndPost(mANativeWindow)) { 
     LOGE("ANativeWindow_unlockAndPost error"); 
     return; 
    } 

    env->ReleaseStringUTFChars(img,imgChar); 
    ANativeWindow_release(mANativeWindow); 
    LOGI("ANativeWindow_release "); 
    return; 
} 

int read_jpeg_file_show(const char *input_filename, 
     ANativeWindow_Buffer& nwBuffer) { 
    struct jpeg_decompress_struct cinfo; 
    struct jpeg_error_mgr jerr; 
    FILE *input_file; 
    JSAMPARRAY buffer; 
    int row_width; 

    unsigned char *buffertmp; 

    cinfo.err = jpeg_std_error(&jerr); 

    if ((input_file = fopen(input_filename, "rb")) == NULL) { 
     fprintf(stderr, "can't open %s\n", input_filename); 
     LOGI("can't open jpg1"); 
     return -1; 
    } 
    jpeg_create_decompress(&cinfo); 

    /* Specify data source for decompression */ 
    jpeg_stdio_src(&cinfo, input_file); 


    /* Read file header, set default decompression parameters */ 
    (void) jpeg_read_header(&cinfo, TRUE); 


    /* Start decompressor */ 
    (void) jpeg_start_decompress(&cinfo); 


    row_width = cinfo.output_width * cinfo.output_components; 

    buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, 
      row_width, 1); 

    buffertmp = (unsigned char *) malloc(row_width); 
    memset(buffertmp, 0, row_width); 
    LOGI("malloc and memset"); 

    /* Process data */ 
    int get8h5 = 248, get8h6 = 252; 
    __uint16_t * line = (__uint16_t *) nwBuffer.bits; 
    int wheight = 0; 

    int scalew = 1, scaleh = 1; 

    if (cinfo.output_width > nwBuffer.width) { 
     scalew = cinfo.output_width/nwBuffer.width; 
    } 

    LOGI(" scale of img = %d", scalew); 

    for (int i = 0, choosehNum = 0; i < cinfo.output_height; i++) { 

     jpeg_read_scanlines(&cinfo, buffer, 1); 
     buffertmp = *buffer; 

     if (i % scalew == 0 && choosehNum++ < nwBuffer.height) { 

      //LOGI("nwBuffer->format == WINDOW_FORMAT_RGB_565"); 
      for (int j = 0, choosewNum = 0; j < cinfo.output_width; j++) { 
       if (j % scalew == 0) { 
        if (nwBuffer.format == WINDOW_FORMAT_RGB_565) { 
         line[choosewNum] = ((__uint16_t) buffertmp[3 * j + 0] 
           & get8h5) << 8 
           | ((__uint16_t) (buffertmp[3 * j + 1] & get8h6) 
             << 3) 
           | ((__uint16_t) (buffertmp[3 * j + 2] & get8h6) 
             >> 3); 
         choosewNum++; 
        } 
       } 

      } 
      line = line + nwBuffer.stride; 
     } 
    } 

    (void) jpeg_finish_decompress(&cinfo); 
    LOGI("jpeg_finish_decompress !!"); 

    jpeg_destroy_decompress(&cinfo); 
    LOGI("jpeg_destroy_decompress !!"); 

    /* Close files, if we opened them */ 
    fclose(input_file); 

    return 0; 
} 

希望能幫到你!

0

很明顯,你必須縮小圖像尺寸或手機無法呈現的圖像在ImageView顯示。所以,您需要縮小圖像,以便圖像可以顯示在您的ImageView中。

int imageScaleWidth = 480; // Change the width 
Bitmap bitmapImage = BitmapFactory.decodeFile(imgDecodableString); // imgDecodableString is your image path. 
int imageScaleHeigth = (int) (bitmapImage.getHeight() * (imageScaleWidth/bitmapImage.getWidth())); 
Bitmap scaled = Bitmap.createScaledBitmap(bitmapImage, imageScaleWidth , imageScaleHeigth , true); 
imgView.setImageBitmap(scaled); 
0

你應該的「裝大的位圖高效」

特別是讀了Android文檔,你提到你不能爲「位圖採樣」但要注意的Android可以讀取圖像文件大小,然後計算可用於可用大小的採樣。然後,Android將只加載採樣的位圖,這很好,因爲屏幕分辨率不足以正確顯示像這樣的圖像。

此外,一定要考慮方法decodeSampledBitmapFromResource的縮略圖。

https://developer.android.com/training/displaying-bitmaps/load-bitmap.html#load-bitmap

而在去年,一定要使用largeHeapManifest屬性,如果需要的話 - 看看基礎上,文檔等存儲優化技術:

https://developer.android.com/training/articles/memory.html