加载BitmapRegionDecoder的图像在模拟器上是可以的,但在设备上太大了

时间:2014-11-12 17:42:57

标签: android bitmap bitmapfactory android-bitmap bitmapregiondecoder

a simple word game app中,我使用以下代码从PNG-image stripe加载26个字母平铺图像:

image stripe

private static final CharacterIterator ABC = 
    new StringCharacterIterator("ABCDEFGHIJKLMNOPQRSTUVWXYZ");

private static HashMap<Character, Bitmap> sImages =
    new HashMap<Character, Bitmap>();

BitmapRegionDecoder decoder = null; 

InputStream is = sContext.getResources()
    .openRawResource(R.drawable.big_english);

try {   
        decoder = BitmapRegionDecoder.newInstance(is, false); 
} catch (IOException ex) {
}       

int h = decoder.getHeight();
Rect r = new Rect(0, 0, h, h);

for (char c = ABC.first(); 
        c != CharacterIterator.DONE; 
        c = ABC.next(), r.offset(h, 0)) {

           Bitmap bmp = decoder.decodeRegion(r, null);
           sImages.put(c, bmp);
}       

这适用于Android模拟器:

emulator

但是在真正的Moto G设备上,字母太大了(可能是1.5因素?当我打印sContext.getResources().getDisplayMetrics().density我出于某种原因得到2.0):

Moto G device

同时正确显示the yellow square tile backround

所有(big_tile.pngbig_english.png以及game_board.png)都是PNG图像 - 为什么差异呢?

为什么会发生这种情况以及如何解决这个问题?

我应该使用inDensity还是其他任何BitmapFactory.Options

或者是因为我的getResources().openRawResource()电话 - 而是使用什么呢?

2 个答案:

答案 0 :(得分:2)

我的图像也有同样的问题,Android设备带有很多屏幕分辨率。您需要在您的可绘制文件夹中放入大量图像,或者为每个屏幕分辨率提供一组图像宽度和高度的规则

for example:
if screen_resolution = 4 inch
int img_height = 200
int img_width = 200
else if screen_resolution = 5 inch
int img_height = 300
int img_width = 300

。 。 等等 希望这可以帮助你一些方法。

这里有一些我的代码(我使用的是imageview而不是位图抱歉):

int width,height;

   //calculate device screen
    DisplayMetrics metrics=new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(metrics);
    float height=metrics.heightPixels/metrics.xdpi;
    float width=metrics.widthPixels/metrics.ydpi;
    float inchscreen = FloatMath.sqrt(height*height+width*width);


if (inchscreen > 4.1000)
    {
        //set image height for device above 4.1 inch screen
        height = 400;
        width = 400     
    }
else {
        //set image height for device below 4.1 inch screen
        height = 280;
        width = 280
    }

if (imgfile != null) {
                    int imageResource = getResources().getIdentifier(uri, null,
                            getPackageName());
                    Drawable image = getResources().getDrawable(imageResource);
                    imageview.setImageDrawable(image);
                    imageview.getLayoutParams().height = h_display;
                    imageview.getLayoutParams().width = h_display;
                    }

答案 1 :(得分:0)

我将在这里分享我自己的解决方案。

问题是,我的字母图块的黄色背景是Drawable,前景是Bitmap(在PNG条纹的BitmapRegionDecoder的帮助下阅读)

由于一些奇怪的原因,我仍然不明白 - 他们的尺寸在某些Android设备上有所不同。

(1)因此my easiest workaround已将Bitmap(带字母的前景)缩放到Drawable(黄色方形背景)的范围内正在绘制字母图块的时间:

private Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);

public void draw(Canvas canvas) {
    canvas.save();
    canvas.translate(left, top);
    mImage.draw(canvas);
    Bitmap bmp = getImages().get(mLetter);
    canvas.drawBitmap(bmp, null, mImage.getBounds(), mPaint);
    canvas.restore();
}

(2)我的more involved workaround已经将Bitmap缩放一次 - 在我用BitmapRegionDecoder读取之后,我将其存储在HashMap中:

private static final CharacterIterator ABC = 
    new StringCharacterIterator("ABCDEFGHIJKLMNOPQRSTUVWXYZ");

private static HashMap<Character, Bitmap> sBitmaps = 
    new HashMap<Character, Bitmap>();

try {
        InputStream is = context.getResources().openRawResource(EN);
        BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is, false);
        int h = decoder.getHeight();
        Rect r = new Rect(0, 0, h, h);
        for (char c = ABC.first();
             c != CharacterIterator.DONE;
             c = ABC.next(), r.offset(h, 0)) {
                Bitmap unscaled = decoder.decodeRegion(r, null);
                Bitmap scaled = Bitmap.createScaledBitmap(unscaled, (int) (SCALE * width), (int) (SCALE * height), true);
                sBitmaps.put(c, scaled);
        }
} catch (IOException ex) {
}

(3)这两种方法都有效,但在较旧的Google Nexus One设备上,出于某种原因,我无法看到前景。在这一点上,我已经失去了神经,停止使用BitmapRegionDecoder,然后用ImageMagick(命令为convert square.png -crop 40x40 square_%d.png)分割PNG条纹。现在my app使用Drawable作为字母图块的前景和背景,适用于所有以SDK级别8开头的设备:

private static final String SQUARE = "square_";

private static final char[] LETTERS = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};

private static HashMap<Character, Drawable> sLetters = 
    new HashMap<Character, Drawable>();

for (int i = 0; i < LETTERS.length; i++) {
    char c = LETTERS[i];
    int id = context.getResources().getIdentifier(PREFIX + i, "drawable", context.getPackageName());
    Drawable d = context.getResources().getDrawable(id);
    d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
    sLetters.put(c, d);
} 

emulator