Пример #1
0
func getGray(src *image.Gray, x, y, borderMethod int) uint8 {
	bound := src.Bounds()
	if x < 0 {
		switch borderMethod {
		case BORDER_COPY:
			x = 0
		default:
			return 0
		}
	} else if x >= bound.Max.X {
		switch borderMethod {
		case BORDER_COPY:
			x = bound.Max.X - 1
		default:
			return 0
		}
	}
	if y < 0 {
		switch borderMethod {
		case BORDER_COPY:
			y = 0
		default:
			return 0
		}
	} else if y >= bound.Max.Y {
		switch borderMethod {
		case BORDER_COPY:
			y = bound.Max.Y - 1
		default:
			return 0
		}
	}
	i := (y-bound.Min.Y)*src.Stride + (x - bound.Min.X)
	return src.Pix[i]
}
Пример #2
0
func Contrast(picture *image.Gray, contrast uint8) *image.Gray {
	bounds := picture.Bounds()
	newPic := image.NewGray(bounds)
	average := getAverage(picture)
	for x := 0; x < bounds.Dx(); x++ {
		for y := 0; y < bounds.Dy(); y++ {
			pixel := picture.At(x, y).(color.Gray).Y
			if pixel > average {
				if pixel+contrast < pixel {
					pixel = 0xff
				} else {
					pixel += contrast
				}
			} else if pixel < average {
				if pixel-contrast > pixel {
					pixel = 0x00
				} else {
					pixel -= contrast
				}
			}
			newPic.Set(x, y, color.Gray{pixel})
		}
	}
	return newPic
}
Пример #3
0
func valueAt(img *image.Gray, x, y float32) float32 {
	dx, dy := x/float32(screenWidth), y/float32(screenHeight)
	b := img.Bounds().Max
	px, py := int(dx*float32(b.X)), int(dy*float32(b.Y))
	v := float32(img.At(px, py).(color.Gray).Y) / 255
	return v
}
Пример #4
0
func New(im image.Gray) *Integral {
	rect := im.Bounds()
	width := rect.Dx()
	height := rect.Dy()

	data := make([]uint32, width*height)
	for x := rect.Min.X; x < rect.Max.X; x++ {
		for y := rect.Min.Y; y < rect.Max.Y; y++ {
			if x == 0 && y == 0 {
				data[0] = uint32(im.Pix[0])
			} else if x == 0 && y != 0 {
				data[y*height+x] = data[(y-1)*height+x] + uint32(im.Pix[y*im.Stride+x])
			} else if y == 0 && x != 0 {
				data[y*height+x] = data[y*height+x-1] + uint32(im.Pix[y*im.Stride+x])
			} else {
				data[y*height+x] = data[(y-1)*height+x] + data[y*height+x-1] - data[(y-1)*height+x-1] + uint32(im.Pix[y*im.Stride+x])
			}
		}
	}

	intImg := &Integral{
		Data:   data,
		Width:  width,
		Height: height,
	}

	return intImg
}
Пример #5
0
func Blobify(img *image.Gray) Blobs {
	var blobs Blobs
	visited := make([]bool, img.Bounds().Max.X*img.Bounds().Max.Y)

	// Scan for first/next blob.
	x, y := 0, 0

	for {
		x, y = nextPixel(x, y, img, visited)
		if x < 0 || y < 0 {
			for _, b := range blobs.blobs {
				// Only compute bridges for wide blobs
				if float64(b.Bounds.Dx()) >= blobs.avgWidth()*1.75 {
					b.computeBridges(blobs.avgWidth())
				}
			}
			log.Printf("Returning Blobs with count: %d\n", len(blobs.blobs))

			return blobs
		}

		// Extract blob.
		b := blobAt(x, y, img, visited)
		x = b.Bounds.Max.X + 1
		blobs.addBlob(b)
	}
}
Пример #6
0
func nearestGray(in *image.Gray, out *image.Gray, scale float64, coeffs []bool, offset []int, filterLength int) {
	newBounds := out.Bounds()
	maxX := in.Bounds().Dx() - 1

	for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
		row := in.Pix[x*in.Stride:]
		for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
			var gray float32
			var sum float32
			start := offset[y]
			ci := y * filterLength
			for i := 0; i < filterLength; i++ {
				if coeffs[ci+i] {
					xi := start + i
					switch {
					case xi < 0:
						xi = 0
					case xi >= maxX:
						xi = maxX
					}
					gray += float32(row[xi])
					sum++
				}
			}

			offset := (y-newBounds.Min.Y)*out.Stride + (x - newBounds.Min.X)
			out.Pix[offset] = floatToUint8(gray / sum)
		}
	}
}
Пример #7
0
func resizeGray(in *image.Gray, out *image.Gray, scale float64, coeffs []int16, offset []int, filterLength int) {
	newBounds := out.Bounds()
	maxX := in.Bounds().Dx() - 1

	for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
		row := in.Pix[(x-newBounds.Min.X)*in.Stride:]
		for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
			var gray int32
			var sum int32
			start := offset[y]
			ci := y * filterLength
			for i := 0; i < filterLength; i++ {
				coeff := coeffs[ci+i]
				if coeff != 0 {
					xi := start + i
					switch {
					case xi < 0:
						xi = 0
					case xi >= maxX:
						xi = maxX
					}
					gray += int32(coeff) * int32(row[xi])
					sum += int32(coeff)
				}
			}

			offset := (y-newBounds.Min.Y)*out.Stride + (x - newBounds.Min.X)
			out.Pix[offset] = clampUint8(gray / sum)
		}
	}
}
Пример #8
0
// checkCircle checks that a circle with a center in (x, y) and a radius r fits to the base image and all pixels are high.
func checkCircle(base *image.Gray, level byte, pxSize, x, y, r float64) bool {
	width := float64(base.Bounds().Dx()) * pxSize
	height := float64(base.Bounds().Dy()) * pxSize
	if x < r || x > width-r || y < r || y > height-r {
		return false
	}
	x0 := int((x - r) / pxSize)
	y0 := int((y - r) / pxSize)
	x1 := int((x + r) / pxSize)
	y1 := int((y + r) / pxSize)
	for cy := y0; cy <= y1; cy++ {
		i0 := cy * base.Stride
		for cx := x0; cx <= x1; cx++ {
			if !inside(x, y, r, (x-r)+float64(cx-x0)*pxSize, (y-r)+float64(cy-y0)*pxSize) {
				continue
			}
			if base.Pix[i0+cx] != level {
				// circle hits background
				//fmt.Printf("checkCircle(pxSize=%f, x=%f, y=%f, r=%f, i0=%d, cx=%d, base.Pix[i0+cx]=%d\n",
				//	pxSize, x, y, r, i0, cx, base.Pix[i0+cx])
				return false
			}
		}
	}
	return true
}
Пример #9
0
func fillTriangle(base *image.Gray, level byte, bbox image.Rectangle, ox, oy float64) []Point {
	basePxSize := *pxSize / float64(*n)
	width := float64(base.Bounds().Dx()) * basePxSize
	height := float64(base.Bounds().Dy()) * basePxSize

	dy := (*toolDiameter) / 2
	dx := dy * 1.73205080757 // sqrt(3)
	var centers []Point
	for i := 0; ; i++ {
		cx := ox + float64(i)*dx
		if cx >= width {
			break
		}
		if cx < float64(bbox.Min.X-1)*basePxSize || cx >= float64(bbox.Max.X+1)*basePxSize {
			continue
		}
		for j := 0; ; j++ {
			cy := oy + float64(j)*dy
			if cy >= height {
				break
			}
			if cy < float64(bbox.Min.Y-1)*basePxSize || cy >= float64(bbox.Max.Y+1)*basePxSize {
				continue
			}
			if (i+j)%2 == 1 {
				continue
			}
			if checkCircle(base, level, basePxSize, cx, cy, (*toolDiameter)/2) {
				centers = append(centers, Point{cx, cy})
			}
		}
	}
	return centers
}
Пример #10
0
func fillQuad(base *image.Gray, level byte, bbox image.Rectangle, ox, oy float64) []Point {
	basePxSize := *pxSize / float64(*n)
	width := float64(base.Bounds().Dx()) * basePxSize
	height := float64(base.Bounds().Dy()) * basePxSize
	dx := *toolDiameter
	dy := *toolDiameter
	var centers []Point
	for i := 0; ; i++ {
		cx := ox + float64(i)*dx
		if cx >= width {
			break
		}
		if cx < float64(bbox.Min.X-1)*basePxSize || cx >= float64(bbox.Max.X+1)*basePxSize {
			//fmt.Printf("bbox={%f,%f}-{%f,%f}, cx: %f, skip...\n",
			//	float64(bbox.Min.X)*basePxSize, float64(bbox.Min.Y)*basePxSize, float64(bbox.Max.X)*basePxSize, float64(bbox.Max.Y)*basePxSize, cx)
			continue
		}
		for j := 0; ; j++ {
			cy := oy + float64(j)*dy
			if cy >= height {
				break
			}
			if cy < float64(bbox.Min.Y-1)*basePxSize || cy >= float64(bbox.Max.Y+1)*basePxSize {
				//fmt.Printf("bbox={%f,%f}-{%f,%f}, cy: %f, skip...\n",
				//	float64(bbox.Min.X)*basePxSize, float64(bbox.Min.Y)*basePxSize, float64(bbox.Max.X)*basePxSize, float64(bbox.Max.Y)*basePxSize, cy)
				continue
			}
			if checkCircle(base, level, basePxSize, cx, cy, (*toolDiameter)/2) {
				centers = append(centers, Point{cx, cy})
			}
		}
	}
	return centers
}
Пример #11
0
//BackProjectGray computes back projection of img
// in Gray16 by performing an addition
// of backprojection by line.
// 16Gray avoids white noise.
func BackProjectGray(img image.Gray) (*image.Gray16, error) {
	size := img.Bounds().Size()
	width := size.Y
	nbProj := size.X
	step := 180.0 / float64(nbProj)

	out := image.NewGray16(image.Rect(0, 0, width, width))

	for X := 0; X < nbProj; X++ {
		//Extract a 1D-projection (one row Y of sinogram)
		line := img.SubImage(image.Rect(X, 0, X+1, width)).(*image.Gray)

		// 3- Do the backprojection and rotate accordingly
		wideLine := resize.Resize(uint(width), uint(width), line, resize.Lanczos3).(*image.Gray)

		θ := manipulator.Rad(float64(X)*step) + math.Pi/2
		rotatedWideLine := image.NewGray(image.Rect(0, 0, width, width))
		err := graphics.Rotate(rotatedWideLine, wideLine, &graphics.RotateOptions{Angle: θ})
		if err != nil {
			return out, err
		}

		// 4- Add the rotated backprojection in the output image
		for x := 0; x < width; x++ {
			for y := 0; y < width; y++ {
				point := uint16(out.At(x, y).(color.Gray16).Y) + uint16(rotatedWideLine.At(x, y).(color.Gray).Y)
				out.Set(x, y, color.Gray16{uint16(point)})
			}
		}
	}

	return out, nil
}
Пример #12
0
// GreyscaleDct Computes the Dct of a greyscale image
func GreyscaleDct(img image.Gray) uint64 {
	// func DctImageHashOne(img image.Image) ([][]float64) {
	R := img.Bounds()
	N := R.Dx() // width
	M := R.Dy() // height
	DCTMatrix := make([][]float64, N)
	for u := 0; u < N; u++ {
		DCTMatrix[u] = make([]float64, M)
		for v := 0; v < M; v++ {
			DCTMatrix[u][v] = dctPoint(img, u, v, N, M)
			// fmt.Println( "DCTMatrix[", u, "][", v, "] is ", DCTMatrix[u][v])
		}
	}

	total := 0.0
	for u := 0; u < N/2; u++ {
		for v := 0; v < M/2; v++ {
			total += DCTMatrix[u][v]
		}
	}
	total -= DCTMatrix[0][0]
	avg := total / float64(((N/2)*(M/2))-1)
	fmt.Println("got average ", avg)
	var hash uint64
	for u := 0; u < N/2; u++ {
		for v := 0; v < M/2; v++ {
			hash = hash * 2
			if DCTMatrix[u][v] > avg {
				hash++
			}
		}
	}

	return hash
}
Пример #13
0
func meanHeight(g *image.Gray) uint8 {
	b := g.Bounds()
	var total uint64
	for i := b.Min.X; i < b.Max.X; i++ {
		for j := b.Min.Y; j < b.Max.Y; j++ {
			total += uint64(g.GrayAt(i, j).Y)
		}
	}
	return uint8(total / uint64((b.Dx() * b.Dy())))
}
Пример #14
0
func getAverage(picture *image.Gray) uint8 {
	var sum uint64 = 0
	bounds := picture.Bounds()
	for x := 0; x < bounds.Dx(); x++ {
		for y := 0; y < bounds.Dy(); y++ {
			sum += uint64(picture.At(x, y).(color.Gray).Y)
		}
	}
	return uint8(sum / uint64(bounds.Dx()*bounds.Dy()))
}
Пример #15
0
// Transforms gray input image color depth to the palette defined in p
// The algorithm simply assigns the nearest palette color to each pixel,
// without distributing error in any way, so expect color banding
func ditheringAverage(img *image.Gray, p *color.Palette) {
	size := img.Bounds()
	for y := size.Min.Y; y < size.Max.Y; y++ {
		for x := size.Min.X; x < size.Max.X; x++ {
			c1 := img.GrayAt(x, y)
			c2 := p.Convert(c1).(color.Gray)
			img.SetGray(x, y, c2)
		}
	}
}
Пример #16
0
// Interpolate uint8/pixel images.
func interpolate1x8(src *image.Gray, dstW, dstH int) image.Image {
	srcRect := src.Bounds()
	srcW := srcRect.Dx()
	srcH := srcRect.Dy()

	ww, hh := uint64(dstW), uint64(dstH)
	dx, dy := uint64(srcW), uint64(srcH)

	n, sum := dx*dy, make([]uint64, dstW*dstH)
	for y := 0; y < srcH; y++ {
		pixOffset := src.PixOffset(0, y)
		for x := 0; x < srcW; x++ {
			// Get the source pixel.
			val64 := uint64(src.Pix[pixOffset])
			pixOffset++

			// Spread the source pixel over 1 or more destination rows.
			py := uint64(y) * hh
			for remy := hh; remy > 0; {
				qy := dy - (py % dy)
				if qy > remy {
					qy = remy
				}
				// Spread the source pixel over 1 or more destination columns.
				px := uint64(x) * ww
				index := (py/dy)*ww + (px / dx)
				for remx := ww; remx > 0; {
					qx := dx - (px % dx)
					if qx > remx {
						qx = remx
					}
					qxy := qx * qy
					sum[index] += val64 * qxy
					index++
					px += qx
					remx -= qx
				}
				py += qy
				remy -= qy
			}
		}
	}
	dst := image.NewGray(image.Rect(0, 0, dstW, dstH))
	index := 0
	for y := 0; y < dstH; y++ {
		pixOffset := dst.PixOffset(0, y)
		for x := 0; x < dstW; x++ {
			dst.Pix[pixOffset] = uint8(sum[index] / n)
			pixOffset++
			index++
		}
	}
	return dst
}
Пример #17
0
// grayToY stores the 8x8 region of m whose top-left corner is p in yBlock.
func grayToY(m *image.Gray, p image.Point, yBlock *block) {
	b := m.Bounds()
	xmax := b.Max.X - 1
	ymax := b.Max.Y - 1
	pix := m.Pix
	for j := 0; j < 8; j++ {
		for i := 0; i < 8; i++ {
			idx := m.PixOffset(min(p.X+i, xmax), min(p.Y+j, ymax))
			yBlock[8*j+i] = int32(pix[idx])
		}
	}
}
Пример #18
0
func GrayImageToMatrix(src image.Gray) (*matrix.Dense, error) {
	bounds := src.Bounds()
	mtx := make([][]float64, bounds.Max.X)
	for x := 0; x < bounds.Max.X; x++ {
		mtx[x] = make([]float64, bounds.Max.Y)
		for y := 0; y < bounds.Max.Y; y++ {
			_, _, b, _ := src.At(x, y).RGBA()
			mtx[x][y] = float64(b)
		}
	}
	return matrix.NewDense(mtx)
}
Пример #19
0
func tightBounds(m *image.Gray) (r image.Rectangle) {
	r = m.Bounds()
	for ; r.Min.Y < r.Max.Y && emptyRow(m, r, r.Min.Y+0); r.Min.Y++ {
	}
	for ; r.Min.Y < r.Max.Y && emptyRow(m, r, r.Max.Y-1); r.Max.Y-- {
	}
	for ; r.Min.X < r.Max.X && emptyCol(m, r, r.Min.X+0); r.Min.X++ {
	}
	for ; r.Min.X < r.Max.X && emptyCol(m, r, r.Max.X-1); r.Max.X-- {
	}
	return r
}
Пример #20
0
func toGray(o *ora.ORA, name string) (*image.Gray, error) {
	var p *image.Gray
	if l := o.Layer(name); l != nil {
		p = image.NewGray(o.Bounds())
		i, err := l.Image()
		if err != nil {
			return nil, err
		}
		draw.Draw(p, image.Rect(0, 0, p.Bounds().Max.X, p.Bounds().Max.Y), i, image.Point{}, draw.Src)
	}
	return p, nil
}
Пример #21
0
// Fill in missing pixels
func interpolateMissingPixels(img image.Gray, mask []bool) {
	var wg sync.WaitGroup
	newMask := make([]bool, len(mask), len(mask))
	copy(newMask, mask)
	couldNotFill := false

	imgWidth := img.Bounds().Max.X
	imgHeight := img.Bounds().Max.Y
	for x := 0; x < imgWidth; x++ {
		wg.Add(1)
		go func(x int) {
			for y := 0; y < imgHeight; y++ {
				imgPos := img.PixOffset(x, y)
				if mask[imgPos] == true {
					continue
				}

				var sum int
				cnt := 0

				if x > 0 && mask[imgPos-1] {
					sum += int(img.Pix[imgPos-1])
					cnt++
				}
				if x < imgWidth-1 && mask[imgPos+1] {
					sum += int(img.Pix[imgPos+1])
					cnt++
				}
				if y > 0 && mask[imgPos-img.Stride] {
					sum += int(img.Pix[imgPos-img.Stride])
					cnt++
				}
				if y < imgHeight-1 && mask[imgPos+img.Stride] {
					sum += int(img.Pix[imgPos+img.Stride])
					cnt++
				}
				if cnt != 0 {
					img.Pix[imgPos] = uint8(sum / cnt)
					newMask[imgPos] = true
				} else {
					couldNotFill = true
				}
			}
			wg.Done()
		}(x)
	}

	wg.Wait()
	if couldNotFill {
		interpolateMissingPixels(img, newMask)
	}
}
Пример #22
0
func scaleGray(src *image.Gray, scale uint8) *image.Gray {
	bounds := src.Bounds()

	dst := image.NewGray(bounds)
	copy(dst.Pix, src.Pix)

	for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
		for x := bounds.Min.X; x < bounds.Max.X; x++ {
			dst.SetGray(x, y, color.Gray{grayAt(src, x, y).Y * scale})
		}
	}
	return dst
}
Пример #23
0
func GrayImageToMatrix(src image.Gray) (*mat64.Dense, error) {
	bounds := src.Bounds()
	rows := bounds.Max.Y
	cols := bounds.Max.X

	mtx := make([]float64, rows*cols)
	for x := 0; x < cols; x++ {
		for y := 0; y < rows; y++ {
			_, _, b, _ := src.At(x, y).RGBA()
			mtx[y*cols+x] = float64(b)
		}
	}
	return mat64.NewDense(rows, cols, mtx), nil
}
Пример #24
0
func average(oldPic *image.Gray) *Picture {
	bounds := oldPic.Bounds()
	newWidth := charWidth * (bounds.Dx() / charWidth)
	newHeight := charHeight * (bounds.Dy() / charHeight)
	newPic := New(newWidth/charWidth, newHeight/charHeight)
	for x := 0; x < newWidth-charWidth; x += charWidth {
		for y := 0; y < newHeight-charHeight; y += charHeight {
			sum := 0
			for i := x; i < x+charWidth; i++ {
				for j := y; j < y+charHeight; j++ {
					sum += int(oldPic.At(i, j).(color.Gray).Y)
				}
			}
			newPic.Set(x/charWidth, y/charHeight, uint8(sum/(charWidth*charHeight)))
		}
	}
	return newPic
}
Пример #25
0
//AutoCorrelateProjections calculates a cross-correlation of each radial
//projection with itself
func AutoCorrelateProjections(projections image.Gray) []float64 {
	size := projections.Bounds().Size()
	width := size.X
	nbProj := size.Y

	out := make([]float64, nbProj*width)

	// for each projection
	for θ := 0; θ < nbProj; θ++ {
		// log.Println("θ:", θ)
		left := projections.PixOffset(0, θ)
		right := projections.PixOffset(width, θ)
		projection := projections.Pix[left:right]
		out = append(out, AutoCorrelateSeries(projection)...)
	}

	return out
}
Пример #26
0
// floodFill fills 4-connected non-background pixels starting from (x,y) with level.
func floodFill(base *image.Gray, level byte, x, y int) image.Rectangle {
	bbox := image.Rect(x, y, x, y)
	cur := []int{y*base.Stride + x}
	for len(cur) > 0 {
		var pix []int
		try := func(j int) {
			if base.Pix[j] != 0 && base.Pix[j] != 254 && base.Pix[j] != level {
				base.Pix[j] = level
				pix = append(pix, j)
				x := j % base.Stride
				y := j / base.Stride
				if x < bbox.Min.X {
					bbox.Min.X = x
				}
				if x > bbox.Max.X {
					bbox.Max.X = x
				}
				if y < bbox.Min.Y {
					bbox.Min.Y = y
				}
				if y > bbox.Max.Y {
					bbox.Max.Y = y
				}
			}
		}
		for _, i := range cur {
			if i%base.Stride != 0 {
				try(i - 1)
			}

			if i%base.Stride != base.Stride-1 {
				try(i + 1)
			}
			if i/base.Stride > 0 {
				try(i - base.Stride)
			}
			if i/base.Stride < base.Bounds().Dy()-1 {
				try(i + base.Stride)
			}
		}
		cur = pix
	}
	return bbox
}
Пример #27
0
func (bilinear) Gray(src *image.Gray, x, y float64) color.Gray {
	p := findLinearSrc(src.Bounds(), x, y)

	// Array offsets for the surrounding pixels.
	off00 := offGray(src, p.low.X, p.low.Y)
	off01 := offGray(src, p.high.X, p.low.Y)
	off10 := offGray(src, p.low.X, p.high.Y)
	off11 := offGray(src, p.high.X, p.high.Y)

	var fc float64
	fc += float64(src.Pix[off00]) * p.frac00
	fc += float64(src.Pix[off01]) * p.frac01
	fc += float64(src.Pix[off10]) * p.frac10
	fc += float64(src.Pix[off11]) * p.frac11

	var c color.Gray
	c.Y = uint8(fc + 0.5)
	return c
}
Пример #28
0
func bilinearGray(src *image.Gray, transform TransformFunc, width, height, borderMethod int) image.Image {
	dst := image.NewGray(image.Rect(0, 0, width, height))
	b := src.Bounds()
	j := 0
	for ydst := 0; ydst < height; ydst++ {
		for xdst := 0; xdst < width; xdst++ {
			X, Y := transform(xdst, ydst)
			X -= 0.5
			Y -= 0.5
			x := int(X)
			y := int(Y)
			if X < 0.0 {
				x -= 1
			}
			if Y < 0.0 {
				y -= 1
			}
			// Are all neighbours outside the source image?
			if x < -1 || y < -1 || x >= b.Dx() || y >= b.Dy() {
				j++
				continue
			}
			// Pixel weights
			dx := X - float64(x)
			dy := Y - float64(y)
			// Image boundaries
			x += b.Min.X
			y += b.Min.Y
			// Calculate new color, add 0.5 to round to nearest integer.
			var G float64 = 0.5
			G += float64(getGray(src, x, y, borderMethod)) * (1 - dx)
			G += float64(getGray(src, x+1, y, borderMethod)) * dx
			G *= (1 - dy)
			var g float64 = 0
			g += float64(getGray(src, x, y+1, borderMethod)) * (1 - dx)
			g += float64(getGray(src, x+1, y+1, borderMethod)) * dx
			G += g * dy
			dst.Pix[j] = uint8(G)
			j++
		}
	}
	return dst
}
Пример #29
0
// encode image.Gray
func encodeGray(cinfo *C.struct_jpeg_compress_struct, src *image.Gray, p *EncoderOptions) (err error) {
	// Set up compression parameters
	cinfo.image_width = C.JDIMENSION(src.Bounds().Dx())
	cinfo.image_height = C.JDIMENSION(src.Bounds().Dy())
	cinfo.input_components = 1
	cinfo.in_color_space = C.JCS_GRAYSCALE

	C.jpeg_set_defaults(cinfo)
	setupEncoderOptions(cinfo, p)

	compInfo := (*C.jpeg_component_info)(unsafe.Pointer(cinfo.comp_info))
	compInfo.h_samp_factor, compInfo.v_samp_factor = 1, 1

	// libjpeg raw data in is in planar format, which avoids unnecessary
	// planar->packed->planar conversions.
	cinfo.raw_data_in = C.TRUE

	// Start compression
	C.jpeg_start_compress(cinfo, C.TRUE)

	// Allocate JSAMPIMAGE to hold pointers to one iMCU worth of image data
	// this is a safe overestimate; we use the return value from
	// jpeg_read_raw_data to figure out what is the actual iMCU row count.
	var rowPtr [AlignSize]C.JSAMPROW
	arrayPtr := [1]C.JSAMPARRAY{
		C.JSAMPARRAY(unsafe.Pointer(&rowPtr[0])),
	}

	var rows C.JDIMENSION
	for rows = 0; rows < cinfo.image_height; {
		// First fill in the pointers into the plane data buffers
		for j := 0; j < int(C.DCTSIZE*compInfo.v_samp_factor); j++ {
			rowPtr[j] = C.JSAMPROW(unsafe.Pointer(&src.Pix[src.Stride*(int(rows)+j)]))
		}
		// Get the data
		rows += C.jpeg_write_raw_data(cinfo, C.JSAMPIMAGE(unsafe.Pointer(&arrayPtr[0])), C.JDIMENSION(C.DCTSIZE*compInfo.v_samp_factor))
	}

	C.jpeg_finish_compress(cinfo)
	return
}
Пример #30
0
func resize1x8(src *image.Gray, dstW, dstH int) image.Image {
	srcRect := src.Bounds()
	srcW := srcRect.Dx()
	srcH := srcRect.Dy()

	dstW64, dstH64 := uint64(dstW), uint64(dstH)
	srcW64, srcH64 := uint64(srcW), uint64(srcH)

	dst := image.NewGray(image.Rect(0, 0, dstW, dstH))
	var x, y uint64
	dstI := 0
	for y = 0; y < dstH64; y++ {
		srcY := int(y * srcH64 / dstH64)
		for x = 0; x < dstW64; x++ {
			srcX := int(x * srcW64 / dstW64)
			dst.Pix[dstI] = src.Pix[srcY*srcW+srcX]
			dstI++
		}
	}
	return dst
}