0%

PNG和NinePNG区别

问题

同一个包,部分手机加载的.9图会发生拉伸?是什么问题导致了NinePng的变形呢?

调研

  • NinePng图的使用
  • NinePng图原理

NinePng图的科普

  • 左边的点代表垂直拉伸的区域
  • 上边的点代表水平拉伸的区域
  • 右边的点代表文字等的垂直可可显示区域
  • 下边的点代表文字等的水平可显示区域

NinePng图原理

Png,NinePng,Aapt-NinePng

  • 普通png (IHDR,IDAT,IEND) 3个chunk

  • NinePng (IHDR,IDAT,IEND,PLTE,tRNS )

  • Aapt-NinePng (npOl,npTc)

解析

回归问题

了解到npTC存放NinePng的拉伸和展示内容信息后,我们对npTC数据块信息进行比较(7.3.2版本混淆过的blq.9.png和7.3.3版本 main_act_bg.9.png)

  • apk中的NinePng

  • aaptNinePng

通过比较发现两份数据一模一样,继续通过java代码中的字节码进行比较

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

try {
InputStream inputStream = getAssets().open("blq.9.png");
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
byte[] a = bitmap.getNinePatchChunk();
if (!NinePatch.isNinePatchChunk(a)) {
throw new RuntimeException("not .9.png");
}
Log.d("blq is .9 :", NinePatch.isNinePatchChunk(a) + "");
NinePatchDrawable ninePatchDrawable = new NinePatchDrawable(new NinePatch(bitmap, bitmap.getNinePatchChunk()));
((ImageView) findViewById(R.id.iv_one)).setBackgroundDrawable(ninePatchDrawable);
InputStream inputStream2 = getAssets().open("main_act_bg.9.png");
Bitmap bitmap1 = BitmapFactory.decodeStream(inputStream2);
byte[] b = bitmap1.getNinePatchChunk();
if (!NinePatch.isNinePatchChunk(b)) {
throw new RuntimeException("not .9.png");
}
Log.d("main_act_bg.9.png ", NinePatch.isNinePatchChunk(b) + "");
NinePatchDrawable ninePatchDrawable2 = new NinePatchDrawable(new NinePatch(bitmap1, bitmap1.getNinePatchChunk()));
((ImageView) findViewById(R.id.iv_two)).setBackgroundDrawable(ninePatchDrawable2);
for (int i = 0; i < b.length; i++) {
System.out.println("NinePatchChunk : " + a[i] + "," + b[i]);
}
} catch (IOException e) {
e.printStackTrace();
}


输出日志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

2019-11-02 06:00:17.023 24242-24242/com.mobile.legends D/blq.9.png :: true
2019-11-02 06:00:17.025 24242-24242/com.mobile.legends D/main_act_bg.9.png: true
2019-11-02 06:00:17.025 24242-24242/com.mobile.legends I/System.out: .9.png NinePatchChunk
: 1,1
2019-11-02 06:00:17.025 24242-24242/com.mobile.legends I/System.out: .9.png NinePatchChunk
: 4,4
2019-11-02 06:00:17.026 24242-24242/com.mobile.legends I/System.out: .9.png NinePatchChunk
: 4,4
2019-11-02 06:00:17.026 24242-24242/com.mobile.legends I/System.out: .9.png NinePatchChunk
: 9,9
2019-11-02 06:00:17.026 24242-24242/com.mobile.legends I/System.out: .9.png NinePatchChunk
: 32,32
2019-11-02 06:00:17.026 24242-24242/com.mobile.legends I/System.out: .9.png NinePatchChunk
: 0,0
2019-11-02 06:00:17.026 24242-24242/com.mobile.legends I/System.out: .9.png NinePatchChunk
: 0,0
2019-11-02 06:00:17.026 24242-24242/com.mobile.legends I/System.out: .9.png NinePatchChunk
.....


再次发现两张图的NinePatchChunk的信息一模一样,理论上两张一模一样的.9图,应该显示都是一样的,不可能其中一张会有拉伸现 象,所以回归问题,我们还是没有解决这个问题,但是如果后续存在这样的问题,我们可以尝试动态加载.9图

加载方式

  • 在res目录下存放,View上直接加载
  • aapt编译 .9图,然后存放到 assets目录下,利用NinePatchDrawable加载

参考