React Native 0.57.x large images low quali

2020-08-10 07:39发布

问题:

There is really low quality when loading large bundled images, even when using resizeMethod="resize". This happens only on Android, not on any iOS simulator/device. Have tested it on Android 8.1 emulator and LG G6 with Android 8.0. Please see the screenshots bellow.

At the left screenshot we see the exact same code running with RN 0.56.0 and at the right screenshot we see RN 0.57.5. The code is just a simple image <Image source={require('./assets/ELHall1.png')} resizeMethod="resize" /> and the image size is 2111 x 4645 pixels. Both projects are fresh installed using react-native init RN057ImageTest and react-native init --version="0.56.0" RN056ImageTest.

Simple App with an Image

...
type Props = {};
export default class App extends Component<Props> {
  render() {
    return (
      <View style={styles.container}>
        {/*<Text style={styles.welcome}>Welcome to React Native!</Text>
        <Text style={styles.instructions}>To get started, edit App.js</Text>
        <Text style={styles.instructions}>{instructions}</Text>*/}
        <Image source={require('./assets/ELHall1.png')} resizeMethod="resize" />
      </View>
    );
  }
}
...

I have created a Github issue to RN repo since September but noone has replied which makes me think that I am doing something wrong. Is there a new prop or an other way to make large images show normal with full quality in RN 0.57.x? Maybe the metr obuilder updates to 0.57.x have changed how the bundler handles the image assets? I have used resizeMethod prop to "scale" and "resize" with no difference at all. I have used PNG8, PNG24 and PNG32 all same result.

EDIT

The Github repo with the code and the PNG image files: https://github.com/clytras/RN057ImageTest

Please don't give any answers about JPEG images and that they do work, I already know that; I want to make PNG images work like they do in RN 0.56.

UPDATE JAN/2020

This is an update for people landing here regarding this issue.

The RN Issue has been closed since August 10, 2019 with the statement that this is not a React Native issue but rather a Fresco issue.

I have created an issue at Fresco on August 22, 2019 and after some conversations and talkings, the only way for now to disable image downsample, is to compile Fresco from source after removing/comment out the downsample code inside DecodeProducer.java.

I have created a repository that has RN 0.61 and has detailed instructions on how to compile Fresco and disable image downsample. The repository can be found here: https://github.com/clytras/RN061FrescoBuild.

It turns out Fresco has a bug and does not apply Fresco configuration using ImagePipelineConfig and MainPackageConfig inside MainApplication.java, you can see more details about this here. RN has downsampling disabled by default! Until Fresco fixes this issue, the only way to disable image downsampling is to compile Fresco from source after removing the downsample code.

UPDATE FEB/2020

I have created a react-native-community/cli template that has RN 0.61.5 project and the required modifications to build Fresco from source. This is an easy and quick way to have a new RN project crafted with custom project name and with the changes needed to compile Fresco from source. It also uses Android NDK Revision 21 and I have tested it on macOS and Windows using yarn 1.21.

Github repository: clytras/react-native-fresco
NPM template: @lytrax/react-native-fresco

It can be installed like this:

npx @react-native-community/cli@next init --template=@lytrax/react-native-fresco <ProjectName>

There are detailed installation instruction in the README. You need to clone/patch Fresco using yarn fresco-setup and then install Android NDK and create android/libraries/fresco/local.properties with Android NDK path.

回答1:

Most of the times it is the dimensions of the Image that matter, UI designers make Designs to standard high end Mobile phones(with fixed Screen Size) and export the Images as .png to xhdpi,xxhdpi and xxxhdpi resolutions. So developers rename those Images by appending @1x, @2x & @3x to those resolutions. Example: ELHall1@1x ,ELHall1@2x, ELHall1@3x.

When Importing Images use the standard name of the Image. Example: ELHall1.png.

To workaround <Image> tag I use the help of Dimension API in React-Native to auto set the width and height of the Image most of the time.

Example: var {height, width} = Dimensions.get('window');

For Example, if the Image has to cover the whole screen, I would do,

 <View style={{flex:1,width:"100%",height:"100%"}}>
    <Image style={{width:width, height:height}} source={require('./assets/ELHall1.png')}  /> 
    // width & height is auto taken using Dimension API
    // To play around pixels use resizeMode= ("contain","center") (Keep this as last option)
  </View>

I Hope I could help you.



回答2:

I tested FastImage and it had a better quality

<FastImage source={require('./assets/ELHall1.png')} style={{height: '100%', aspectRatio: 2.5}} />


回答3:

It is the way to apply @clytras' patch to an existing project. And it cannot run android simulator anymore. I am always testing on real devices.