Android中的位图大小限制

Android中的位图大小限制,android,delphi,bitmap,firemonkey,Android,Delphi,Bitmap,Firemonkey,在我的应用程序中,我使用intent从库中获取图像文件名 我正试图将这个文件名加载到TImage。我试图用LoadFromFile加载它,并获取JBitmap,将其转换为TBitmap,然后将其分配给我的TImage。这只适用于最大尺寸为98 x 98像素的位图。。。如果宽度或高度大部分时间大于99或98像素我会收到一条错误消息“位图大小太大”。有时候我可以升到250 x 250 我想知道为什么三天以来 代码如下: var jBitmapD, jSmallBitmap: JBitmap;

在我的应用程序中,我使用
intent
从库中获取图像文件名 我正试图将这个文件名加载到
TImage
。我试图用
LoadFromFile
加载它,并获取
JBitmap
,将其转换为
TBitmap
,然后
将其分配给我的
TImage
。这只适用于最大尺寸为98 x 98像素的位图。。。如果宽度或高度大部分时间大于99或98像素我会收到一条错误消息“位图大小太大”。有时候我可以升到250 x 250

我想知道为什么三天以来

代码如下:

var

  jBitmapD, jSmallBitmap: JBitmap;
  BitmapD : TBitmap;
  imgW, imgH:Integer;

begin

...
    jBitmapD := TJBitmapFactory.JavaClass.decodeFile(StringToJString(imgGallerieChm));

    ...

    jSmallBitmap := TJBitmap.JavaClass.createScaledBitmap(jBitmapD, 98, 98, True);

    //jSmallBitmap := TJBitmap.JavaClass.createScaledBitmap(jBitmapD, 101, 101, True);
    //jSmallBitmap := TJBitmap.JavaClass.createScaledBitmap(jBitmapD, 1234, 567, True);
    ...

    imgH := jSmallBitmap.getHeight;
    imgW := jSmallBitmap.getWidth;

    bitmapD := TBitmap.Create; //Work if jSmallBitmap if smaller than 99 x 99

    //bitmapD.Create(98,98); //Work  if jSmallBitmap if smaller than 99 x 99
    //bitmapD.Create(222,333); //Don't work

    try
       bitmapD.SetSize(imgW,ImgH); //without this, its not working and it should be 99 x 99 or less... most of the time
       bitmapD := JBitmapToBitmap(jSmallBitmap);
       imgLepObs.Bitmap.Assign(bitmapD);
    finally
       bitmapD.Free;
    end;
如果AImage和TBitmap在大多数情况下小于99 x 99,则下一个函数将起作用

function TfrmMain.JBitmapToBitmap(const AImage: JBitmap): TBitmap;
var
  bitmapSurface :TBitmapSurface;
begin
  bitmapSurface := TBitmapSurface.Create;
  try
    if JBitmapToSurface(AImage, bitmapSurface) then
      begin

      Result.Assign(bitmapSurface);
      end;
  finally
  bitmapSurface.Free;
  end;
end;
谢谢你的帮助。。。我就要放弃了

我尝试用以下方法缩小位图的尺寸:

bfOptions.inSampleSize := StrToInt(Edit1.Text); //
bfOptions.inJustDecodeBounds := False;
jSmallBitmap := TJBitmapFactory.JavaClass.decodeFile(StringToJString(imgGallerieChm), bfOptions);
它大部分时间都在工作。。。生成的位图越小,成功的几率越高。。。对于给定的大小,它有时工作,有时不工作,有时在我重新启动应用程序后立即工作…

公共类ImageLoader{
            public class ImageLoader {

                MemoryCache memoryCache=new MemoryCache();
                FileCache fileCache;
                private Map<ImageView, String> imageViews=Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
                ExecutorService executorService; 

                public ImageLoader(Context context){

                    fileCache=new FileCache(context);
                    executorService=Executors.newFixedThreadPool(5);
                }

                final int stub_id=R.drawable.ic_launcher;
                public void DisplayImage(String url, ImageView imageView)
                {
                    imageViews.put(imageView, url);
                    Bitmap bitmap=memoryCache.get(url);
                    if(bitmap!=null)
                        imageView.setImageBitmap(bitmap);
                    else
                    {
                        queuePhoto(url, imageView);
                        imageView.setImageResource(stub_id);
                    }
                }

                private void queuePhoto(String url, ImageView imageView)
                {
                    PhotoToLoad p=new PhotoToLoad(url, imageView);
                    executorService.submit(new PhotosLoader(p));
                }

                private Bitmap getBitmap(String url) 
                {
                    File f=fileCache.getFile(url);

                    //from SD cache
                    Bitmap b = decodeFile(f);
                    if(b!=null)
                        return b;

                    //from web
                    try {
                        Bitmap bitmap=null;
                        URL imageUrl = new URL(url);
                        HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
                        conn.setConnectTimeout(30000);
                        conn.setReadTimeout(30000);
                        conn.setInstanceFollowRedirects(true);
                        InputStream is=conn.getInputStream();
                        OutputStream os = new FileOutputStream(f);
                        Utils.CopyStream(is, os);
                        os.close();
                        bitmap = decodeFile(f);
                        return bitmap;
                    } catch (Throwable ex){
                       ex.printStackTrace();
                       if(ex instanceof OutOfMemoryError)
                           memoryCache.clear();
                       return null;
                    }
                }

                //decodes image and scales it to reduce memory consumption
                private Bitmap decodeFile(File f){
                    try {
                        //decode image size
                        BitmapFactory.Options o = new BitmapFactory.Options();
                        o.inJustDecodeBounds = true;
                        BitmapFactory.decodeStream(new FileInputStream(f),null,o);

                        //Find the correct scale value. It should be the power of 2.
                        final int REQUIRED_SIZE=70;
                        int width_tmp=o.outWidth, height_tmp=o.outHeight;
                        int scale=1;
                        while(true){
                            if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
                                break;
                            width_tmp/=2;
                            height_tmp/=2;
                            scale*=2;
                        }

                        //decode with inSampleSize
                        BitmapFactory.Options o2 = new BitmapFactory.Options();
                        o2.inSampleSize=scale;
                        return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
                    } catch (FileNotFoundException e) {}
                    return null;
                }

                //Task for the queue
                private class PhotoToLoad
                {
                    public String url;
                    public ImageView imageView;
                    public PhotoToLoad(String u, ImageView i){
                        url=u; 
                        imageView=i;
                    }
                }

                class PhotosLoader implements Runnable {
                    PhotoToLoad photoToLoad;
                    PhotosLoader(PhotoToLoad photoToLoad){
                        this.photoToLoad=photoToLoad;
                    }

                    @Override
                    public void run() {
                        if(imageViewReused(photoToLoad))
                            return;
                        Bitmap bmp=getBitmap(photoToLoad.url);
                        memoryCache.put(photoToLoad.url, bmp);
                        if(imageViewReused(photoToLoad))
                            return;
                        BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad);
                        Activity a=(Activity)photoToLoad.imageView.getContext();
                        a.runOnUiThread(bd);
                    }
                }

                boolean imageViewReused(PhotoToLoad photoToLoad){
                    String tag=imageViews.get(photoToLoad.imageView);
                    if(tag==null || !tag.equals(photoToLoad.url))
                        return true;
                    return false;
                }

                //Used to display bitmap in the UI thread
                class BitmapDisplayer implements Runnable
                {
                    Bitmap bitmap;
                    PhotoToLoad photoToLoad;
                    public BitmapDisplayer(Bitmap b, PhotoToLoad p){bitmap=b;photoToLoad=p;}
                    public void run()
                    {
                        if(imageViewReused(photoToLoad))
                            return;
                        if(bitmap!=null)
                            photoToLoad.imageView.setImageBitmap(bitmap);
                        else
                            photoToLoad.imageView.setImageResource(stub_id);
                    }
                }

                public void clearCache() {
                    memoryCache.clear();
                    fileCache.clear();
                }

            }
MemoryCache MemoryCache=新的MemoryCache(); 文件缓存文件缓存; private Map ImageView=Collections.synchronizedMap(新的WeakHashMap()); 执行服务执行服务; 公共图像加载器(上下文){ fileCache=新的fileCache(上下文); executorService=Executors.newFixedThreadPool(5); } 最终int stub_id=R.drawable.ic_启动器; public void DisplayImage(字符串url,ImageView) { put(imageView,url); 位图位图=memoryCache.get(url); if(位图!=null) 设置图像位图(位图); 其他的 { 队列照片(url、imageView); setImageResource(存根id); } } 私有void队列照片(字符串url,ImageView) { PhotoToLoad p=新的PhotoToLoad(url,imageView); executorService.submit(新的PhotoLoader(p)); } 私有位图getBitmap(字符串url) { 文件f=fileCache.getFile(url); //从SD缓存 位图b=解码文件(f); 如果(b!=null) 返回b; //从网络 试一试{ 位图=空; URL imageUrl=新URL(URL); HttpURLConnection conn=(HttpURLConnection)imageUrl.openConnection(); 连接设置连接超时(30000); 连接设置读取超时(30000); conn.setInstanceFollowRedirects(真); InputStream is=conn.getInputStream(); OutputStream os=新文件OutputStream(f); Utils.CopyStream(is,os); os.close(); 位图=解码文件(f); 返回位图; }捕获(可丢弃的ex){ 例如printStackTrace(); if(ex instanceof OutOfMemoryError) memoryCache.clear(); 返回null; } } //对图像进行解码和缩放以减少内存消耗 私有位图解码文件(文件f){ 试一试{ //解码图像大小 BitmapFactory.Options o=新的BitmapFactory.Options(); o、 inJustDecodeBounds=true; 解码流(新的FileInputStream(f),null,o); //找到正确的刻度值。它应该是2的幂。 所需的最终int_尺寸=70; 内部宽度=o.向外宽度,高度=o.向外高度; int标度=1; while(true){
如果(width_tmp/2,我建议您的解决方案是解码较大的图像

BitmapFactory类提供了几种解码方法(decodeByteArray()、decodeFile()、decodeResource()等)

请参阅下面的SO链接以获取我的答案。我提供了解码图像的步骤和代码示例


我也遇到了类似的问题。该问题是delphi RTL for android中的一个已知错误。如果在线程中创建图像,则会出现异常:TBitmap。创建会引发“位图大小太大”。
这是因为canvas factory无法获得正确的CanvaType。它必须由EMB修复。我在一个主线程中创建位图,目前可以使用。

我使用了一个名为Image Loader的Java类在图像视图中设置图像。请您的回答提供一些文本解释,说明为什么需要这样做。只需提供没有其他内容的代码就可以了这里不赞成。你还发布了Java代码作为Delphi问题的答案,这也不合适。Java!=Delphi。谢谢你的回答。我目前使用你的方法加载位图,但没有任何更改…我无法处理大于100 x 100像素的位图…这正是我的问题。你能解释一下吗“。我在一个主线程中创建位图,现在可以使用了“?它在主线程上运行得很好!谢谢你的帮助!我不需要加载JImage,我只需要获取路径名,然后在主线程的过程中,我只需要使用LoadFromFile!好的。很抱歉回复太晚。我希望EMB能尽快修复它。我将图像加载到流中,并在TThread中创建位图。同步。”