JessYanCoding / AndroidAutoSize

🔥 A low-cost Android screen adaptation solution (今日头条屏幕适配方案终极版,一个极低成本的 Android 屏幕适配方案).
Apache License 2.0
13.52k stars 1.98k forks source link

glide中加载图片density不一致导致bitmap大小不一致 #375

Open zhuzhushang opened 3 years ago

zhuzhushang commented 3 years ago

glide加载完图片打印图片density,density不一致,glide有操作会修改density嘛?glide版本4.4.0 有时候240,有时候是333,应该都是333. image 我这边imageview宽高自适应的,所以显示大小也不一致。

JessYanCoding commented 3 years ago

https://github.com/JessYanCoding/AndroidAutoSize/issues/218 https://github.com/JessYanCoding/AndroidAutoSize/issues/91

zhuzhushang commented 3 years ago

因为我这边发现是在transform方法中调用了 Bitmap result = pool.get(toTransform.getWidth(), toTransform.getHeight(), Bitmap.Config.ARGB_8888); 方法后改变了bitmap的density,但是宽高并没有变化,所以我这里直接调用了bitmap的setdensity方法,设回正确的density。 result.setDensity(getResources().getDisplayMetrics().densityDpi); 目前还没发现问题。

RuiRay commented 1 year ago

原因是调用 Bitmap.createBitmap(width, height, Bitmap.Config.XXX) 函数创建 Bitmap 时,它的 mDensity 属性用的是默认值,追踪源码可以看出来:http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/jni/android/graphics/Bitmap.cpp#Bitmap_creator

Bitmap.java: createBitmap(int width, int height, Config config)
    -> createBitmap(width, height, config, <hasAlpha>true)
    -> createBitmap(<DisplayMetrics>null, width, height, config, hasAlpha)
    -> createBitmap(display, width, height, config, hasAlpha, ColorSpace.get(ColorSpace.Named.SRGB))
    -> nativeCreate(null, <offset>0, width, width, height, config.nativeInt, <mutable>true, <xyzD50>null, <p>null)
Bitmap.cpp: jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors, jint offset, jint stride, jint width, jint height, jint configHandle, jboolean isMutable, jfloatArray xyzD50, jobject transferParameters)
    -> createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable), <ninePatchChunk>, <ninePatchInsets>, <density>)
        -> 后几个参数未传,看头文件定义的默认参数值: createBitmap(JNIEnv* env, Bitmap* bitmap, int bitmapCreateFlags, jbyteArray ninePatchChunk = NULL, jobject ninePatchInsets = NULL, int density = -1);
    -> env->NewObject(gBitmap_class, gBitmap_constructorMethodID, reinterpret_cast<jlong>(bitmapWrapper), bitmap->width(), bitmap->height(), density, isMutable, isPremultiplied, ninePatchChunk, ninePatchInsets)
Bitmap.java: (long nativeBitmap, int width, int height, int density, boolean isMutable, boolean requestPremultiplied, byte[] ninePatchChunk, NinePatch.InsetStruct ninePatchInsets)
    -> if (density >= 0) { mDensity = density; }    (从头文件中看,density=-1,所以用的mDensity原始值)
    -> public int mDensity = getDefaultDensity();

所以修改 sDefaultDensity 的值就好了,可以通过反射:

private static void setBitmapDefaultDensity(int dpi) {
    try {
        // 修改 Bitmap 中的静态成员 private static volatile int sDefaultDensity = -1;
        Method method = Bitmap.class.getDeclaredMethod("setDefaultDensity", int.class);
        method.setAccessible(true);
        method.invoke(null, dpi);
    } catch (Exception e) {
        Log.w(TAG, "setBitmapDefaultDensity()", e);
    }
}