How to add text to an image in React Native?

Viewed 29500

I'm researching if it is easily possible with React Native or whether I should build a native app.

I want to edit an image from the photo library and add a text overlay to it. Think of it like a postcard with a greeting message on it.

How would I add text to and image and make a new copy of it in react native? I'm not looking for detailed code, just for an explanation on how to get started.

Update: Would it be a good alternative to just save the coordinates of the message on the picture instead of generating a new image?

10 Answers

You can go with 2 ways. You can either render the text on an image component and save the position of that text or you can process the image and get a new image with the text.

The first option brings up the problem of that position is relative to image's size. Means that if the image renders on a different sized screen the position and size of text should also be moved accordingly. This option needs a good calculation algorithm. Also, another problem could be the rendering times. Text component will render instantly but Image component needs to load the image first. This option also needs a good way of render algorithm.

The second option is not possible without a 3rd party library or some level of native code since react-native doesn't support image processing beyond the limits of CSS. A good and maintained image processing library is gl-react-native-v2. This library helps you to process and manipulate the image as you wish and then save the result with captureFrame(config). This option is more capable of processing file but needs you to save a new image.

Either way is good if the way you go is appropriate for your use case. The decision really depends on your case and preference.

You could use react-native's ImageBackground tag since using the Image tag as a container would give you a yellow box warning.

The sample code for it with overlay is as shown below

<ImageBackground source={SomeImage} style=  {SomeStyle} resizeMode='SomeMode'>
   {loader}
</ImageBackground>

It would be efficient if you work on the same image by changing the flex property in the styles of the image or you may set the position: absolute to the main image container and assign top , bottom, left, right to the nested container.

Helpful link may be found here

<View style={{flex: 1, justifyContent: 'center', alignItems: 'center', marginTop: 20}}>
    <Image
     style={{
       flex: 1,
       width:100,
       height:100,
     }}
     source={require('../imgs/star.png')}
     />
     <Text style={{position: 'absolute', fontSize: 20}}>890</Text>
 </View>

I'm researching if it is easily possible with React Native or whether I should build a native app.

This sounds very doable in react-native

I want to edit an image from the photo library and add a text overlay to it. Think of it like a postcard with a greeting message on it.

I think I would capture ALL the relevant metadata as an object...

{
    image: {
        uri: './assets/image.jpg',
        height: 576,
        width: 1024
    },
    message: {
        fontFace: 'Calibri',
        fontSize: 16,
        text: 'Happy Holidays!'
        boundingBox: { 
            height: '30%',
            width: '30%',
            top: 0,
            left: 0
        }
    }
}

With the above detail (and maybe more), you'd then be able to reconstruct the design intent on any device, regardless of size (tablet vs mobile) or pixel depth. The boundingBox would be expressed in terms relative to the image's rendered dimensions. In the above example, the message would be contained in a text box no more than 30% of the image width, 30% of its height, and positioned in the top-left corner.

How would I add text to an image and make a new copy of it in react native?

This eliminates the need to do any screenshotting or actual image manipulation, etc. No need to "make a new copy". Just treat them as two separate and distinct assets, then merge them at render using the metadata you captured.

Final thought: if you "need" to "upload the finished photo to a server" as you stated in another comment to another solution, you can do this serverside using any number of technologies using the metadata as your guide.

If you need to only show a text over the image you can wrap the image in a view and after the image insert a text element with position: 'absolute'. If you want a copy of the image containing the text then you can use the same approach but take a snapshot using react-native-view-shot

Below code is what I used to add text on image at particular coordinates on image.

Xcode 8.3.2 Swift 3.1

func textToImage(drawText text: NSString, inImage image: UIImage, atPoint point: CGPoint) -> UIImage {
        let textColor = UIColor.white
        let textFont = UIFont(name: "Helvetica Bold", size: 10)!

        let scale = UIScreen.main.scale
        UIGraphicsBeginImageContextWithOptions(image.size, false, scale)

        let textFontAttributes = [
            NSFontAttributeName: textFont,
            NSForegroundColorAttributeName: textColor,
            ] as [String : Any]
        image.draw(in: CGRect(origin: CGPoint.zero, size: image.size))

        let rect = CGRect(origin: point, size: image.size)
        text.draw(in: rect, withAttributes: textFontAttributes)

        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()


        return newImage!
    }

And call above method as below

let imageWithText = textToImage(drawText: "textOnImage", inImage:yourImage, atPoint: CGPoint(x:9,y:11))

As far as I know, the image component can be used as a container so you can do something like this:

<Image>
  <Text>{"some text"}</Text>
</Image>

There are several libraries available for that. If you want to add a text to an image you can use: react-native-media-editor. This is quite a good option for adding text to an image but I recommend you react-native-image-tools. It provides so much flexibility. You can add a text and position it accordingly. Apart from that, there are filters, cropping option, light adjustments and so much more.

It depends on the use case but if you simply want to put a text on an image, using ImageBackground is a one of the good approach.

Do it like below.

<ImageBackground
  source={{ uri: hoge }}
  style={{
    height: 105,
    width: 95,
    position: 'relative', // because it's parent
    top: 7,
    left: 5
  }}
>
  <Text
    style={{
      fontWeight: 'bold',
      color: 'white',
      position: 'absolute', // child
      bottom: 0, // position where you want
      left: 0
    }}
  >
    hoge
  </Text>
</ImageBackground>

Related