// MetadataImage returns Metadata from an Image. Format is always unset. func MetadataImage(image *vips.Image) Metadata { o := DetectOrientation(image) w, h := o.Dimensions(image.Xsize(), image.Ysize()) if w <= 0 || h <= 0 { panic("Invalid image dimensions.") } return Metadata{Width: w, Height: h, Orientation: o, HasAlpha: image.HasAlpha()} }
func jpegSave(image *vips.Image, options SaveOptions) ([]byte, error) { // JPEG interlace saves 2-3%, but incurs a few hundred bytes of // overhead, requires buffering the image completely in RAM for // encoding and decoding, and takes over 3x the CPU. This isn't // usually beneficial on small images and is too expensive for large // images. pixels := image.Xsize() * image.Ysize() interlace := pixels >= 200*200 && pixels <= 1024*1024 // Strip and optimize both save space, enable them. return image.JpegsaveBuffer(true, options.Quality, true, interlace) }
func useLossless(image *vips.Image, options SaveOptions) bool { if !options.Lossless { return false } if !options.LossyIfPhoto { return true } // Mobile devices start being unwilling to load >= 3 megapixel PNGs. // Also we don't want to bother to edge detect on large images. if image.Xsize()*image.Ysize() >= 3*1024*1024 { return false } // Take a histogram of a Sobel edge detect of our image. What's the // highest number of histogram values in a row that are more than 1% // of the maximum value? Above 16 indicates a photo. metric, err := image.PhotoMetric(0.01) return err != nil || metric < 16 }