2013-03-09 39 views
25

Im tạo ứng dụng cần giải mã ảnh lớn thành bitmap để hiển thị trong ImageView.Android: Chiều rộng và chiều cao tối đa cho phép của bitmap

Nếu tôi chỉ cố gắng để giải mã chúng thẳng vào một bitmap tôi nhận được lỗi sau "Bitmap quá lớn để được tải lên thành một kết cấu (1944x2592, max = 2048x2048)"

Vì vậy, để có thể hiển thị hình ảnh với độ phân giải quá cao im sử dụng:

Bitmap bitmap = BitmapFactory.decodeFile(path); 

if(bitmap.getHeight()>=2048||bitmap.getWidth()>=2048){ 
    DisplayMetrics metrics = new DisplayMetrics(); 
    getWindowManager().getDefaultDisplay().getMetrics(metrics); 
    int width = metrics.widthPixels; 
    int height = metrics.heightPixels; 
    bitmap =Bitmap.createScaledBitmap(bitmap, width, height, true);    
} 

này hoạt động nhưng tôi không thực sự muốn hardcode giá trị tối đa là 2048 như tôi có trong if-tuyên bố bây giờ, nhưng tôi không thể tìm ra cách để có được một sự kích thước tối đa cho phép của bitmap cho một thiết bị

Bất kỳ ý tưởng nào?

Trả lời

9

Giới hạn này phải được xuất phát từ triển khai OpenGL cơ bản. Nếu bạn đã sử dụng OpenGL trong ứng dụng, bạn có thể sử dụng một cái gì đó như thế này để có được kích thước tối đa:

int[] maxSize = new int[1]; 
gl.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, maxSize, 0); 
// maxSize[0] now contains max size(in both dimensions) 

Điều này cho thấy tôi cả Galaxy Nexus của tôi và Galaxy S2 có tối đa 2048x2048. Thật không may, nếu bạn chưa sử dụng nó, cách duy nhất để có được một bối cảnh OpenGL để gọi điều này là tạo ra một (bao gồm cả surfaceview, vv), mà là rất nhiều chi phí chỉ để truy vấn tối đa kích thước.

+0

Cảm ơn bạn đã trả lời, đây cũng là điều tôi đang nghĩ. Bất kỳ ý tưởng bao nhiêu thay đổi này từ các thiết bị khác nhau? – Fredkr

+0

Thành thật mà nói, tôi không chắc chắn. Đó là lý do tại sao tôi đã thử hai thiết bị. Nếu tôi có thể tìm được chiếc HTC Magic cũ của mình, tôi cũng đã thử cái đó.Tôi biết trên OpenGL tiêu chuẩn spec cho biết nó luôn luôn> = 1024, nhưng tôi không chắc chắn về OpenGLES. – Geobits

+0

Được rồi, cảm ơn một lần nữa. Đoán i'l hardcode một giá trị 1024 để chắc chắn. – Fredkr

2

này sẽ giải mã và hình ảnh quy mô trước khi nạp vào bộ nhớ, chỉ cần thay đổi ngang và dọc để kích thước mà bạn thực sự muốn

BitmapFactory.Options options = new BitmapFactory.Options(); 
options.inJustDecodeBounds = true; 
BitmapFactory.decodeFile(path, options); 
int imageHeight = options.outHeight; 
int imageWidth = options.outWidth; 
String imageType = options.outMimeType; 
if(imageWidth > imageHeight) { 
    options.inSampleSize = calculateInSampleSize(options,512,256);//if landscape 
} else{ 
    options.inSampleSize = calculateInSampleSize(options,256,512);//if portrait 
} 
options.inJustDecodeBounds = false; 
bitmap = BitmapFactory.decodeFile(path,options); 

phương pháp để tính kích thước

public static int calculateInSampleSize(
     BitmapFactory.Options options, int reqWidth, int reqHeight) { 
    // Raw height and width of image 
    final int height = options.outHeight; 
    final int width = options.outWidth; 
    int inSampleSize = 1; 

    if (height > reqHeight || width > reqWidth) { 

     // Calculate ratios of height and width to requested height and width 
     final int heightRatio = Math.round((float) height/(float) reqHeight); 
     final int widthRatio = Math.round((float) width/(float) reqWidth); 

     // Choose the smallest ratio as inSampleSize value, this will guarantee 
     // a final image with both dimensions larger than or equal to the 
     // requested height and width. 
     inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; 
    } 

    return inSampleSize; 
} 
0

Nếu bạn đang ở cấp API 14+ (ICS), bạn có thể sử dụng các chức năng getMaximumBitmapWidthgetMaximumBitmapHeight trên lớp Canvas. Điều này sẽ làm việc trên cả hai phần cứng tăng tốc và phần mềm lớp.

Tôi tin rằng phần cứng Android ít nhất phải hỗ trợ 2048x2048, vì vậy đó sẽ là một giá trị thấp nhất an toàn. Trên các lớp phần mềm, kích thước tối đa là 32766x32766.

+4

Tôi thực sự đã thử nó, nó trả về một giá trị trên 30k để nó không giúp được ở tất cả – Fredkr

+0

Đó là vì khung nhìn của bạn không tăng tốc phần cứng. canvas.isHardwareAccelerated() ', nó sẽ trả về' true'. Nếu không, hãy thử 'view.setLayerType (View.LAYER_TYPE_HARDWARE, null)' hoặc cho phép tăng tốc phần cứng trong tệp kê khai (android: hardwareAccelerated = "true"). –

+0

Thử điều này là tốt, vẫn còn một giá trị trên 30k – Fredkr

0

Giới hạn 2048 * 2048 là dành cho GN. GN là một thiết bị xhdpi và có lẽ bạn đặt hình ảnh vào thùng mật độ sai. Tôi đã di chuyển hình ảnh 720 * 1280 từ drawable sang drawable-xhdpi và nó hoạt động.

Cảm ơn câu trả lời của Romain Guy. Đây là số link câu trả lời của anh ấy.

11

Một cách khác để nhận được kích thước tối đa cho phép là lặp qua tất cả các cấu hình EGL10 và theo dõi kích thước lớn nhất.

public static int getMaxTextureSize() { 
    // Safe minimum default size 
    final int IMAGE_MAX_BITMAP_DIMENSION = 2048; 

    // Get EGL Display 
    EGL10 egl = (EGL10) EGLContext.getEGL(); 
    EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); 

    // Initialise 
    int[] version = new int[2]; 
    egl.eglInitialize(display, version); 

    // Query total number of configurations 
    int[] totalConfigurations = new int[1]; 
    egl.eglGetConfigs(display, null, 0, totalConfigurations); 

    // Query actual list configurations 
    EGLConfig[] configurationsList = new EGLConfig[totalConfigurations[0]]; 
    egl.eglGetConfigs(display, configurationsList, totalConfigurations[0], totalConfigurations); 

    int[] textureSize = new int[1]; 
    int maximumTextureSize = 0; 

    // Iterate through all the configurations to located the maximum texture size 
    for (int i = 0; i < totalConfigurations[0]; i++) { 
     // Only need to check for width since opengl textures are always squared 
     egl.eglGetConfigAttrib(display, configurationsList[i], EGL10.EGL_MAX_PBUFFER_WIDTH, textureSize); 

     // Keep track of the maximum texture size 
     if (maximumTextureSize < textureSize[0]) 
      maximumTextureSize = textureSize[0]; 
    } 

    // Release 
    egl.eglTerminate(display); 

    // Return largest texture size found, or default 
    return Math.max(maximumTextureSize, IMAGE_MAX_BITMAP_DIMENSION); 
} 

Từ thử nghiệm của tôi, điều này khá đáng tin cậy và không yêu cầu bạn tạo một thể hiện. Hiệu suất-khôn ngoan, điều này mất 18 mili giây để thực hiện trên Note 2 của tôi và chỉ có 4 phần nghìn giây trên G3 của tôi.

+1

Điều này có vẻ như nó đang làm việc cho tôi, và thậm chí cả các thiết bị API 16 cũ hơn thường mất <1ms, với 5ms là dài nhất tôi thấy nó mất sau khi chạy nó một vài lần. Kết quả không nên thay đổi vì vậy tôi đã lưu kết quả sau một lần chạy chỉ để tránh làm việc cpu thêm. –

+0

Lưu ý rằng một số thiết bị có nhiều cấu hình kích thước họa tiết tối đa. Kindle Fire HD 7 '' (2012) có cấu hình báo cáo kích thước kết cấu tối đa 2048 và kích thước họa tiết tối đa 4096. – lillicoder

Các vấn đề liên quan