How to stop ImageMagick in Ruby (Rmagick) evaluating an @ sign in text annotation

StackOverflow https://stackoverflow.com/questions/18697306

  •  28-06-2022
  •  | 
  •  

سؤال

In an app I recently built for a client the following code resulted in the variable @nameText being evaluated, and then resulting in an error 'no text' (since the variable doesn't exist).

To get around this I used gsub, as per the example below. Is there a way to tell Magick not to evaluate the string at all?

require 'RMagick'

@image = Magick::Image.read( '/path/to/image.jpg' ).first
@nameText = '@SomeTwitterUser'
@text = Magick::Draw.new
@text.font_family = 'Futura'
@text.pointsize = 22
@text.font_weight = Magick::BoldWeight

# Causes error 'no text'...
# @text.annotate( @image, 0,0,200,54, @nameText )

@text.annotate( @image, 0,0,200,54, @nameText.gsub('@', '\@') )
هل كانت مفيدة؟

المحلول

This is the C code from RMagick that is returning the error:

// Translate & store in Draw structure
draw->info->text = InterpretImageProperties(NULL, image, StringValuePtr(text));
if (!draw->info->text)
{
    rb_raise(rb_eArgError, "no text");
}

It is the call to InterpretImageProperties that is modifying the input text - but it is not Ruby, or a Ruby instance variable that it is trying to reference. The function is defined here in the Image Magick core library: http://www.imagemagick.org/api/MagickCore/property_8c_source.html#l02966

Look a bit further down, and you can see the code:

/* handle a '@' replace string from file */
if (*p == '@') {
   p++;
   if (*p != '-' && (IsPathAccessible(p) == MagickFalse) ) {
     (void) ThrowMagickException(&image->exception,GetMagickModule(),
         OptionError,"UnableToAccessPath","%s",p);
     return((char *) NULL);
   }
   return(FileToString(p,~0,&image->exception));
}

In summary, this is a core library feature which will attempt to load text from file (named SomeTwitterUser in your case, I have confirmed this -try it!), and your work-around is probably the best you can do.

For efficiency, and minimal changes to input strings, you could rely on the selectivity of the library code and only modify the string if it starts with @:

@text.annotate( @image, 0,0,200,54, @name_string.gsub( /^@/, '\@') )
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top