Ejemplo n.º 1
0
func TestMain(m *testing.M) {
	vips.Initialize()
	vips.LeakSet(true)
	r := m.Run()
	vips.ThreadShutdown()
	vips.Shutdown()
	os.Exit(r)
}
Ejemplo n.º 2
0
func (p *Pool) worker() {
	runtime.LockOSThread()

	for {
		q := <-p.RequestCh
		if q == nil {
			break
		}

		s := &Response{}
		if hasAborted(q.Aborted) {
			s.Error = ErrAborted
		} else {
			s.Blob, s.Error = Thumbnail(q.Blob, q.Options)
		}

		q.ResponseCh <- s
	}

	vips.ThreadShutdown()
	runtime.UnlockOSThread()

	p.wg.Done()
}
Ejemplo n.º 3
0
// Thumbnail scales or crops a compressed image blob according to the
// Options specified in o and returns a compressed image.
// Should be called from a thread pool with runtime.LockOSThread() locked.
func Thumbnail(blob []byte, o Options) ([]byte, error) {
	if o.MaxProcessingDuration > 0 {
		timer := time.AfterFunc(o.MaxProcessingDuration, func() {
			panic(fmt.Sprintf("Thumbnail took longer than %v", o.MaxProcessingDuration))
		})
		defer timer.Stop()
	}

	// Free some thread-local caches. Safe to call unnecessarily.
	defer vips.ThreadShutdown()

	m, err := format.MetadataBytes(blob)
	if err != nil {
		return nil, err
	}

	o, err = o.Check(m)
	if err != nil {
		return nil, err
	}

	// If source image is lossy, disable lossless.
	if m.Format == format.Jpeg {
		o.Save.Lossless = false
	}

	// Figure out size to scale image down to.  For crop, this is the
	// intermediate size the original image would have to be scaled to
	// be cropped to requested size.
	iw, ih, trustWidth := scaleAspect(m.Width, m.Height, o.Width, o.Height, !o.Crop)

	// Are we shrinking by more than 2.5%?
	shrinking := iw < m.Width-m.Width/40 && ih < m.Height-m.Height/40

	// Figure out the jpeg/webp shrink factor and load image.
	// Jpeg shrink rounds up the number of pixels.
	psf := preShrinkFactor(m.Width, m.Height, iw, ih, trustWidth, o.FastResize, m.Format == format.Jpeg)
	image, err := load(blob, m.Format, psf)
	if err != nil {
		return nil, err
	}
	defer image.Close()

	if err := srgb(image); err != nil {
		return nil, err
	}

	if err := resize(image, iw, ih, o.FastResize, o.BlurSigma, o.Sharpen && shrinking); err != nil {
		return nil, err
	}

	// Make sure we generate images with 8 bits per channel.  Do this before the
	// rotate to reduce the amount of data that needs to be copied.
	if image.ImageGetBandFormat() != vips.BandFormatUchar {
		if err := image.Cast(vips.BandFormatUchar); err != nil {
			return nil, err
		}
	}

	if o.Crop {
		if err = crop(image, o.Width, o.Height); err != nil {
			return nil, err
		}
	}

	if image.HasAlpha() {
		if min, err := minTransparency(image); err == nil && min >= 0.9 {
			if err := image.Flatten(); err != nil {
				return nil, err
			}
		}
	}

	if err := m.Orientation.Apply(image); err != nil {
		return nil, err
	}

	return format.Save(image, o.Save)
}