Example #1
0
func main() {
	// Some GraphicsMagick boilerplate
	C.InitializeMagick(nil)
	defer C.DestroyMagick()
	C.GetExceptionInfo(&exceptionInfo)
	imageInfo = C.CloneImageInfo(nil)
	defer C.DestroyExceptionInfo(&exceptionInfo)
	defer C.DestroyImageInfo(imageInfo)

	// main OMIT

	Show("./cgo/armed_gopher.jpg")

	img, err := Read("./cgo/armed_gopher.jpg")
	if err != nil {
		fmt.Println(err)
		return
	}

	if img, err = Resize(img, 200, 800); err != nil {
		fmt.Println("resize error:", err)
		return
	}

	if err = Save(img, "./cgo/resized_gopher.jpg"); err != nil {
		fmt.Println("save error:", err)
		return
	}

	Show("./cgo/resized_gopher.jpg")
}
Example #2
0
// Composite modifies the image, drawing the draw Image argument at offset
// (x, y) using the c Composite operation.
func (im *Image) Composite(c Composite, draw *Image, x int, y int) error {
	op, err := im.compositeOperator(c)
	if err != nil {
		return err
	}
	var ex C.ExceptionInfo
	C.GetExceptionInfo(&ex)
	defer C.DestroyExceptionInfo(&ex)
	var data C.CompositeData
	data.composite = C.int(op)
	data.draw = draw.image
	data.x = C.int(x)
	data.y = C.int(y)
	res, err := im.applyDataFunc("compositing", C.ImageDataFunc(C.compositeImage), &data)
	// res.image will be != than im.image when im is a non
	// coalesced animation
	if res.image != im.image {
		unrefImages(im.image)
		initializeRefCounts(res.image)
		refImages(res.image)
		im.image = res.image
		dontFree(res)
	}
	return err
}
Example #3
0
func (im *Image) fn(what string, f C.ImageFunc) (*Image, error) {
	var ex C.ExceptionInfo
	C.GetExceptionInfo(&ex)
	defer C.DestroyExceptionInfo(&ex)
	res := C.bridge_image_func(f, im.image, &ex)
	return checkImage(res, nil, &ex, what)
}
Example #4
0
func (im *Image) Roll(xoffset, yoffset int) (*Image, error) {
	var ex C.ExceptionInfo
	C.GetExceptionInfo(&ex)
	defer C.DestroyExceptionInfo(&ex)
	rolled := C.RollImage(im.image, magickLong(xoffset), magickLong(yoffset), &ex)
	return checkImage(rolled, nil, &ex, "rolling")
}
Example #5
0
// FloatMatrix returns an Image in the GRAY colorspace as FloatMatrix,
// where each pixel represents an element of the matrix. Each element
// is normalized to the [0,1] range.
func (im *Image) FloatMatrix() (FloatMatrix, error) {
	if im.Colorspace() != GRAY {
		return nil, fmt.Errorf("FloatMatrix() is available only for GRAY images, this one is in %s", im.Colorspace())
	}
	width := im.Width()
	height := im.Height()
	ptrs := make([]*C.double, width)
	for ii := range ptrs {
		ptrs[ii] = allocDoublePtr(height)
	}
	defer func() {
		for _, p := range ptrs {
			freeDoublePtr(p)
		}
	}()
	var ex C.ExceptionInfo
	C.GetExceptionInfo(&ex)
	defer C.DestroyExceptionInfo(&ex)
	C.image_matrix(im.image, (**C.double)(unsafe.Pointer(&ptrs[0])), &ex)
	if ex.severity != C.UndefinedException {
		return nil, exError(&ex, "generating float matrix")
	}
	m := make([][]float64, width)
	for ii := range m {
		m[ii] = doublePtrToFloat64Slice(ptrs[ii], height)
	}
	return FloatMatrix(m), nil
}
Example #6
0
func (im *Image) NColors() (int, error) {
	var ex C.ExceptionInfo
	C.GetExceptionInfo(&ex)
	defer C.DestroyExceptionInfo(&ex)
	val := C.GetNumberColors(im.image, nil, &ex)
	if ex.severity != C.UndefinedException {
		return 0, exError(&ex, "getting colors")
	}
	return int(val), nil
}
Example #7
0
// ChannelDepth returns the depth of the given channel.
func (im *Image) ChannelDepth(ch Channel) (uint, error) {
	var ex C.ExceptionInfo
	C.GetExceptionInfo(&ex)
	defer C.DestroyExceptionInfo(&ex)
	ret := C.GetImageChannelDepth(im.image, C.ChannelType(ch), &ex)
	if ex.severity != C.UndefinedException {
		return 0, exError(&ex, "getting channel info")
	}
	return uint(ret), nil
}
Example #8
0
func (im *Image) IsPalette() (bool, error) {
	var ex C.ExceptionInfo
	C.GetExceptionInfo(&ex)
	defer C.DestroyExceptionInfo(&ex)
	b := C.IsPaletteImage(im.image, &ex)
	if ex.severity != C.UndefinedException {
		return false, exError(&ex, "getting isPalette")
	}
	return int(b) != 0, nil
}
Example #9
0
func (im *Image) statistics() (*Statistics, error) {
	var ex C.ExceptionInfo
	C.GetExceptionInfo(&ex)
	defer C.DestroyExceptionInfo(&ex)
	var stats C.ImageStatistics
	C.GetImageStatistics(im.image, &stats, &ex)
	if ex.severity != C.UndefinedException {
		return nil, exError(&ex, "getting statistics")
	}
	return newStatistics(&stats), nil
}
Example #10
0
// Clone returns a copy of the image. If the image
// has multiple frames, it copies all of them. To
// Clone just one frame use im.Frame(i).Clone().
func (im *Image) Clone() (*Image, error) {
	var ex C.ExceptionInfo
	C.GetExceptionInfo(&ex)
	defer C.DestroyExceptionInfo(&ex)
	var image *C.Image
	if im.parent == nil {
		image = C.CloneImageList(im.image, &ex)
	} else {
		image = C.CloneImage(im.image, magickSize(0), magickSize(0), 1, &ex)
	}
	return checkImage(image, nil, &ex, "cloning")
}
Example #11
0
func (im *Image) applyFunc(what string, f C.ImageFunc) (*Image, error) {
	var ex C.ExceptionInfo
	C.GetExceptionInfo(&ex)
	defer C.DestroyExceptionInfo(&ex)
	res := C.apply_image_func(f, im.root(), unsafe.Pointer(im.parent), btoi(im.coalesced), &ex)
	if res == nil {
		return nil, exError(&ex, what)
	}
	ret := newImage(res, nil)
	ret.coalesced = true
	return ret, nil
}
Example #12
0
func (im *Image) applyDataFunc(what string, f C.ImageDataFunc, data interface{}) (*Image, error) {
	p := unsafe.Pointer(reflect.ValueOf(data).Pointer())
	var ex C.ExceptionInfo
	C.GetExceptionInfo(&ex)
	defer C.DestroyExceptionInfo(&ex)
	res := C.apply_image_data_func(f, im.root(), p, unsafe.Pointer(im.parent), btoi(im.coalesced), &ex)
	if res == nil {
		return nil, exError(&ex, what)
	}
	ret := newImage(res, nil)
	ret.coalesced = true
	return ret, nil
}
Example #13
0
func (im *Image) statistics() (*Statistics, error) {
	var ex C.ExceptionInfo
	C.GetExceptionInfo(&ex)
	defer C.DestroyExceptionInfo(&ex)
	stats := C.GetImageChannelStatistics(im.image, &ex)
	if stats != nil {
		defer freeMagickMemory(unsafe.Pointer(stats))
	}
	if stats == nil || ex.severity != C.UndefinedException {
		return nil, exError(&ex, "getting statistics")
	}
	return newStatistics(stats), nil
}
Example #14
0
func decodeData(data []byte, try int) (*Image, error) {
	if len(data) == 0 {
		return nil, ErrNoData
	}
	info := C.CloneImageInfo(nil)
	defer C.DestroyImageInfo(info)
	var ex C.ExceptionInfo
	C.GetExceptionInfo(&ex)
	defer C.DestroyExceptionInfo(&ex)
	im := C.BlobToImage(info, unsafe.Pointer(&data[0]), C.size_t(len(data)), &ex)
	if im == nil && try < maxGifTries && ex.severity == C.CorruptImageError && looksLikeGif(data) {
		return fixAndDecodeGif(data, try)
	}
	return checkImage(im, nil, &ex, "decoding")
}
Example #15
0
// Composite modifies the image, drawing the draw Image argument at offset
// (x, y) using the c Composite operation.
func (im *Image) Composite(c Composite, draw *Image, x int, y int) error {
	op, err := im.compositeOperator(c)
	if err != nil {
		return err
	}
	var ex C.ExceptionInfo
	C.GetExceptionInfo(&ex)
	defer C.DestroyExceptionInfo(&ex)
	var data C.CompositeData
	data.composite = C.int(op)
	data.draw = draw.image
	data.x = C.int(x)
	data.y = C.int(y)
	_, err = im.applyDataFunc("compositing", C.ImageDataFunc(C.compositeImage), &data)
	return err
}
Example #16
0
// Supported formats returns a list with the names
// of all supported image formats. This varies depending
// on the backend and the compile options that have been
// used while building IM or GM.
func SupportedFormats() ([]string, error) {
	var ex C.ExceptionInfo
	C.GetExceptionInfo(&ex)
	defer C.DestroyExceptionInfo(&ex)
	infos, p := supportedFormats(&ex)
	if infos == nil {
		return nil, exError(&ex, "getting supported formats")
	}
	var formats []string
	for _, v := range infos {
		if v == nil {
			break
		}
		formats = append(formats, C.GoString(v.name))
	}
	freeMagickMemory(p)
	return formats, nil
}
Example #17
0
func (im *Image) Apply(f func(*Image) (*Image, error)) (*Image, error) {
	if im.IsOrphan() || im.parent != nil {
		return f(im)
	}
	var ex C.ExceptionInfo
	C.GetExceptionInfo(&ex)
	defer C.DestroyExceptionInfo(&ex)
	cur, free := im.coalescedCImage(&ex)
	if cur == nil {
		return nil, exError(&ex, "coalescing")
	}
	buf := &Image{
		parent: im,
		image:  cur,
	}
	first, err := f(buf)
	if err != nil {
		return nil, err
	}
	prev := first.image
	var res *Image
	for cur := (*C.Image)(im.image.next); cur != nil; cur = (*C.Image)(cur.next) {
		buf.image = cur
		res, err = f(buf)
		if err != nil {
			break
		}
		dontFree(res)
		img := res.image
		if img != cur {
			prev.next = (*C.struct__Image)(img)
			img.previous = (*C.struct__Image)(prev)
		}
		prev = img
	}
	if free && (first.image != cur || err != nil) {
		C.DestroyImageList(cur)
	}
	if err != nil {
		return nil, err
	}
	return first, nil
}
Example #18
0
// SetPixels changes the pixels in the given rect, in row major order.
// Note that the number of elements in p must match r.Width * r.Height,
// otherwise an error is returned.
func (im *Image) SetPixels(r Rect, p []*Pixel) error {
	if int(r.Width*r.Height) != len(p) {
		return fmt.Errorf("rect contains %d pixels, but %d were provided", int(r.Width*r.Height), len(p))
	}
	if len(p) == 0 {
		return nil
	}
	var ex C.ExceptionInfo
	C.GetExceptionInfo(&ex)
	defer C.DestroyExceptionInfo(&ex)
	packets := make([]C.PixelPacket, len(p))
	for ii, v := range p {
		copyPixel(v, &packets[ii])
	}
	if !im.setPixels(&r, (*C.PixelPacket)(unsafe.Pointer(&packets[0])), &ex) {
		return exError(&ex, "setting pixels")
	}
	return nil
}
Example #19
0
func (im *Image) AddFrame(f Frame, c *Pixel) (*Image, error) {
	return im.Apply(func(i *Image) (*Image, error) {
		var ex C.ExceptionInfo
		C.GetExceptionInfo(&ex)
		defer C.DestroyExceptionInfo(&ex)
		var m *Pixel
		if c != nil {
			m = i.MatteColor()
			i.SetMatteColor(c)
		}
		framed := C.FrameImage(i.image, f.frameInfo(), &ex)
		if m != nil {
			i.SetMatteColor(m)
		}
		if framed == nil {
			return nil, exError(&ex, "adding border")
		}
		return newImage(framed, nil), nil
	})
}
Example #20
0
func (im *Image) AddBorder(r Rect, c *Pixel) (*Image, error) {
	return im.Apply(func(i *Image) (*Image, error) {
		var ex C.ExceptionInfo
		C.GetExceptionInfo(&ex)
		defer C.DestroyExceptionInfo(&ex)
		var b *Pixel
		if c != nil {
			b = i.BorderColor()
			im.SetBorderColor(c)
		}
		bordered := C.BorderImage(i.image, r.rectangleInfo(), &ex)
		if b != nil {
			i.SetBorderColor(b)
		}
		if bordered == nil {
			return nil, exError(&ex, "adding border")
		}
		return newImage(bordered, nil), nil
	})
}
Example #21
0
// Pixels returns the image pixels contained in the given rect,
// in row major order. Note that modifications to the returned pixels
// won't alter the image. Use SetPixels to change pixels in the
// image.
func (im *Image) Pixels(r Rect) ([]*Pixel, error) {
	var ex C.ExceptionInfo
	C.GetExceptionInfo(&ex)
	defer C.DestroyExceptionInfo(&ex)
	ptr := im.pixels(&r, &ex)
	if ptr == nil {
		return nil, exError(&ex, "getting pixels")
	}
	count := int(r.Width * r.Height)
	var pkts []C.PixelPacket
	header := (*reflect.SliceHeader)((unsafe.Pointer(&pkts)))
	header.Cap = count
	header.Len = count
	header.Data = uintptr(unsafe.Pointer(ptr))
	px := make([]*Pixel, count)
	for ii, v := range pkts {
		px[ii] = newPixel(&v)
	}
	return px, nil
}
Example #22
0
// Encode writes the image to the given io.Writer, encoding
// it according to the info parameter. Please, see the
// Info type for the available encoding options.
func (im *Image) Encode(w io.Writer, info *Info) error {
	var ex C.ExceptionInfo
	C.GetExceptionInfo(&ex)
	defer C.DestroyExceptionInfo(&ex)
	if info == nil {
		info = NewInfo()
	}
	/* ImageToBlob copies the format from the image into
	the image info. Overwrite if required and then restore
	*/
	im.mu.Lock()
	var format *C.char
	copied := false
	if info.info.magick[0] != 0 {
		copied = true
		if im.image.magick[0] != 0 {
			format = C.strdup(&im.image.magick[0])
		}
		C.strncpy(&im.image.magick[0], &info.info.magick[0], C.MaxTextExtent)
	}
	var s C.size_t
	mem := imageToBlob(info, im, &s, &ex)
	if copied {
		/* Restore image format */
		if format != nil {
			C.strncpy(&im.image.magick[0], format, C.MaxTextExtent)
			C.free(unsafe.Pointer(format))
		} else {
			C.memset(unsafe.Pointer(&im.image.magick[0]), 0, C.MaxTextExtent)
		}
	}
	im.mu.Unlock()
	if mem == nil {
		return exError(&ex, "encoding")
	}
	b := goBytes(mem, int(s))
	w.Write(b)
	C.free(mem)
	return nil
}
Example #23
0
// FloatMatrix returns an Image in the GRAY colorspace as FloatMatrix,
// where each pixel represents an element of the matrix. Each element
// is normalized to the [0,1] range.
func (im *Image) FloatMatrix() (FloatMatrix, error) {
	if im.Colorspace() != GRAY {
		return nil, fmt.Errorf("FloatMatrix() is available only for GRAY images, this one is in %s", im.Colorspace())
	}
	width := im.Width()
	height := im.Height()
	m := make([][]float64, width)
	ptrs := make([]unsafe.Pointer, width)
	for ii := range m {
		col := make([]float64, height)
		m[ii] = col
		ptrs[ii] = unsafe.Pointer(&col[0])
	}
	var ex C.ExceptionInfo
	C.GetExceptionInfo(&ex)
	defer C.DestroyExceptionInfo(&ex)
	C.image_matrix(im.image, (**C.double)(unsafe.Pointer(&ptrs[0])), &ex)
	if ex.severity != C.UndefinedException {
		return nil, exError(&ex, "generating float matrix")
	}
	return FloatMatrix(m), nil
}
Example #24
0
func (im *Image) histogram() (*Histogram, error) {
	var ex C.ExceptionInfo
	C.GetExceptionInfo(&ex)
	defer C.DestroyExceptionInfo(&ex)
	var colors C.ulong
	hist := C.GetColorHistogram(im.image, &colors, &ex)
	if hist == nil {
		return nil, exError(&ex, "getting histogram")
	}
	defer C.free(unsafe.Pointer(hist))
	count := int(colors)
	items := make([]*HistogramItem, count)
	var hitems []C.HistogramColorPacket
	sliceHeader := (*reflect.SliceHeader)((unsafe.Pointer(&hitems)))
	sliceHeader.Cap = count
	sliceHeader.Len = count
	sliceHeader.Data = uintptr(unsafe.Pointer(hist))
	for ii, v := range hitems {
		px := newPixel(&v.pixel)
		items[ii] = &HistogramItem{px, int(v.count)}
	}
	return &Histogram{items}, nil
}
Example #25
0
func (im *Image) operateChannel(op Operator, ch Channel, value float64) error {
	var cop C.QuantumOperator
	switch op {
	case OpAdd:
		cop = C.AddQuantumOp
	case OpAnd:
		cop = C.AndQuantumOp
	case OpAssign:
		cop = C.AssignQuantumOp
	case OpDepth:
		cop = C.DepthQuantumOp
	case OpDivide:
		cop = C.DivideQuantumOp
	case OpGamma:
		cop = C.GammaQuantumOp
	case OpLog:
		cop = C.LogQuantumOp
	case OpLShift:
		cop = C.LShiftQuantumOp
	case OpMax:
		cop = C.MaxQuantumOp
	case OpMin:
		cop = C.MinQuantumOp
	case OpMultiply:
		cop = C.MultiplyQuantumOp
	case OpGaussianNoise:
		cop = C.GammaQuantumOp
	case OpImpulseNoise:
		cop = C.NoiseImpulseQuantumOp
	case OpLaplacianNoise:
		cop = C.NoiseLaplacianQuantumOp
	case OpMultiplicativeNoise:
		cop = C.NoiseMultiplicativeQuantumOp
	case OpPoissonNoise:
		cop = C.NoisePoissonQuantumOp
	case OpRandomNoise:
		cop = C.NoiseRandomQuantumOp
	case OpUniformNoise:
		cop = C.NoisePoissonQuantumOp
	case OpOr:
		cop = C.OrQuantumOp
	case OpPow:
		cop = C.PowQuantumOp
	case OpRShift:
		cop = C.RShiftQuantumOp
	case OpSubstract:
		cop = C.SubtractQuantumOp
	case OpThresholdBlack:
		cop = C.ThresholdBlackQuantumOp
	case OpThreshold:
		cop = C.ThresholdQuantumOp
	case OpThresholdWhite:
		cop = C.ThresholdWhiteQuantumOp
	case OpXor:
		cop = C.XorQuantumOp
	default:
		return notImplementedError(fmt.Sprintf("operator %s", op))
	}
	var ex C.ExceptionInfo
	C.GetExceptionInfo(&ex)
	defer C.DestroyExceptionInfo(&ex)
	if C.QuantumOperatorImage(im.image, C.ChannelType(ch), cop, C.double(value), &ex) != C.MagickTrue {
		return exError(&ex, "operating")
	}
	return nil
}