2016-05-24 64 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