brendan-duncan / image

Dart Image Library for opening, manipulating, and saving various different image file formats.
MIT License
1.14k stars 255 forks source link

I want to use custom font size in Flutter Image.drawString #615

Open MayurSankhla opened 4 months ago

MayurSankhla commented 4 months ago

This is about Flutter, Dart, Image, specifically drawString function.

First of all, what I am trying to do is watermark the picture taken with the text (product name). I mean not just placing text over the image but actually merge it with picture so that the user can submit the picture and share it while sharing the product.

To do so. I found the right function drawString(), but the problem is it only supports arial48, arial24 and arial14 font sizes. Since I have to write the product name in custom fontsize which I'm extracting by calculating the width and height of the original image. Is there any one who tried this before or any who can make it possible. Anyone who knows?

I've tried this.

` import 'package:image/image.dart' as img;

img.drawString(originalImage,'$myProductName($pictureTag)', x: value, y: value, color: img.ColorFloat32.rgb(255,255,255), font: img.arial48, ); ` But I need to use custom font size instead of these predefined sizes.

I'm using flutter: 3.19.0 version. and image: ^4.1.7

brendan-duncan commented 4 months ago

Font support is very limited, just fixed size bitmap fonts (as you've discovered). You can create your own fonts to use with drawString, I made a brief doc on it at https://github.com/brendan-duncan/image/blob/main/doc/fonts.md.

MayurSankhla commented 4 months ago

Please explain a brief more. if I want custom font size while processing the image then what I need to do? will I've to use multiple .ttf files of different font sizes?

brendan-duncan commented 4 months ago

Yes, there is no variable sized font rendering.

ivictoruan commented 3 months ago

Hello! There are others contents where I can learn how to create custom fonts? I'm creating a watermark and there is an image and text. So accoding image size I would like to change the sizes.

FS-17 commented 2 months ago

I found a workaround to use custom font but it only works with flutter. here is how you can do it:

  1. you need to import flutter material,typed_data and dart ui:

    import 'package:flutter/material.dart';
    import 'dart:ui';
    import 'dart:typed_data';
  2. create a TextStyle within a TextSpan:

    TextSpan textSpan = TextSpan(
    text: 'Hello World',
    style: TextStyle(
    fontFamily: 'YourFont',
    fontSize: 20,
    color: Colors.black,
    ),
    );
  3. create a TextPainter and layout the text:

    TextPainter textPainter = TextPainter(
    text: textSpan,
    textDirection: TextDirection.ltr,
    );
    textPainter.layout();
  4. Then create a canvas and paint the text, so you can convert it to an image:

    PictureRecorder recorder = PictureRecorder();
    Canvas canvas = Canvas(recorder);
    textPainter.paint(canvas, Offset(0, 0));
    Picture picture = recorder.endRecording();
    
    final image = await picture.toImage(textPainter.width.toInt(), textPainter.height.toInt());
  5. Then you can convert the image to a byte array and to an image object from dart image lib:

    ByteData? byteData = await image.toByteData(format: ImageByteFormat.png);
    Uint8List pngBytes = byteData!.buffer.asUint8List();
    final textimg = img.decodeImage(pngBytes)!;

    now textimg is an Image object from dart image lib, its only text so you can add it to another image or save it as a file.

to add it to another image you can do this:

composite(otherimage, textimg, dstX: 0, dstY: 0);

the whole code should look like this:

import 'package:flutter/material.dart';
import 'package:image/image.dart' as img;
import 'dart:ui';
import 'dart:typed_data';

void main() async {
  TextSpan textSpan = TextSpan(
    text: 'Hello World',
    style: TextStyle(
      fontFamily: 'YourFont',
      fontSize: 20,
      color: Colors.black,
    ),
  );

  TextPainter textPainter = TextPainter(
      text: textSpan,
      textDirection: TextDirection.ltr,
  );
  textPainter.layout();

  PictureRecorder recorder = PictureRecorder();

  Canvas canvas = Canvas(recorder);
  textPainter.paint(canvas, Offset(0, 0));
  Picture picture = recorder.endRecording();

  final image = await picture.toImage(
      textPainter.width.toInt(), textPainter.height.toInt());

  ByteData? byteData = await image.toByteData(format: ImageByteFormat.png);
  Uint8List pngBytes = byteData!.buffer.asUint8List();
  final textimg = img.decodeImage(pngBytes)!;

  Image otherimage = readPng('path/to/your/image.png');
  composite(otherimage, textimg, dstX: 0, dstY: 0);
}

its only a workaround but it works, i hope it helps you.

FS-17 commented 2 months ago

@brendan-duncan can we implement this in the library, it will solve a lot of text rendering problems

brendan-duncan commented 2 months ago

I can't add the Flutter dependencies to the image package. That could be done in a separate package, and it would be awesome if it were. I won't able to do that myself, it opens up too many maintenance issues and I already have more projects than time. I somewhat regret adding any font / text rendering to this library at all, it's one of the main things complained about, and text rendering is a hugely complicated issue, especially with non-ASCII. But I appreciate the desire to have it, I wish I could offer more.

FS-17 commented 2 months ago

i made that as a separate package, so it will be easier to maintain and update, this is the link to the package: https://pub.dev/packages/draw_text