mirror of
				https://github.com/esimov/caire.git
				synced 2025-10-31 20:02:32 +08:00 
			
		
		
		
	test: added new test cases
This commit is contained in:
		
							
								
								
									
										204
									
								
								carver_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										204
									
								
								carver_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,204 @@ | |||||||
|  | package caire | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"image" | ||||||
|  | 	"image/color" | ||||||
|  | 	"image/draw" | ||||||
|  | 	"testing" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | var p *Processor | ||||||
|  |  | ||||||
|  | func init() { | ||||||
|  | 	p = &Processor{ | ||||||
|  | 		NewWidth:       ImgWidth, | ||||||
|  | 		NewHeight:      ImgHeight, | ||||||
|  | 		BlurRadius:     1, | ||||||
|  | 		SobelThreshold: 4, | ||||||
|  | 		Percentage:     false, | ||||||
|  | 		Square:         false, | ||||||
|  | 		Debug:          false, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestCarver_EnergySeamShouldNotBeDetected(t *testing.T) { | ||||||
|  | 	var seams [][]Seam | ||||||
|  | 	var totalEnergySeams int | ||||||
|  |  | ||||||
|  | 	img := image.NewNRGBA(image.Rect(0, 0, ImgWidth, ImgHeight)) | ||||||
|  | 	dx, dy := img.Bounds().Dx(), img.Bounds().Dy() | ||||||
|  |  | ||||||
|  | 	var c = NewCarver(dx, dy) | ||||||
|  | 	for x := 0; x < ImgWidth; x++ { | ||||||
|  | 		width, height := img.Bounds().Max.X, img.Bounds().Max.Y | ||||||
|  | 		c = NewCarver(width, height) | ||||||
|  | 		c.ComputeSeams(img, p) | ||||||
|  | 		les := c.FindLowestEnergySeams() | ||||||
|  | 		seams = append(seams, les) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for i := 0; i < len(seams); i++ { | ||||||
|  | 		for s := 0; s < len(seams[i]); s++ { | ||||||
|  | 			totalEnergySeams += seams[i][s].X | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if totalEnergySeams != 0 { | ||||||
|  | 		t.Errorf("Energy seam shouldn't been detected") | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestCarver_DetectHorizontalEnergySeam(t *testing.T) { | ||||||
|  | 	var seams [][]Seam | ||||||
|  | 	var totalEnergySeams int | ||||||
|  |  | ||||||
|  | 	img := image.NewNRGBA(image.Rect(0, 0, ImgWidth, ImgHeight)) | ||||||
|  | 	draw.Draw(img, img.Bounds(), &image.Uniform{image.White}, image.ZP, draw.Src) | ||||||
|  |  | ||||||
|  | 	// Replace the pixel colors in a single row from 0xff to 0xdd. 5 is an arbitrary value. | ||||||
|  | 	// The seam detector should recognize that line as being of low energy density | ||||||
|  | 	// and should perform the seam computation process. | ||||||
|  | 	// This way we'll make sure, that the seam detector correctly detects one and only one line. | ||||||
|  | 	dx, dy := img.Bounds().Dx(), img.Bounds().Dy() | ||||||
|  | 	for x := 0; x < dx; x++ { | ||||||
|  | 		img.Pix[(5*dx+x)*4+0] = 0xdd | ||||||
|  | 		img.Pix[(5*dx+x)*4+1] = 0xdd | ||||||
|  | 		img.Pix[(5*dx+x)*4+2] = 0xdd | ||||||
|  | 		img.Pix[(5*dx+x)*4+3] = 0xdd | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var c = NewCarver(dx, dy) | ||||||
|  | 	for x := 0; x < ImgWidth; x++ { | ||||||
|  | 		width, height := img.Bounds().Max.X, img.Bounds().Max.Y | ||||||
|  | 		c = NewCarver(width, height) | ||||||
|  | 		c.ComputeSeams(img, p) | ||||||
|  | 		les := c.FindLowestEnergySeams() | ||||||
|  | 		seams = append(seams, les) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for i := 0; i < len(seams); i++ { | ||||||
|  | 		for s := 0; s < len(seams[i]); s++ { | ||||||
|  | 			totalEnergySeams += seams[i][s].X | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if totalEnergySeams == 0 { | ||||||
|  | 		t.Errorf("The seam detector should have detected a horizontal energy seam") | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestCarver_DetectVerticalEnergySeam(t *testing.T) { | ||||||
|  | 	var seams [][]Seam | ||||||
|  | 	var totalEnergySeams int | ||||||
|  |  | ||||||
|  | 	img := image.NewNRGBA(image.Rect(0, 0, ImgWidth, ImgHeight)) | ||||||
|  | 	draw.Draw(img, img.Bounds(), &image.Uniform{image.White}, image.ZP, draw.Src) | ||||||
|  |  | ||||||
|  | 	// Replace the pixel colors in a single column from 0xff to 0xdd. 5 is an arbitrary value. | ||||||
|  | 	// The seam detector should recognize that line as being of low energy density | ||||||
|  | 	// and should perform the seam computation process. | ||||||
|  | 	// This way we'll make sure, that the seam detector correctly detects one and only one line. | ||||||
|  | 	dx, dy := img.Bounds().Dx(), img.Bounds().Dy() | ||||||
|  | 	for y := 0; y < dy; y++ { | ||||||
|  | 		img.Pix[5*4+(dx*y)*4+0] = 0xdd | ||||||
|  | 		img.Pix[5*4+(dx*y)*4+1] = 0xdd | ||||||
|  | 		img.Pix[5*4+(dx*y)*4+2] = 0xdd | ||||||
|  | 		img.Pix[5*4+(dx*y)*4+3] = 0xff | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var c = NewCarver(dx, dy) | ||||||
|  | 	img = c.RotateImage90(img) | ||||||
|  | 	for x := 0; x < ImgHeight; x++ { | ||||||
|  | 		width, height := img.Bounds().Max.X, img.Bounds().Max.Y | ||||||
|  | 		c = NewCarver(width, height) | ||||||
|  | 		c.ComputeSeams(img, p) | ||||||
|  | 		les := c.FindLowestEnergySeams() | ||||||
|  | 		seams = append(seams, les) | ||||||
|  | 	} | ||||||
|  | 	img = c.RotateImage270(img) | ||||||
|  |  | ||||||
|  | 	for i := 0; i < len(seams); i++ { | ||||||
|  | 		for s := 0; s < len(seams[i]); s++ { | ||||||
|  | 			totalEnergySeams += seams[i][s].X | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if totalEnergySeams == 0 { | ||||||
|  | 		t.Errorf("The seam detector should have detected a vertical energy seam") | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestCarver_RemoveSeam(t *testing.T) { | ||||||
|  | 	img := image.NewNRGBA(image.Rect(0, 0, ImgWidth, ImgHeight)) | ||||||
|  | 	bounds := img.Bounds() | ||||||
|  |  | ||||||
|  | 	// We choose to fill up the background with an uniform white color | ||||||
|  | 	// and afterwards we replace the colors in a single row with lower intensity ones. | ||||||
|  | 	draw.Draw(img, bounds, &image.Uniform{image.White}, image.ZP, draw.Src) | ||||||
|  | 	origImg := img | ||||||
|  |  | ||||||
|  | 	dx, dy := img.Bounds().Dx(), img.Bounds().Dy() | ||||||
|  | 	// Replace the pixels in row 5 with lower intensity colors. | ||||||
|  | 	for x := 0; x < dx; x++ { | ||||||
|  | 		img.Set(x, 5, color.RGBA{R: 0xdd, G: 0xdd, B: 0xdd, A: 0xff}) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	c := NewCarver(dx, dy) | ||||||
|  | 	c.ComputeSeams(img, p) | ||||||
|  | 	seams := c.FindLowestEnergySeams() | ||||||
|  | 	img = c.RemoveSeam(img, seams, false) | ||||||
|  |  | ||||||
|  | 	isEq := true | ||||||
|  | 	// The test should pass if the detector correctly finds the row wich pixel values are of lower intensity. | ||||||
|  | 	for x := 0; x < dx; x++ { | ||||||
|  | 		for y := 0; y < dy; y++ { | ||||||
|  | 			// In case the seam detector correctly recognize the modified line as of low importance | ||||||
|  | 			// it should remove it, which means the new image width should be 1px less then the original image. | ||||||
|  | 			r0, g0, b0, _ := origImg.At(x, y).RGBA() | ||||||
|  | 			r1, g1, b1, _ := img.At(x, y).RGBA() | ||||||
|  |  | ||||||
|  | 			if r0>>8 != r1>>8 && g0>>8 != g1>>8 && b0>>8 != b1>>8 { | ||||||
|  | 				isEq = false | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if isEq { | ||||||
|  | 		t.Errorf("Seam should have been removed") | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestCarver_AddSeam(t *testing.T) { | ||||||
|  | 	img := image.NewNRGBA(image.Rect(0, 0, ImgWidth, ImgHeight)) | ||||||
|  | 	bounds := img.Bounds() | ||||||
|  |  | ||||||
|  | 	// We choose to fill up the background with an uniform white color | ||||||
|  | 	// Afterwards we'll replace the colors in a single row with lower intensity ones. | ||||||
|  | 	draw.Draw(img, bounds, &image.Uniform{image.White}, image.ZP, draw.Src) | ||||||
|  | 	origImg := img | ||||||
|  |  | ||||||
|  | 	dx, dy := img.Bounds().Dx(), img.Bounds().Dy() | ||||||
|  | 	// Replace the pixels in row 5 with lower intensity colors. | ||||||
|  | 	for x := 0; x < dx; x++ { | ||||||
|  | 		img.Set(x, 5, color.RGBA{R: 0xdd, G: 0xdd, B: 0xdd, A: 0xff}) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	c := NewCarver(dx, dy) | ||||||
|  | 	c.ComputeSeams(img, p) | ||||||
|  | 	seams := c.FindLowestEnergySeams() | ||||||
|  | 	img = c.AddSeam(img, seams, false) | ||||||
|  |  | ||||||
|  | 	dx, dy = img.Bounds().Dx(), img.Bounds().Dy() | ||||||
|  |  | ||||||
|  | 	isEq := true | ||||||
|  | 	// The test should pass if the detector correctly finds the row wich has lower intensity colors. | ||||||
|  | 	for x := 0; x < dx; x++ { | ||||||
|  | 		for y := 0; y < dy; y++ { | ||||||
|  | 			r0, g0, b0, _ := origImg.At(x, y).RGBA() | ||||||
|  | 			r1, g1, b1, _ := img.At(x, y).RGBA() | ||||||
|  |  | ||||||
|  | 			if r0>>8 != r1>>8 && g0>>8 != g1>>8 && b0>>8 != b1>>8 { | ||||||
|  | 				isEq = false | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if isEq { | ||||||
|  | 		t.Errorf("Seam should have been added") | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -6,10 +6,12 @@ import ( | |||||||
| 	"testing" | 	"testing" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| const ImgWidth = 10 | const ( | ||||||
| const ImgHeight = 10 | 	ImgWidth  = 10 | ||||||
|  | 	ImgHeight = 10 | ||||||
|  | ) | ||||||
|  |  | ||||||
| func TestGrayscale(t *testing.T) { | func TestImage_GrayscaleMode(t *testing.T) { | ||||||
| 	img := image.NewRGBA(image.Rect(0, 0, ImgWidth, ImgHeight)) | 	img := image.NewRGBA(image.Rect(0, 0, ImgWidth, ImgHeight)) | ||||||
| 	for i := 0; i < img.Bounds().Dx(); i++ { | 	for i := 0; i < img.Bounds().Dx(); i++ { | ||||||
| 		for j := 0; j < img.Bounds().Dy(); j++ { | 		for j := 0; j < img.Bounds().Dy(); j++ { | ||||||
|   | |||||||
| @@ -417,7 +417,7 @@ func (p *Processor) Process(r io.Reader, w io.Writer) error { | |||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	img := imgToNRGBA(src) | 	img := p.imgToNRGBA(src) | ||||||
|  |  | ||||||
| 	switch w.(type) { | 	switch w.(type) { | ||||||
| 	case *os.File: | 	case *os.File: | ||||||
| @@ -491,7 +491,7 @@ func (p *Processor) enlarge(c *Carver, img *image.NRGBA) (*image.NRGBA, error) { | |||||||
| } | } | ||||||
|  |  | ||||||
| // imgToNRGBA converts any image type to *image.NRGBA with min-point at (0, 0). | // imgToNRGBA converts any image type to *image.NRGBA with min-point at (0, 0). | ||||||
| func imgToNRGBA(img image.Image) *image.NRGBA { | func (p *Processor) imgToNRGBA(img image.Image) *image.NRGBA { | ||||||
| 	srcBounds := img.Bounds() | 	srcBounds := img.Bounds() | ||||||
| 	if srcBounds.Min.X == 0 && srcBounds.Min.Y == 0 { | 	if srcBounds.Min.X == 0 && srcBounds.Min.Y == 0 { | ||||||
| 		if src0, ok := img.(*image.NRGBA); ok { | 		if src0, ok := img.(*image.NRGBA); ok { | ||||||
|   | |||||||
| @@ -5,25 +5,14 @@ import ( | |||||||
| 	"testing" | 	"testing" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func TestProcessor_Resize(t *testing.T) { | func TestResize_ReduceImageWidth(t *testing.T) { | ||||||
| 	reduceImageH(t) |  | ||||||
| 	reduceImageV(t) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func reduceImageH(t *testing.T) { |  | ||||||
| 	img := image.NewNRGBA(image.Rect(0, 0, ImgWidth, ImgHeight)) | 	img := image.NewNRGBA(image.Rect(0, 0, ImgWidth, ImgHeight)) | ||||||
| 	var c = NewCarver(img.Bounds().Dx(), img.Bounds().Dy()) | 	var c = NewCarver(img.Bounds().Dx(), img.Bounds().Dy()) | ||||||
| 	newWidth := ImgWidth / 2 | 	newWidth := ImgWidth / 2 | ||||||
| 	p := &Processor{ |  | ||||||
| 		BlurRadius:     2, | 	p.NewWidth = newWidth | ||||||
| 		SobelThreshold: 10, | 	p.NewHeight = ImgHeight | ||||||
| 		NewWidth:       newWidth, |  | ||||||
| 		NewHeight:      ImgHeight, |  | ||||||
| 		Percentage:     false, |  | ||||||
| 		Square:         false, |  | ||||||
| 		Debug:          false, |  | ||||||
| 	} |  | ||||||
| 	// Reduce image size horizontally |  | ||||||
| 	for x := 0; x < newWidth; x++ { | 	for x := 0; x < newWidth; x++ { | ||||||
| 		width, height := img.Bounds().Max.X, img.Bounds().Max.Y | 		width, height := img.Bounds().Max.X, img.Bounds().Max.Y | ||||||
| 		c = NewCarver(width, height) | 		c = NewCarver(width, height) | ||||||
| @@ -38,20 +27,14 @@ func reduceImageH(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func reduceImageV(t *testing.T) { | func TestResize_ReduceImageHeight(t *testing.T) { | ||||||
| 	img := image.NewNRGBA(image.Rect(0, 0, ImgWidth, ImgHeight)) | 	img := image.NewNRGBA(image.Rect(0, 0, ImgWidth, ImgHeight)) | ||||||
| 	var c = NewCarver(img.Bounds().Dx(), img.Bounds().Dy()) | 	var c = NewCarver(img.Bounds().Dx(), img.Bounds().Dy()) | ||||||
| 	newHeight := ImgHeight / 2 | 	newHeight := ImgHeight / 2 | ||||||
| 	p := &Processor{ |  | ||||||
| 		BlurRadius:     2, | 	p.NewWidth = ImgWidth | ||||||
| 		SobelThreshold: 10, | 	p.NewHeight = newHeight | ||||||
| 		NewWidth:       ImgWidth, |  | ||||||
| 		NewHeight:      newHeight, |  | ||||||
| 		Percentage:     false, |  | ||||||
| 		Square:         false, |  | ||||||
| 		Debug:          false, |  | ||||||
| 	} |  | ||||||
| 	// Reduce image size horizontally |  | ||||||
| 	img = c.RotateImage90(img) | 	img = c.RotateImage90(img) | ||||||
| 	for x := 0; x < newHeight; x++ { | 	for x := 0; x < newHeight; x++ { | ||||||
| 		width, height := img.Bounds().Max.X, img.Bounds().Max.Y | 		width, height := img.Bounds().Max.X, img.Bounds().Max.Y | ||||||
| @@ -67,3 +50,51 @@ func reduceImageV(t *testing.T) { | |||||||
| 		t.Errorf("Resulted image height expected to be %v. Got %v", newHeight, imgHeight) | 		t.Errorf("Resulted image height expected to be %v. Got %v", newHeight, imgHeight) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestResize_IncreaseImageWidth(t *testing.T) { | ||||||
|  | 	img := image.NewNRGBA(image.Rect(0, 0, ImgWidth, ImgHeight)) | ||||||
|  | 	origImgWidth := img.Bounds().Dx() | ||||||
|  | 	var c = NewCarver(img.Bounds().Dx(), img.Bounds().Dy()) | ||||||
|  | 	newWidth := ImgWidth * 2 | ||||||
|  |  | ||||||
|  | 	p.NewWidth = newWidth | ||||||
|  | 	p.NewHeight = ImgHeight | ||||||
|  |  | ||||||
|  | 	for x := 0; x < newWidth; x++ { | ||||||
|  | 		width, height := img.Bounds().Max.X, img.Bounds().Max.Y | ||||||
|  | 		c = NewCarver(width, height) | ||||||
|  | 		c.ComputeSeams(img, p) | ||||||
|  | 		seams := c.FindLowestEnergySeams() | ||||||
|  | 		img = c.AddSeam(img, seams, p.Debug) | ||||||
|  | 	} | ||||||
|  | 	imgWidth := img.Bounds().Max.X - origImgWidth | ||||||
|  |  | ||||||
|  | 	if imgWidth != newWidth { | ||||||
|  | 		t.Errorf("Resulted image width expected to be %v. Got %v", newWidth, imgWidth) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestResize_IncreaseImageHeight(t *testing.T) { | ||||||
|  | 	img := image.NewNRGBA(image.Rect(0, 0, ImgWidth, ImgHeight)) | ||||||
|  | 	origImgHeigth := img.Bounds().Dy() | ||||||
|  | 	var c = NewCarver(img.Bounds().Dx(), img.Bounds().Dy()) | ||||||
|  | 	newHeight := ImgHeight * 2 | ||||||
|  |  | ||||||
|  | 	p.NewWidth = ImgWidth | ||||||
|  | 	p.NewHeight = newHeight | ||||||
|  |  | ||||||
|  | 	img = c.RotateImage90(img) | ||||||
|  | 	for x := 0; x < newHeight; x++ { | ||||||
|  | 		width, height := img.Bounds().Max.X, img.Bounds().Max.Y | ||||||
|  | 		c = NewCarver(width, height) | ||||||
|  | 		c.ComputeSeams(img, p) | ||||||
|  | 		seams := c.FindLowestEnergySeams() | ||||||
|  | 		img = c.AddSeam(img, seams, p.Debug) | ||||||
|  | 	} | ||||||
|  | 	img = c.RotateImage270(img) | ||||||
|  | 	imgHeight := img.Bounds().Max.Y - origImgHeigth | ||||||
|  |  | ||||||
|  | 	if imgHeight != newHeight { | ||||||
|  | 		t.Errorf("Resulted image height expected to be %v. Got %v", newHeight, imgHeight) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 esimov
					esimov