3 Star 0 Fork 0

Gitee 极速下载 / bimg

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
此仓库是为了提升国内下载速度的镜像仓库,每日同步一次。 原始仓库: https://github.com/h2non/bimg
克隆/下载
vips.go 22.51 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871
package bimg
/*
#cgo pkg-config: vips
#include "vips.h"
*/
import "C"
import (
"errors"
"fmt"
"math"
"os"
"runtime"
"strings"
"sync"
"unsafe"
)
// VipsVersion exposes the current libvips semantic version
const VipsVersion = string(C.VIPS_VERSION)
// VipsMajorVersion exposes the current libvips major version number
const VipsMajorVersion = int(C.VIPS_MAJOR_VERSION)
// VipsMinorVersion exposes the current libvips minor version number
const VipsMinorVersion = int(C.VIPS_MINOR_VERSION)
const (
maxCacheMem = 100 * 1024 * 1024
maxCacheSize = 500
)
var (
m sync.Mutex
initialized bool
)
// VipsMemoryInfo represents the memory stats provided by libvips.
type VipsMemoryInfo struct {
Memory int64
MemoryHighwater int64
Allocations int64
}
// vipsSaveOptions represents the internal option used to talk with libvips.
type vipsSaveOptions struct {
Speed int
Quality int
Compression int
Type ImageType
Interlace bool
NoProfile bool
StripMetadata bool
Lossless bool
InputICC string // Absolute path to the input ICC profile
OutputICC string // Absolute path to the output ICC profile
Interpretation Interpretation
Palette bool
}
type vipsWatermarkOptions struct {
Width C.int
DPI C.int
Margin C.int
NoReplicate C.int
Opacity C.float
Background [3]C.double
}
type vipsWatermarkImageOptions struct {
Left C.int
Top C.int
Opacity C.float
}
type vipsWatermarkTextOptions struct {
Text *C.char
Font *C.char
}
func init() {
Initialize()
}
// Initialize is used to explicitly start libvips in thread-safe way.
// Only call this function if you have previously turned off libvips.
func Initialize() {
if C.VIPS_MAJOR_VERSION <= 7 && C.VIPS_MINOR_VERSION < 40 {
panic("unsupported libvips version!")
}
m.Lock()
runtime.LockOSThread()
defer m.Unlock()
defer runtime.UnlockOSThread()
err := C.vips_init(C.CString("bimg"))
if err != 0 {
panic("unable to start vips!")
}
// Set libvips cache params
C.vips_cache_set_max_mem(maxCacheMem)
C.vips_cache_set_max(maxCacheSize)
// Define a custom thread concurrency limit in libvips (this may generate thread-unsafe issues)
// See: https://github.com/jcupitt/libvips/issues/261#issuecomment-92850414
if os.Getenv("VIPS_CONCURRENCY") == "" {
C.vips_concurrency_set(1)
}
// Enable libvips cache tracing
if os.Getenv("VIPS_TRACE") != "" {
C.vips_enable_cache_set_trace()
}
initialized = true
}
// Shutdown is used to shutdown libvips in a thread-safe way.
// You can call this to drop caches as well.
// If libvips was already initialized, the function is no-op
func Shutdown() {
m.Lock()
defer m.Unlock()
if initialized {
C.vips_shutdown()
initialized = false
}
}
// VipsCacheSetMaxMem Sets the maximum amount of tracked memory allowed before the vips operation cache
// begins to drop entries.
func VipsCacheSetMaxMem(maxCacheMem int) {
C.vips_cache_set_max_mem(C.size_t(maxCacheMem))
}
// VipsCacheSetMax sets the maximum number of operations to keep in the vips operation cache.
func VipsCacheSetMax(maxCacheSize int) {
C.vips_cache_set_max(C.int(maxCacheSize))
}
// VipsCacheDropAll drops the vips operation cache, freeing the allocated memory.
func VipsCacheDropAll() {
C.vips_cache_drop_all()
}
// VipsVectorSetEnabled enables or disables SIMD vector instructions. This can give speed-up,
// but can also be unstable on some systems and versions.
func VipsVectorSetEnabled(enable bool) {
flag := 0
if enable {
flag = 1
}
C.vips_vector_set_enabled(C.int(flag))
}
// VipsDebugInfo outputs to stdout libvips collected data. Useful for debugging.
func VipsDebugInfo() {
C.im__print_all()
}
// VipsMemory gets memory info stats from libvips (cache size, memory allocs...)
func VipsMemory() VipsMemoryInfo {
return VipsMemoryInfo{
Memory: int64(C.vips_tracked_get_mem()),
MemoryHighwater: int64(C.vips_tracked_get_mem_highwater()),
Allocations: int64(C.vips_tracked_get_allocs()),
}
}
// VipsIsTypeSupported returns true if the given image type
// is supported by the current libvips compilation.
func VipsIsTypeSupported(t ImageType) bool {
if t == JPEG {
return int(C.vips_type_find_bridge(C.JPEG)) != 0
}
if t == WEBP {
return int(C.vips_type_find_bridge(C.WEBP)) != 0
}
if t == PNG {
return int(C.vips_type_find_bridge(C.PNG)) != 0
}
if t == GIF {
return int(C.vips_type_find_bridge(C.GIF)) != 0
}
if t == PDF {
return int(C.vips_type_find_bridge(C.PDF)) != 0
}
if t == SVG {
return int(C.vips_type_find_bridge(C.SVG)) != 0
}
if t == TIFF {
return int(C.vips_type_find_bridge(C.TIFF)) != 0
}
if t == MAGICK {
return int(C.vips_type_find_bridge(C.MAGICK)) != 0
}
if t == HEIF {
return int(C.vips_type_find_bridge(C.HEIF)) != 0
}
if t == AVIF {
return int(C.vips_type_find_bridge(C.HEIF)) != 0
}
return false
}
// VipsIsTypeSupportedSave returns true if the given image type
// is supported by the current libvips compilation for the
// save operation.
func VipsIsTypeSupportedSave(t ImageType) bool {
if t == JPEG {
return int(C.vips_type_find_save_bridge(C.JPEG)) != 0
}
if t == WEBP {
return int(C.vips_type_find_save_bridge(C.WEBP)) != 0
}
if t == PNG {
return int(C.vips_type_find_save_bridge(C.PNG)) != 0
}
if t == TIFF {
return int(C.vips_type_find_save_bridge(C.TIFF)) != 0
}
if t == HEIF {
return int(C.vips_type_find_save_bridge(C.HEIF)) != 0
}
if t == AVIF {
return int(C.vips_type_find_save_bridge(C.HEIF)) != 0
}
if t == GIF {
return int(C.vips_type_find_save_bridge(C.GIF)) != 0
}
return false
}
func vipsExifStringTag(image *C.VipsImage, tag string) string {
return vipsExifShort(C.GoString(C.vips_exif_tag(image, C.CString(tag))))
}
func vipsExifIntTag(image *C.VipsImage, tag string) int {
return int(C.vips_exif_tag_to_int(image, C.CString(tag)))
}
func vipsExifOrientation(image *C.VipsImage) int {
return int(C.vips_exif_orientation(image))
}
func vipsExifShort(s string) string {
i := strings.Index(s, " (")
if i > 0 {
return s[:i]
}
return s
}
func vipsHasAlpha(image *C.VipsImage) bool {
return int(C.has_alpha_channel(image)) > 0
}
func vipsHasProfile(image *C.VipsImage) bool {
return int(C.has_profile_embed(image)) > 0
}
func vipsWindowSize(name string) float64 {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
return float64(C.interpolator_window_size(cname))
}
func vipsSpace(image *C.VipsImage) string {
return C.GoString(C.vips_enum_nick_bridge(image))
}
func vipsRotate(image *C.VipsImage, angle Angle) (*C.VipsImage, error) {
var out *C.VipsImage
defer C.g_object_unref(C.gpointer(image))
err := C.vips_rotate_bridge(image, &out, C.int(angle))
if err != 0 {
return nil, catchVipsError()
}
return out, nil
}
func vipsAutoRotate(image *C.VipsImage) (*C.VipsImage, error) {
var out *C.VipsImage
defer C.g_object_unref(C.gpointer(image))
err := C.vips_autorot_bridge(image, &out)
if err != 0 {
return nil, catchVipsError()
}
return out, nil
}
func vipsTransformICC(image *C.VipsImage, inputICC string, outputICC string) (*C.VipsImage, error) {
var out *C.VipsImage
defer C.g_object_unref(C.gpointer(image))
outputIccPath := C.CString(outputICC)
defer C.free(unsafe.Pointer(outputIccPath))
inputIccPath := C.CString(inputICC)
defer C.free(unsafe.Pointer(inputIccPath))
err := C.vips_icc_transform_with_default_bridge(image, &out, outputIccPath, inputIccPath)
//err := C.vips_icc_transform_bridge2(image, &outImage, outputIccPath, inputIccPath)
if int(err) != 0 {
return nil, catchVipsError()
}
return out, nil
}
func vipsFlip(image *C.VipsImage, direction Direction) (*C.VipsImage, error) {
var out *C.VipsImage
defer C.g_object_unref(C.gpointer(image))
err := C.vips_flip_bridge(image, &out, C.int(direction))
if err != 0 {
return nil, catchVipsError()
}
return out, nil
}
func vipsZoom(image *C.VipsImage, zoom int) (*C.VipsImage, error) {
var out *C.VipsImage
defer C.g_object_unref(C.gpointer(image))
err := C.vips_zoom_bridge(image, &out, C.int(zoom), C.int(zoom))
if err != 0 {
return nil, catchVipsError()
}
return out, nil
}
func vipsWatermark(image *C.VipsImage, w Watermark) (*C.VipsImage, error) {
var out *C.VipsImage
// Defaults
noReplicate := 0
if w.NoReplicate {
noReplicate = 1
}
text := C.CString(w.Text)
font := C.CString(w.Font)
background := [3]C.double{C.double(w.Background.R), C.double(w.Background.G), C.double(w.Background.B)}
textOpts := vipsWatermarkTextOptions{text, font}
opts := vipsWatermarkOptions{C.int(w.Width), C.int(w.DPI), C.int(w.Margin), C.int(noReplicate), C.float(w.Opacity), background}
defer C.free(unsafe.Pointer(text))
defer C.free(unsafe.Pointer(font))
err := C.vips_watermark(image, &out, (*C.WatermarkTextOptions)(unsafe.Pointer(&textOpts)), (*C.WatermarkOptions)(unsafe.Pointer(&opts)))
if err != 0 {
return nil, catchVipsError()
}
return out, nil
}
func vipsRead(buf []byte) (*C.VipsImage, ImageType, error) {
var image *C.VipsImage
imageType := vipsImageType(buf)
if imageType == UNKNOWN {
return nil, UNKNOWN, errors.New("Unsupported image format")
}
length := C.size_t(len(buf))
imageBuf := unsafe.Pointer(&buf[0])
err := C.vips_init_image(imageBuf, length, C.int(imageType), &image)
if err != 0 {
return nil, UNKNOWN, catchVipsError()
}
return image, imageType, nil
}
func vipsColourspaceIsSupportedBuffer(buf []byte) (bool, error) {
image, _, err := vipsRead(buf)
if err != nil {
return false, err
}
C.g_object_unref(C.gpointer(image))
return vipsColourspaceIsSupported(image), nil
}
func vipsColourspaceIsSupported(image *C.VipsImage) bool {
return int(C.vips_colourspace_issupported_bridge(image)) == 1
}
func vipsInterpretationBuffer(buf []byte) (Interpretation, error) {
image, _, err := vipsRead(buf)
if err != nil {
return InterpretationError, err
}
interp := vipsInterpretation(image)
C.g_object_unref(C.gpointer(image))
return interp, nil
}
func vipsInterpretation(image *C.VipsImage) Interpretation {
return Interpretation(C.vips_image_guess_interpretation_bridge(image))
}
func vipsFlattenBackground(image *C.VipsImage, background Color) (*C.VipsImage, error) {
var outImage *C.VipsImage
backgroundC := [3]C.double{
C.double(background.R),
C.double(background.G),
C.double(background.B),
}
if vipsHasAlpha(image) {
err := C.vips_flatten_background_brigde(image, &outImage,
backgroundC[0], backgroundC[1], backgroundC[2])
if int(err) != 0 {
return nil, catchVipsError()
}
C.g_object_unref(C.gpointer(image))
image = outImage
}
return image, nil
}
func vipsPreSave(image *C.VipsImage, o *vipsSaveOptions) (*C.VipsImage, error) {
var outImage *C.VipsImage
// Remove ICC profile metadata
if o.NoProfile {
C.remove_profile(image)
}
// Use a default interpretation and cast it to C type
if o.Interpretation == 0 {
o.Interpretation = InterpretationSRGB
}
interpretation := C.VipsInterpretation(o.Interpretation)
// Apply the proper colour space
if vipsColourspaceIsSupported(image) {
err := C.vips_colourspace_bridge(image, &outImage, interpretation)
if int(err) != 0 {
return nil, catchVipsError()
}
image = outImage
}
if o.OutputICC != "" && o.InputICC != "" {
outputIccPath := C.CString(o.OutputICC)
defer C.free(unsafe.Pointer(outputIccPath))
inputIccPath := C.CString(o.InputICC)
defer C.free(unsafe.Pointer(inputIccPath))
err := C.vips_icc_transform_with_default_bridge(image, &outImage, outputIccPath, inputIccPath)
if int(err) != 0 {
return nil, catchVipsError()
}
C.g_object_unref(C.gpointer(image))
return outImage, nil
}
if o.OutputICC != "" && vipsHasProfile(image) {
outputIccPath := C.CString(o.OutputICC)
defer C.free(unsafe.Pointer(outputIccPath))
err := C.vips_icc_transform_bridge(image, &outImage, outputIccPath)
if int(err) != 0 {
return nil, catchVipsError()
}
C.g_object_unref(C.gpointer(image))
image = outImage
}
return image, nil
}
func vipsSave(image *C.VipsImage, o vipsSaveOptions) ([]byte, error) {
defer C.g_object_unref(C.gpointer(image))
tmpImage, err := vipsPreSave(image, &o)
if err != nil {
return nil, err
}
// When an image has an unsupported color space, vipsPreSave
// returns the pointer of the image passed to it unmodified.
// When this occurs, we must take care to not dereference the
// original image a second time; we may otherwise erroneously
// free the object twice.
if tmpImage != image {
defer C.g_object_unref(C.gpointer(tmpImage))
}
length := C.size_t(0)
saveErr := C.int(0)
interlace := C.int(boolToInt(o.Interlace))
quality := C.int(o.Quality)
strip := C.int(boolToInt(o.StripMetadata))
lossless := C.int(boolToInt(o.Lossless))
palette := C.int(boolToInt(o.Palette))
speed := C.int(o.Speed)
if o.Type != 0 && !IsTypeSupportedSave(o.Type) {
return nil, fmt.Errorf("VIPS cannot save to %#v", ImageTypes[o.Type])
}
var ptr unsafe.Pointer
switch o.Type {
case WEBP:
saveErr = C.vips_webpsave_bridge(tmpImage, &ptr, &length, strip, quality, lossless)
case PNG:
saveErr = C.vips_pngsave_bridge(tmpImage, &ptr, &length, strip, C.int(o.Compression), quality, interlace, palette, speed)
case TIFF:
saveErr = C.vips_tiffsave_bridge(tmpImage, &ptr, &length)
case HEIF:
saveErr = C.vips_heifsave_bridge(tmpImage, &ptr, &length, strip, quality, lossless)
case AVIF:
saveErr = C.vips_avifsave_bridge(tmpImage, &ptr, &length, strip, quality, lossless, speed)
case GIF:
saveErr = C.vips_gifsave_bridge(tmpImage, &ptr, &length, strip)
default:
saveErr = C.vips_jpegsave_bridge(tmpImage, &ptr, &length, strip, quality, interlace)
}
if int(saveErr) != 0 {
return nil, catchVipsError()
}
buf := C.GoBytes(ptr, C.int(length))
// Clean up
C.g_free(C.gpointer(ptr))
C.vips_error_clear()
return buf, nil
}
func getImageBuffer(image *C.VipsImage) ([]byte, error) {
var ptr unsafe.Pointer
length := C.size_t(0)
interlace := C.int(0)
quality := C.int(100)
err := C.int(0)
err = C.vips_jpegsave_bridge(image, &ptr, &length, 1, quality, interlace)
if int(err) != 0 {
return nil, catchVipsError()
}
defer C.g_free(C.gpointer(ptr))
defer C.vips_error_clear()
return C.GoBytes(ptr, C.int(length)), nil
}
func vipsExtract(image *C.VipsImage, left, top, width, height int) (*C.VipsImage, error) {
var buf *C.VipsImage
defer C.g_object_unref(C.gpointer(image))
if width > maxSize || height > maxSize {
return nil, errors.New("Maximum image size exceeded")
}
top, left = max(top), max(left)
err := C.vips_extract_area_bridge(image, &buf, C.int(left), C.int(top), C.int(width), C.int(height))
if err != 0 {
return nil, catchVipsError()
}
return buf, nil
}
func vipsSmartCrop(image *C.VipsImage, width, height int) (*C.VipsImage, error) {
var buf *C.VipsImage
defer C.g_object_unref(C.gpointer(image))
if width > maxSize || height > maxSize {
return nil, errors.New("Maximum image size exceeded")
}
err := C.vips_smartcrop_bridge(image, &buf, C.int(width), C.int(height))
if err != 0 {
return nil, catchVipsError()
}
return buf, nil
}
func vipsTrim(image *C.VipsImage, background Color, threshold float64) (int, int, int, int, error) {
defer C.g_object_unref(C.gpointer(image))
top := C.int(0)
left := C.int(0)
width := C.int(0)
height := C.int(0)
err := C.vips_find_trim_bridge(image,
&top, &left, &width, &height,
C.double(background.R), C.double(background.G), C.double(background.B),
C.double(threshold))
if err != 0 {
return 0, 0, 0, 0, catchVipsError()
}
return int(top), int(left), int(width), int(height), nil
}
func vipsShrinkJpeg(buf []byte, input *C.VipsImage, shrink int) (*C.VipsImage, error) {
var image *C.VipsImage
var ptr = unsafe.Pointer(&buf[0])
defer C.g_object_unref(C.gpointer(input))
err := C.vips_jpegload_buffer_shrink(ptr, C.size_t(len(buf)), &image, C.int(shrink))
if err != 0 {
return nil, catchVipsError()
}
return image, nil
}
func vipsShrinkWebp(buf []byte, input *C.VipsImage, shrink int) (*C.VipsImage, error) {
var image *C.VipsImage
var ptr = unsafe.Pointer(&buf[0])
defer C.g_object_unref(C.gpointer(input))
err := C.vips_webpload_buffer_shrink(ptr, C.size_t(len(buf)), &image, C.int(shrink))
if err != 0 {
return nil, catchVipsError()
}
return image, nil
}
func vipsShrink(input *C.VipsImage, shrink int) (*C.VipsImage, error) {
var image *C.VipsImage
defer C.g_object_unref(C.gpointer(input))
err := C.vips_shrink_bridge(input, &image, C.double(float64(shrink)), C.double(float64(shrink)))
if err != 0 {
return nil, catchVipsError()
}
return image, nil
}
func vipsReduce(input *C.VipsImage, xshrink float64, yshrink float64) (*C.VipsImage, error) {
var image *C.VipsImage
defer C.g_object_unref(C.gpointer(input))
err := C.vips_reduce_bridge(input, &image, C.double(xshrink), C.double(yshrink))
if err != 0 {
return nil, catchVipsError()
}
return image, nil
}
func vipsEmbed(input *C.VipsImage, left, top, width, height int, extend Extend, background Color) (*C.VipsImage, error) {
var image *C.VipsImage
// Max extend value, see: https://libvips.github.io/libvips/API/current/libvips-conversion.html#VipsExtend
if extend > 5 {
extend = ExtendBackground
}
defer C.g_object_unref(C.gpointer(input))
err := C.vips_embed_bridge(input, &image, C.int(left), C.int(top), C.int(width),
C.int(height), C.int(extend), C.double(background.R), C.double(background.G), C.double(background.B))
if err != 0 {
return nil, catchVipsError()
}
return image, nil
}
func vipsAffine(input *C.VipsImage, residualx, residualy float64, i Interpolator, extend Extend) (*C.VipsImage, error) {
if extend > 5 {
extend = ExtendBackground
}
var image *C.VipsImage
cstring := C.CString(i.String())
interpolator := C.vips_interpolate_new(cstring)
defer C.free(unsafe.Pointer(cstring))
defer C.g_object_unref(C.gpointer(input))
defer C.g_object_unref(C.gpointer(interpolator))
err := C.vips_affine_interpolator(input, &image, C.double(residualx), 0, 0, C.double(residualy), interpolator, C.int(extend))
if err != 0 {
return nil, catchVipsError()
}
return image, nil
}
func vipsImageType(buf []byte) ImageType {
if len(buf) < 12 {
return UNKNOWN
}
if buf[0] == 0xFF && buf[1] == 0xD8 && buf[2] == 0xFF {
return JPEG
}
if IsTypeSupported(GIF) && buf[0] == 0x47 && buf[1] == 0x49 && buf[2] == 0x46 {
return GIF
}
if buf[0] == 0x89 && buf[1] == 0x50 && buf[2] == 0x4E && buf[3] == 0x47 {
return PNG
}
if IsTypeSupported(TIFF) &&
((buf[0] == 0x49 && buf[1] == 0x49 && buf[2] == 0x2A && buf[3] == 0x0) ||
(buf[0] == 0x4D && buf[1] == 0x4D && buf[2] == 0x0 && buf[3] == 0x2A)) {
return TIFF
}
if IsTypeSupported(PDF) && buf[0] == 0x25 && buf[1] == 0x50 && buf[2] == 0x44 && buf[3] == 0x46 {
return PDF
}
if IsTypeSupported(WEBP) && buf[8] == 0x57 && buf[9] == 0x45 && buf[10] == 0x42 && buf[11] == 0x50 {
return WEBP
}
if IsTypeSupported(SVG) && IsSVGImage(buf) {
return SVG
}
if IsTypeSupported(MAGICK) && strings.HasSuffix(readImageType(buf), "MagickBuffer") {
return MAGICK
}
// NOTE: libheif currently only supports heic sub types; see:
// https://github.com/strukturag/libheif/issues/83#issuecomment-421427091
if IsTypeSupported(HEIF) && buf[4] == 0x66 && buf[5] == 0x74 && buf[6] == 0x79 && buf[7] == 0x70 &&
buf[8] == 0x68 && buf[9] == 0x65 && buf[10] == 0x69 && buf[11] == 0x63 {
// This is a HEIC file, ftypheic
return HEIF
}
if IsTypeSupported(HEIF) && buf[4] == 0x66 && buf[5] == 0x74 && buf[6] == 0x79 && buf[7] == 0x70 &&
buf[8] == 0x6d && buf[9] == 0x69 && buf[10] == 0x66 && buf[11] == 0x31 {
// This is a HEIF file, ftypmif1
return HEIF
}
if IsTypeSupported(HEIF) && buf[4] == 0x66 && buf[5] == 0x74 && buf[6] == 0x79 && buf[7] == 0x70 &&
buf[8] == 0x6d && buf[9] == 0x73 && buf[10] == 0x66 && buf[11] == 0x31 {
// This is a HEIFS file, ftypmsf1
return HEIF
}
if IsTypeSupported(HEIF) && buf[4] == 0x66 && buf[5] == 0x74 && buf[6] == 0x79 && buf[7] == 0x70 &&
buf[8] == 0x68 && buf[9] == 0x65 && buf[10] == 0x69 && buf[11] == 0x73 {
// This is a HEIFS file, ftypheis
return HEIF
}
if IsTypeSupported(HEIF) && buf[4] == 0x66 && buf[5] == 0x74 && buf[6] == 0x79 && buf[7] == 0x70 &&
buf[8] == 0x68 && buf[9] == 0x65 && buf[10] == 0x76 && buf[11] == 0x63 {
// This is a HEIFS file, ftyphevc
return HEIF
}
if IsTypeSupported(HEIF) && buf[4] == 0x66 && buf[5] == 0x74 && buf[6] == 0x79 && buf[7] == 0x70 &&
buf[8] == 0x61 && buf[9] == 0x76 && buf[10] == 0x69 && buf[11] == 0x66 {
return AVIF
}
return UNKNOWN
}
func readImageType(buf []byte) string {
length := C.size_t(len(buf))
imageBuf := unsafe.Pointer(&buf[0])
load := C.vips_foreign_find_load_buffer(imageBuf, length)
return C.GoString(load)
}
func catchVipsError() error {
s := C.GoString(C.vips_error_buffer())
C.vips_error_clear()
C.vips_thread_shutdown()
return errors.New(s)
}
func boolToInt(b bool) int {
if b {
return 1
}
return 0
}
func vipsGaussianBlur(image *C.VipsImage, o GaussianBlur) (*C.VipsImage, error) {
var out *C.VipsImage
defer C.g_object_unref(C.gpointer(image))
err := C.vips_gaussblur_bridge(image, &out, C.double(o.Sigma), C.double(o.MinAmpl))
if err != 0 {
return nil, catchVipsError()
}
return out, nil
}
func vipsSharpen(image *C.VipsImage, o Sharpen) (*C.VipsImage, error) {
var out *C.VipsImage
defer C.g_object_unref(C.gpointer(image))
err := C.vips_sharpen_bridge(image, &out, C.int(o.Radius), C.double(o.X1), C.double(o.Y2), C.double(o.Y3), C.double(o.M1), C.double(o.M2))
if err != 0 {
return nil, catchVipsError()
}
return out, nil
}
func max(x int) int {
return int(math.Max(float64(x), 0))
}
func vipsDrawWatermark(image *C.VipsImage, o WatermarkImage) (*C.VipsImage, error) {
var out *C.VipsImage
watermark, _, e := vipsRead(o.Buf)
if e != nil {
return nil, e
}
opts := vipsWatermarkImageOptions{C.int(o.Left), C.int(o.Top), C.float(o.Opacity)}
err := C.vips_watermark_image(image, watermark, &out, (*C.WatermarkImageOptions)(unsafe.Pointer(&opts)))
if err != 0 {
return nil, catchVipsError()
}
return out, nil
}
func vipsGamma(image *C.VipsImage, Gamma float64) (*C.VipsImage, error) {
var out *C.VipsImage
defer C.g_object_unref(C.gpointer(image))
err := C.vips_gamma_bridge(image, &out, C.double(Gamma))
if err != 0 {
return nil, catchVipsError()
}
return out, nil
}
func vipsBrightness(image *C.VipsImage, brightness float64) (*C.VipsImage, error) {
var out *C.VipsImage
defer C.g_object_unref(C.gpointer(image))
err := C.vips_brightness_bridge(image, &out, C.double(brightness))
if err != 0 {
return nil, catchVipsError()
}
return out, nil
}
func vipsContrast(image *C.VipsImage, contrast float64) (*C.VipsImage, error) {
var out *C.VipsImage
defer C.g_object_unref(C.gpointer(image))
err := C.vips_contrast_bridge(image, &out, C.double(contrast))
if err != 0 {
return nil, catchVipsError()
}
return out, nil
}
1
https://gitee.com/mirrors/bimg.git
git@gitee.com:mirrors/bimg.git
mirrors
bimg
bimg
v1.1.9

搜索帮助