1

There is really not much relevant info, and official manual makes me cry. I'm trying to run custom scripts via MagickCommandGenesis because I gave up in attempt to convert some scripts into clean c code with API usage. However, this piece of code:

    //char* cmdargs[] = { "convert", "-rotate", "-90" };
    char* cmdargs[] = { "-rotate", "-90" };
    int argcount = 2;

    ExceptionInfo* e = AcquireExceptionInfo();
    GetExceptionInfo(e);
    MagickBooleanType cmdres = MagickCommandGenesis(wand->image_info, ConvertImageCommand, argcount, cmdargs, NULL, e);

    if (e->severity != UndefinedException || cmdres == MagickFalse) {
        syslog(LOG_NOTICE, "mwb::error:%s", e->severity != UndefinedException ? "derp" : "undefined");
    }

always writes "undefined", i.e. MagickCommandGenesis returned false, but not throwed exception.

I can't use temporary files to read or write from, I want to do all operations in memory, therefore wand is read via MagickReadImageBlob. Blob is absolutely valid, I can do any API operations and finally draw image on screen, the only thing that not works is command run.

The only one relevant question I found is here but it not so useful. Even more, OP used read and write in files and still got the error. There is answer marked as accepted, but it suggest to use MagickCommandGenesis, what I do already.

Upd:

I figured out that image_info member of MagickWand actually has nothing (probably it just initialized with defaults and not used by MagickWand at all). So now I looking for proper way to instantiate ImageInfo structure from memory blob. That's what I tried:

    char* cmdargs[] = { "-rotate", "-90" };
    int argcount = 2;

    ExceptionInfo* e = AcquireExceptionInfo();
    GetExceptionInfo(e);

    size_t len;
    u_char* blob = MagickGetImageBlob(wand, &len);
    ImageInfo* info = CloneImageInfo(NULL);
    SetImageInfoBlob(info, blob, len);

    MagickBooleanType cmdres = MagickCommandGenesis(info, ConvertImageCommand, argcount, cmdargs, NULL, e);
    
    MagickWand* target = NewMagickWand();
    MagickReadImageBlob(target, info->blob, info->length);
    // DestroyMagickWand(wand);
    wand = target;

    syslog(LOG_NOTICE, "mwb::blob is %zu", MagickGetImageWidth(target));

    if (e->severity != UndefinedException || cmdres == MagickFalse) {
        syslog(LOG_NOTICE, "mwb::error:%s", e->severity != UndefinedException ? "derp" : "undefined");
    }

Unfortunately, I still get "undefined" error, so MagickCommandGenesis still returns false, but don't throws exception.

Community
  • 1
  • 1
Tommi
  • 3,199
  • 1
  • 24
  • 38
  • How is `wand->image_info` defined? – emcconville Aug 21 '14 at 17:34
  • It's an internal structure of ImageMagick core. I'm not familiar with its code, but struct looks like [this](https://github.com/trevor/ImageMagick/blob/master/trunk/MagickCore/image.h#L361). If you asking how I defined it, I don't. I supposed it defined when I read image to MagickWand. – Tommi Aug 21 '14 at 17:57
  • @emcconville ok, I realized that wand->image_info->length is 0 and blob is NULL, so looks like MagickWand don't fill this structure at all. Therefore, question changes to "Is it possible to instantiate proper ImageInfo from MagickWand to pass it to MagickCommandGenesis"? – Tommi Aug 21 '14 at 21:01
  • apologies, I thought I answered this back in August. I've attempted to re-post my original answer as I remember it. – emcconville Apr 27 '15 at 16:28
  • @emcconville Actually, I rewrote the whole project with openCV to achieve higher speed, but I'll try your answer because I still interested of how to solve this original question. – Tommi Apr 27 '15 at 17:26
  • OpenCV is a smart move ;) – emcconville Apr 27 '15 at 17:29

1 Answers1

1

Two items to consider.

First: MagickCommandGenesis is expecting a full, not partial, command. Example

 convert source.png -rotate -90 out.png

Second: ImageInfo pointer should be newly allocate memory for the command process to act against. Use AcquireImageInfo(), as givingwand->image_info will result in undefined behavior.

Ideally you should just use C-API methods exclusively, but you can mix existing MagickWand instances with MagickCommand by leveraging the memory program register protocol mpr:.

MagickWand *wand = NewMagickWand();
MagickReadImage(wand, "rose:");
MagickNegateImage(wand, 1); // For example, negate image
// Hand-off image to memory program register
MagickWriteImage(wand, "mpr:my_label");
// Build full command
char* cmdargs[] = {"convert",
                   "mpr:my_label",
                   "-rotate",
                   "-90",
                   "output.png", // Or to another mpr:
                   NULL};
 int argcount = 5;
 // Allocate memory for MagickCommand
 ImageInfo * info = AcquireImageInfo();
 ExceptionInfo* e = AcquireExceptionInfo();
 // Execute command
 MagickCommandGenesis(info, ConvertImageCommand, argcount, cmdargs, NULL, e);
 wand = DestroyMagickWand(wand);
 /* Error handling omitted */
emcconville
  • 23,800
  • 4
  • 50
  • 66