0

I am using the following code which fetch the object from Amazon s3 and after performing resizing and cropping. I want to store it on s3. But the problem is i am not able convert the mw (Image maigck object) to byte array. Which will be used for storing it on s3. Moreover in current method it uses jpeg.Encode. What if the image in .png or .gif format. How will we convert it to []byte?

Could you please also tell me how to evenly crop an image just passing the aspect ratio not cropping coordinates. imgStream.Crop((int)originalWidth, ((int)(originalWidth / masterAspectRatio)), Gravity.Center) like we do it in .net. Reason i am asking is there is no method in library which provides this flexibility.

s3Client := s3.New(session.New(), &aws.Config{Region: aws.String(region)})
            params := &s3.GetObjectInput{
            Bucket: aws.String(bucketName),
            Key: aws.String(keyName),
            }

        out, err := s3Client.GetObject(params)

        if err != nil {
             log.Fatal(err)
        }

        img, err := ioutil.ReadAll(out.Body)
        if err != nil {
            log.Fatal(err)
        }      

        mw := imagick.NewMagickWand()   

        err = mw.ReadImageBlob(img)
        if err != nil {
            log.Fatal(err)
        }

        //Perform resizing and cropping on mw object

        buf := new(bytes.Buffer)
        err = jpeg.Encode(buf, mw, nil)
        sendmw_s3 := buf.Bytes()

         paramsPut := &s3.PutObjectInput{
                        Bucket:         aws.String(masterBucketName),
                        Key:            aws.String(keyName),
                        Body:         bytes.NewReader(sendmw_s3),
                }

        resp, err := s3Client.PutObject(paramsPut)
        if err != nil {
            log.Fatal(err)
        }

Error :

 cannot use mw (type *imagick.MagickWand) as type image.Image in argument to jpeg.Encode:
    *imagick.MagickWand does not implement image.Image (missing At method)
Danack
  • 24,939
  • 16
  • 90
  • 122
Naresh
  • 5,073
  • 12
  • 67
  • 124
  • 5
    A quick inspection of the imagick API lead me to https://gowalker.org/github.com/gographics/imagick/imagick#MagickWand_GetImageBlob which seems to return an already encoded []byte in the needed format (JPEG, Gif...). Isn't it what you need ? – SirDarius Feb 03 '16 at 14:41
  • @SirDarius Thanks, didn't notice that. – Naresh Feb 03 '16 at 16:35
  • Also, `SetImageFormat()` can convert the format before you call `GetImageBlob()` – jdi Feb 03 '16 at 19:56

2 Answers2

2

You need to use the func (mw *MagickWand) GetImageBlob() []byte function.

It returns a slice of bytes containing a complete encoded image for the current file format (JPEG, gif, PNG...).

The returned data can therefore be saved to disk, or sent to s3 as-is.

See https://gowalker.org/github.com/gographics/imagick/imagick#MagickWand_GetImageBlob for the documentation.

SirDarius
  • 41,440
  • 8
  • 86
  • 100
1

This question is actually two questions, and @SirDarius answered one of them, by suggesting the use of GetImageBlob(). You can also use SetImageFormat() to change the image format before generating the blob.

For the part about the crop, I am sure there are a bunch of ways to do this with ImageMagick. The way I have done it, to achieve a center crop is to first transform the image so that the smaller dimension fits into my desired target resolution. And then to crop away the parts that overflow.

// Create a new image where smallest dimension is fit
// and the rest overflows the dimensions
size := fmt.Sprintf("%dx%d^+0+0", w, h)
tx := wand.TransformImage("", size)

// Center Crop away the extra parts of the image, to perform
tx.SetImageGravity(imagick.GRAVITY_CENTER)
offsetX := -(int(w) - int(tx.GetImageWidth())) / 2
offsetY := -(int(h) - int(tx.GetImageHeight())) / 2
err := tx.ExtentImage(w, h, offsetX, offsetY)
...
jdi
  • 90,542
  • 19
  • 167
  • 203
  • But here you are not taking use of aspect ratio. I have the requirement like let's say image is in 16:9 aspect ratio and then i need to convert it in nearest 4:3 aspect ratio. So, how do i it using above method – Naresh Feb 04 '16 at 06:55
  • Oh you don't want a center crop then. You want a fit and pad – jdi Feb 04 '16 at 07:00
  • Currently, I am using `mw.CropImage(uint(originalWidth), (uint(originalWidth / masterAspectRatio)), 0, 0)`. But it crops the image from origin and keep the width and height as mentioned. So, if let's say i want to change the aspect ratio from 16:9 to 4:3 then i want to crop the width from both the side and similarly if i want to change the aspect ration from 4:3 to 16:9 then i need to crop the height from both the side to get the image in desired aspect ratio . – Naresh Feb 04 '16 at 07:26
  • So, how as i mentioned in the question in the .net it could be done like `imgStream.Crop((int)originalWidth, ((int)(originalWidth / masterAspectRatio)), Gravity.Center`. Similarly how do i do it in go that is my question – Naresh Feb 04 '16 at 07:29
  • Out of curiosity have you even tried my suggestion or did you just look at it and assume it isn't what you want? because after yout comment, now it does sound like you want a proper center crop, which is what mine does – jdi Feb 04 '16 at 09:41
  • I resize it down to match a smaller target if necessary and then I crop it at the center – jdi Feb 04 '16 at 09:43
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/102573/discussion-between-naresh-and-jdi). – Naresh Feb 04 '16 at 10:01