JVK
JVK

Reputation: 3912

Setting opacity of image in golang

I have following code. That does paste a foreground image (logo.jpg) over background image (background.jpg) While pasting this foreground image, I want to set the opacity of this foreground image. I used DrawMask (http://golang.org/doc/articles/image_draw.html), but it seems I am missing something here. Please see the code below. Anyone has any idea?

package main

    import (
    "os"
    "image/draw"
    "image"
    "image/jpeg"
)

func main() {
//Background image
    fImg1, _ := os.Open("background.jpg")
    defer fImg1.Close()
    img1, _, _ := image.Decode(fImg1)

//Logo to stick over background image
    fImg2, _ := os.Open("logo.jpg")
    defer fImg2.Close()
    img2, _, _ := image.Decode(fImg2)

//Mask image (that is just a solid light gray image of same size as logo)
    fmask, _ := os.Open("mask.jpg")
    defer fImg2.Close()
    mask, _, _ := image.Decode(fmask)

//Create a new blank image m
    m := image.NewRGBA(image.Rect(0, 0, 1920, 1280))

//Paste background image over m
    draw.Draw(m, m.Bounds(), img1, image.Point{0,0}, draw.Src)

//Now paste logo image over m using a mask (ref. http://golang.org/doc/articles/image_draw.html )

//******Goal is to have opacity value 50 of logo image, when we paste it****
    draw.DrawMask(m, m.Bounds(), img2, image.Point{-100,-100}, mask, image.Point{-100,-100}, draw.Src)

     toimg, _ := os.Create("new.jpg")
     defer toimg.Close()

     jpeg.Encode(toimg, m, &jpeg.Options{jpeg.DefaultQuality})
}

Above code is helped by Sathish (http://stackoverflow.com/questions/12430874/image-manipulation-in-golang). Thanks Sathish.

Upvotes: 3

Views: 4978

Answers (2)

sathishvj
sathishvj

Reputation: 1464

Since you want to base the mask off of another image, you probably have to do a conversion of the grayscale to an alpha mask. The below code works nicely on a sample that I tried.

package main

import (
    "fmt"
    "image"
    "image/color"
    "image/draw"
    "image/jpeg"
    "os"
)

func main() {

    fBg, err := os.Open("bkground.jpg")
    defer fBg.Close()
    bg, _, err := image.Decode(fBg)

    fSrc, err := os.Open("arrow1.jpg")
    defer fSrc.Close()
    src, _, err := image.Decode(fSrc)

    fMaskImg, err := os.Open("mask.jpg")
    defer fMaskImg.Close()
    maskImg, _, err := image.Decode(fMaskImg)

    bounds := src.Bounds() //you have defined that both src and mask are same size, and maskImg is a grayscale of the src image. So we'll use that common size.
    mask := image.NewAlpha(bounds)
    for x := 0; x < bounds.Dx(); x++ {
        for y := 0; y < bounds.Dy(); y++ {
            //get one of r, g, b on the mask image ...
            r, _, _, _ := maskImg.At(x, y).RGBA()
            //... and set it as the alpha value on the mask.  
            mask.SetAlpha(x, y, color.Alpha{uint8(255 - r)}) //Assuming that white is your transparency, subtract it from 255
        }
    }

    m := image.NewRGBA(bounds)
    draw.Draw(m, m.Bounds(), bg, image.ZP, draw.Src)

    draw.DrawMask(m, bounds, src, image.ZP, mask, image.ZP, draw.Over)

    toimg, _ := os.Create("new.jpeg")
    defer toimg.Close()

    err = jpeg.Encode(toimg, m, nil)
    if err != nil {
        fmt.Println("Error: " + err.Error())
    }
}
  • Extra note: while converting a jpeg image to grayscale in gimp, I noticed that it is automatically saving with some options that the image package could not decode. So you might want to check the error values after each of the operations. To reduce code size, I've mostly removed it here.

Upvotes: 2

Stephen Weinberg
Stephen Weinberg

Reputation: 53418

I see two errors with your code.

  1. You are setting the mask incorrectly. To get 50% opacity you want something like mask := image.NewUniform(color.Alpha{128}) where 128 is half way between 0 (transparent), and 255 (opaque). If you want more than 256 levels of opacity, see color.Alpha16.

  2. When calling draw.DrawMask(), you most likely want to use the draw.Over Op instead of draw.Src. Try them both out and you should see the difference.

I also recommend m := image.NewRGBA(img1.Bounds()), but it is not wrong to do it manually.

Upvotes: 5

Related Questions