Примените фоновый цвет при аннотировании изображения текстом, используя Magick.Net

Я использую C# и Magick.Net, чтобы комментировать изображения следующим образом:

var text = "Variable text";
var img = new MagickImage("image.jpg");
img.FontPointsize = 50;
img.FillColor = new MagickColor(Color.White);
img.Annotate(text, Gravity.Northwest);

Аннотация работает, однако текст не всегда легко читается, так как он может сочетаться с изображением.

Руководство ImageMagick имеет полный раздел, предлагающий решения для этого:

  • Изложил ярлык

    convert dragon.gif -gravity south \
      -stroke '#000C' -strokewidth 2 -annotate 0 'Faerie Dragon' \
      -stroke  none   -fill white    -annotate 0 'Faerie Dragon' \
      anno_outline.jpg
    
  • Draw Dim Box

    convert dragon.gif \
      -fill '#0008' -draw 'rectangle 5,128,114,145' \
      -fill white   -annotate +10+141 'Faerie Dragon' \
      anno_dim_draw.jpg
    

(Я бы использовал этот метод, только если больше ничего не работает, потому что он требует явного определения ширины и высоты прямоугольника.)

  • Undercolor Box

    convert dragon.gif  -fill white  -undercolor '#00000080'  -gravity South \
      -annotate +0+5 ' Faerie Dragon '     anno_undercolor.jpg
    
  • Составная метка

    convert -background '#00000080' -fill white label:'Faerie Dragon' miff:- |\
          composite -gravity south -geometry +0+3 \
          -   dragon.gif   anno_composite.jpg
    
  • Авторазмер заголовка

    width=`identify -format %w dragon.gif`; \
    convert -background '#0008' -fill white -gravity center -size ${width}x30 \
      caption:"Faerie Dragons love hot apple pies\!" \
      dragon.gif +swap -gravity south -composite  anno_caption.jpg
    
  • Необычная этикетка

    convert -size 100x14 xc:none -gravity center \
      -stroke black -strokewidth 2 -annotate 0 'Faerie Dragon' \
      -background none -shadow 100x3+0+0 +repage \
      -stroke none -fill white     -annotate 0 'Faerie Dragon' \
      dragon.gif  +swap -gravity south -geometry +0-3 \
      -composite  anno_fancy.jpg
    

Любой из вышеперечисленных подходов будет хорошо для меня. Тем не менее, я не могу найти необходимую функциональность в.Net API. Например, я пытался установить BackgroundColor перед вызовом Annotate. Это не произвело никакого эффекта:

img.BackgroundColor = new MagickColor(Color.Black);

Я хотел бы получить несколько советов о том, как реализовать любой метод, который повышает удобочитаемость текста аннотации, используя Magick.Net.

3 ответа

Решение

В итоге я реализовал опцию Composited Label следующим образом:

var text = "Variable text";
var img = new MagickImage("image.jpg");

using (var imgText = new MagickImage())
{
     imgText.FontPointsize = 50;
     imgText.BackgroundColor = new MagickColor(Color.Black);
     imgText.FillColor = new MagickColor(Color.White);
     imgText.Read("label:" + text);
     img.Composite(text, Gravity.Northwest);
}

Хитрость заключается в том, чтобы "прочитать" изображение, но предоставить label: запись вместо имени файла. Как только это будет сделано, мы можем просто скомбинировать сгенерированное изображение с оригинальным.

Помимо добавления черного фона к текстовой аннотации, этот код дает тот же результат, что и тот, который размещен в вопросе.

Просто еще один способ, похожий на @user1942447

      string textToAdd = "ultra wide text with /r/n multiline row";

var readSettings = new MagickReadSettings
{
    Font = "Arial",
    TextGravity = Gravity.Center,
    BackgroundColor = MagickColors.Transparent,
    Height = 200, // height of text box
    Width = 300 // width of text box
};

using (var tImage = new MagickImage())
{
    using (var caption = new MagickImage($"label:{textToAdd}", readSettings))
    {
        //image is your main image where you need to put text
        image.Composite(caption, 10, 20, CompositeOperator.Over);    
        image.Write(AppContext.BaseDirectory + Guid.NewGuid() + ".png");
    }
}

Размер текста будет изменяться автоматически в зависимости от размера текстового поля. Если вам нужен строгий размер шрифта, используйте свойство FontPointsize, но текст может выходить за границы.

Для всех, кто пытается выяснить, как разместить текст на изображениях.

Это похоже на код, который я использую для добавления текста к изображениям в Magick.NET.

Используйте этот код в качестве фрагмента LINQPad. Используйте пакет Nuge t Magick.NET-Q16-AnyCPU.

void Main()
{
    TextRender();
}

public void TextRender()
{
    //If you use a transparent color here, you won't see the text
    var imageBackgroundColor = new MagickColor("White");

    using (MagickImage image = new MagickImage(imageBackgroundColor, 400, 400))
    {
        var drawable = new DrawableText(0,10,"Line One\nLine Two\nLine Three");
        var gravity = new DrawableGravity(Gravity.North);
        var font = new DrawableFont("Arial");
        var antialias = new DrawableTextAntialias(true);
        var size = new DrawablePointSize(50);
        var color = new DrawableFillColor(Color.Black);
        //If needed
        //var strokeColor = new DrawableStrokeColor(Color.White);

        image.Annotate("Some annotation", Gravity.Center);

        image.Draw(drawable, gravity, font, antialias, size, color);//, strokeColor);

        var imageFileName = @"c:\temp\tempImage.jpg";

        //Write the file to disk
        image.Write(imageFileName);

        //For use in linqpad only
        //Load the written file from disk and show it in the Results window
        var image2 = (Bitmap) Image.FromFile(imageFileName, true);
        image2.Dump();
    }
}

Это результат:

Другие вопросы по тегам