ifelsething logoifelsething

Get Original Image Size in React Native

Posted By: Harish
Get Original Image Size in React Native

We have seen a callback, onLoad to get the image size details after rendering the image. This is loaded image size which can be different from original image size. But sometimes we may need the original image size before even rendering.

For this, we have two methods for getting remote image size, getSize() and getSizeWithHeaders().

For local resource files, we have resolveAssetSource() method to get the size.

We will see their output in this post.

Create A New Project

Create a new react-native project by using npx. Check documentation for creating a new react native project.

npx react-native@latest init ImageRN

Example Implementation

We will create a simple screen with the above methods implementation.

Import and add Image component with a local or remote image source.

To understand better, we will load a remote URL to get on load and original sizes.

//App.tsx
...
import { Image } from 'react-native';
...
const remoteImage = 'https://iet-images.s3.ap-south-1.amazonaws.com/fav.png';
...
<Image
  style={styles.image}
  resizeMode="contain"
  onLoad={(e) => {
    const data = e.nativeEvent;
    console.log("On Load: ", data);
  }}
  src={remoteImage}
/>
...

If we run the app,

#for Android
npx react-native run-android

#for ios
npx react-native run-ios

We will get the width and height of the loaded image. Please note that the images get adjusted based on the screen and resize modes.

LOG  On Load:  {"source": {"height": 266, "uri": "https://iet-images.s3.ap-south-1.amazonaws.com/fav.png", "width": 355}, "target": 169}

Now, we will reload the app with getSize() and getSizeWithHeaders() methods.

Import useEffect from react and run both methods at the same time. Check below code.

...
useEffect(() => {
  Image.getSize(
    remoteImage,
    (width, height) => {
      console.log("Original Size: ", width, height);
    },
    (err) => {
      console.log(err);
    }
  )
  Image.getSizeWithHeaders(
    remoteImage,
    {
      'Content-Type': 'image/png',
      'Authorization': 'your-token'
    },
    (width, height) => {
      console.log("Original Size With Headers: ", width, height);
    },
    (err) => {
      console.log(err);
    }
  )
}, []);
...

From the above code, we can see that these methods are called before rendering and we will get width and height properties as a callback event.

Both methods are the same but use the getSizeWithHeaders() method when headers are needed to load the image.

LOG  Original Size:  1200 900
LOG  Original Size With Headers:  1200 900

Above methods are for remote images, but what about local image assets?

For local images, we can use the resolveAssetSource() method. This takes the path of the image.

...
const imagePath = require('./assets/fav.png');
...
useEffect(() => {
...
const width = Image.resolveAssetSource(imagePath).width;
const height =  Image.resolveAssetSource(imagePath).height;
console.log("Original Local Image Size: ", width, height);
...
}, []);
...

If we reload the screen, we will get the original width and height of the local image.

LOG  Original Size With Headers:  1200 900
Get Original Image Size in React Native

Complete code of our example,

//App.tsx
import React, { useEffect, useState } from "react";
import {
  Text,
  StyleSheet,
  SafeAreaView,
  StatusBar,
  View,
  Image
} from "react-native";

export default function App() {

  const [originalSize, setOriginalSize] = useState({});
  const [loadSize, setLoadSize] = useState({});

  const remoteImage = 'https://iet-images.s3.ap-south-1.amazonaws.com/fav.png';
  const imagePath = require('./assets/fav.png');

  useEffect(() => {

    // Remote Image without Headers
    Image.getSize(
      remoteImage,
      (width, height) => {
        console.log("Original Size: ", width, height);
        setOriginalSize({
          width: width,
          height: height
        })
      },
      (err) => {
        console.log(err);
      }
    );

    // Remote Image with Headers
    Image.getSizeWithHeaders(
      remoteImage,
      {
        'Content-Type': 'image/png',
        'Authorization': 'your-token'
      },
      (width, height) => {
        console.log("Original Size With Headers: ", width, height);
      },
      (err) => {
        console.log(err);
      }
    );

    // Local Image
    const width = Image.resolveAssetSource(imagePath).width;
    const height = Image.resolveAssetSource(imagePath).height;
    console.log("Original Local Image Size: ", width, height);

  }, []);

  return (
    <SafeAreaView style={{ flex: 1, backgroundColor: 'white' }}>
      <StatusBar
        barStyle="dark-content"
      />
      <View style={styles.container} >
        <Text style={styles.text}>
          ifelsething.com
        </Text>
        <Text style={styles.text}>
          original image size and loaded image size in react native
        </Text>
        <Image
          style={styles.image}
          resizeMode="contain"
          onLoad={(e) => {
            const data = e.nativeEvent;
            console.log("On Load: ", data);
            setLoadSize({
              width: data.source.width,
              height: data.source.height
            })
          }}
          src={remoteImage}
        />
        <Text style={styles.text}>
          Original Image Size: {originalSize.width} x {originalSize.height}
        </Text>
        <Text style={styles.text}>
          On Load Image Size: {loadSize.width} x {loadSize.height}
        </Text>
      </View>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    margin: 10,
    gap: 20,
  },
  text: {
    fontSize: 15,
    color: 'black',
    fontStyle: 'italic'
  },
  image: {
    width: '100%',
    height: 300,
    alignSelf: 'center',
  }
});

Share is Caring

Related Posts