github.com/go-oss/image@v0.1.1-0.20230517025328-001b78555e78/imageutil/decode.go (about)

     1  // Package imageutil wrapper for jpeg.DecodeWithQuality & remove exif, apply orientation.
     2  package imageutil
     3  
     4  import (
     5  	"bytes"
     6  	"errors"
     7  	"image"
     8  	"io"
     9  
    10  	jq "github.com/go-oss/image/jpeg"
    11  	"github.com/rwcarlsen/goexif/exif"
    12  
    13  	// use webp decoder
    14  	_ "golang.org/x/image/webp"
    15  )
    16  
    17  var (
    18  	// ErrUnsupportedFileType represents unsupported error.
    19  	ErrUnsupportedFileType = errors.New("unsupported file type")
    20  )
    21  
    22  // Image represents image.Image wrapper.
    23  type Image struct {
    24  	Image            image.Image
    25  	Quality          int
    26  	OriginalMIMEType MIMEType
    27  }
    28  
    29  // Decode image file.
    30  func Decode(file io.Reader) (*Image, error) {
    31  	fileHeader := make([]byte, 512)
    32  	_, err := file.Read(fileHeader)
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  
    37  	multiReader := io.MultiReader(bytes.NewBuffer(fileHeader), file)
    38  
    39  	mimeType := DetectMimeType(fileHeader)
    40  	if mimeType == UndefinedType {
    41  		return nil, ErrUnsupportedFileType
    42  	}
    43  
    44  	buff := new(bytes.Buffer)
    45  	reader := io.TeeReader(multiReader, buff)
    46  
    47  	img := &Image{
    48  		OriginalMIMEType: mimeType,
    49  	}
    50  
    51  	if mimeType == JPEG {
    52  		img.Image, img.Quality, err = jq.DecodeWithQuality(reader)
    53  		if err != nil {
    54  			return nil, err
    55  		}
    56  
    57  		// check EXIF and apply orientation
    58  		meta, decodeErr := exif.Decode(buff)
    59  		// if error occurred, exif is invalid and discarded.
    60  		if decodeErr == nil {
    61  			newImg, _ := applyOrientation(img.Image, meta)
    62  			if newImg != nil {
    63  				img.Image = newImg
    64  			}
    65  		}
    66  	} else {
    67  		img.Image, _, err = image.Decode(reader)
    68  		if err != nil {
    69  			return nil, err
    70  		}
    71  	}
    72  
    73  	return img, nil
    74  }