Search code examples
iosimage-processingimagemagickdistortion

ios - ImageMagick How to code to apply ShepardsDistortion on image


I am new to ImageMagick,and i want to develop an effect of ShepardsDistortion on source image. i gone through many posts and sites, but i didn't find way to implement "ShepardsDistortion" in iOS.

    MagickWand *mw = NewMagickWand();
    MagickSetFormat(mw, "png");

    UIImage *sourceImage=[_sourceImgView image];
    NSData *imgData=UIImagePNGRepresentation(sourceImage);
    MagickReadImageBlob(mw, [imgData bytes], [imgData length]);
    Image *image=GetImageFromMagickWand(mw);

    DistortImage(image, ShepardsDistortion, , ,);

I done upto this, but i dont know what to pass as arg in DitortImage(). So if anyone knows then help me.

EDIT:

-(void)distortImage{

    MagickWandGenesis();
    MagickWand * wand;
    MagickBooleanType status;

    wand = NewMagickWand();
    MagickSetFormat(wand, "png");
    status = MagickReadImage(wand,"chess.png");

    // Arguments for Shepards
    double points[8];
    points[0] = 250; // First X point (starting)
    points[1] = 250; // First Y point (starting)
    points[2] =  50; // First X point (ending)
    points[3] = 150; // First Y point (ending)
    points[4] = 500; // Second X point (starting)
    points[5] = 380; // Second Y point (starting)
    points[6] = 600; // Second X point (ending)
    points[7] = 460; // Second Y point (ending)


    MagickDistortImage(wand,ShepardsDistortion,8,points,MagickFalse);
    NSString * tempFilePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"out.png"];
    MagickWriteImage(wand,[tempFilePath cStringUsingEncoding:NSASCIIStringEncoding]);
    UIImage * imgObj = [UIImage imageWithContentsOfFile:tempFilePath];
    _resultImgView.image=imgObj;

//    
//    unsigned char * cBlob;
//    size_t data_size;
//    cBlob = MagickGetImageBlob(wand, &data_size);
//    NSData * nsBlob = [NSData dataWithBytes:cBlob length:data_size];
//    UIImage *uiImage = [UIImage imageWithData:nsBlob];
//    _resultImgView.image=uiImage;

    MagickWriteImage(wand,"out.png");
    wand=DestroyMagickWand(wand);
    MagickWandTerminus();
}

Solution

  • Arguments are passed to DistortImage as the start of a list of doubles, and size information about the list. Example:

    size_t SizeOfPoints = 8;
    double Points[SizeOfPoints];
    DistortImage(image,
                 ShepardsDistoration,
                 SizeOfPoints,
                 Points,
                 MagickFalse,
                 NULL
                );
    

    In your example, you seem to be mixing MagickWand & MagickCore methods; which, seems unnecessary and confusing. I would keep this distortion simple, and only use MagickWand's MagickDistortImage method. Here's a example in

    int main(int argc. const char **argv)
    {
      MagickWandGenesis();
      MagickWand * wand;
      MagickBooleanType status;
    
      wand = NewMagickWand();
      status = MagickReadImage(wand,"logo:");
    
      // Arguments for Shepards
      double points[8];
      // 250x250 -> 50x150
      points[0] = 250; // First X point (starting)
      points[1] = 250; // First Y point (starting)
      points[2] =  50; // First X point (ending)
      points[3] = 150; // First Y point (ending)
      // 500x380 -> 600x460
      points[4] = 500; // Second X point (starting)
      points[5] = 380; // Second Y point (starting)
      points[6] = 600; // Second X point (ending)
      points[7] = 460; // Second Y point (ending)
    
      MagickDistortImage(wand,ShepardsDistortion,8,points,MagickFalse);
      MagickWriteImage(wand,"out.png");
    
      wand=DestroyMagickWand(wand);
      MagickWandTerminus();
    
      return 0;
    }
    

    Resulting in a distorted translated image (details)

    ShepardsDistortion Example

    Edit

    For iOS, you can use NSTemporaryDirectory (like in this answer), or create an image dynamically using NSData (like in this question).

    Example with temporary path:

    NSString * tempFilePath = [NSTemporaryDirectory() 
                                 stringByAppendingPathComponent:@"out.png"];
    MagickWriteImage(self.wand,
        [tempFilePath cStringUsingEncoding:NSASCIIStringEncoding]);
    UIImage * imgObj = [UIImage imageWithContentsOfFile:tempFilePath];
    

    And an example with NSData + blob

    unsigned char * cBlob;
    size_t data_size;
    cBlob = MagickGetImageBlob(wand, &data_size);
    NSData * nsBlob = [NSData dataWithBytes:cBlob length:data_size];
    UIImage * uiImage = [UIImage imageWithData:nsBlob];