Test rework, bugfixes and more tests
|
@ -5,10 +5,13 @@ import (
|
||||||
"math"
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
func rgbtoXYZ(r, g, b uint32) (x, y, z float64) {
|
// colorToXYZ returns CIE XYZ representation of color.
|
||||||
varR := float64(r) / 255
|
// https://en.wikipedia.org/wiki/Color_model#CIE_XYZ_color_space
|
||||||
varG := float64(g) / 255
|
func colorToXYZ(color color.Color) (x, y, z float64) {
|
||||||
varB := float64(b) / 255
|
r, g, b, _ := color.RGBA()
|
||||||
|
varR := float64(r>>8) / 255
|
||||||
|
varG := float64(g>>8) / 255
|
||||||
|
varB := float64(b>>8) / 255
|
||||||
|
|
||||||
if varR > 0.04045 {
|
if varR > 0.04045 {
|
||||||
varR = math.Pow((varR+0.055)/1.055, 2.4)
|
varR = math.Pow((varR+0.055)/1.055, 2.4)
|
||||||
|
@ -28,16 +31,15 @@ func rgbtoXYZ(r, g, b uint32) (x, y, z float64) {
|
||||||
varB = varB / 12.92
|
varB = varB / 12.92
|
||||||
}
|
}
|
||||||
|
|
||||||
varR = varR * 100
|
x = varR*41.24 + varG*35.76 + varB*18.05
|
||||||
varG = varG * 100
|
y = varR*21.26 + varG*71.52 + varB*7.22
|
||||||
varB = varB * 100
|
z = varR*1.93 + varG*11.92 + varB*95.05
|
||||||
|
|
||||||
x = varR*0.4124 + varG*0.3576 + varB*0.1805
|
|
||||||
y = varR*0.2126 + varG*0.7152 + varB*0.0722
|
|
||||||
z = varR*0.0193 + varG*0.1192 + varB*0.9505
|
|
||||||
return x, y, z
|
return x, y, z
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// xyztoLAB converts CIE XYZ color space to CIE LAB color space
|
||||||
|
// https://en.wikipedia.org/wiki/Lab_color_space#CIELAB-CIEXYZ_conversions
|
||||||
func xyztoLAB(x, y, z float64) (l, a, b float64) {
|
func xyztoLAB(x, y, z float64) (l, a, b float64) {
|
||||||
refX, refY, refZ := 95.047, 100.000, 108.883 // Daylight, sRGB, Adobe-RGB, Observer D65, 2°
|
refX, refY, refZ := 95.047, 100.000, 108.883 // Daylight, sRGB, Adobe-RGB, Observer D65, 2°
|
||||||
|
|
||||||
|
@ -68,7 +70,8 @@ func xyztoLAB(x, y, z float64) (l, a, b float64) {
|
||||||
return l, a, b
|
return l, a, b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// colorToLAB returns LAB representation of any color (without aplha)
|
||||||
|
// https://en.wikipedia.org/wiki/Lab_color_space
|
||||||
func colorToLAB(color color.Color) (l, a, b float64) {
|
func colorToLAB(color color.Color) (l, a, b float64) {
|
||||||
cr, cg, cb, _ := color.RGBA()
|
return xyztoLAB(colorToXYZ(color))
|
||||||
return xyztoLAB(rgbtoXYZ(cr, cg, cb))
|
|
||||||
}
|
}
|
||||||
|
|
28
colorconverson_test.go
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
package colorcrop
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image/color"
|
||||||
|
"math"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestColorToLAB(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
color color.Color
|
||||||
|
expectedL, expectedA, expectedB float64
|
||||||
|
gotL, gotA, gotB float64
|
||||||
|
}{
|
||||||
|
{color: color.RGBA{0, 0, 0, 255}, expectedL: 0.0, expectedA: 0.0, expectedB: 0.0},
|
||||||
|
{color: color.RGBA{0, 0, 255, 255}, expectedL: 32.30258667, expectedA: 79.19666179, expectedB: -107.86368104},
|
||||||
|
{color: color.RGBA{0, 255, 0, 255}, expectedL: 87.73703347, expectedA: -86.18463650, expectedB: 83.18116475},
|
||||||
|
{color: color.RGBA{255, 0, 0, 255}, expectedL: 53.23288179, expectedA: 80.10930953, expectedB: 67.22006831},
|
||||||
|
{color: color.RGBA{255, 255, 255, 255}, expectedL: 100.00000000, expectedA: 0.00526050, expectedB: -0.01040818},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
test.gotL, test.gotA, test.gotB = colorToLAB(test.color)
|
||||||
|
if math.Abs(test.gotL-test.expectedL) > epsilon || math.Abs(test.gotA-test.expectedA) > epsilon || math.Abs(test.gotB-test.expectedB) > epsilon {
|
||||||
|
t.Errorf("%v: expected {%.8f, %.8f, %.8f}, got {%.8f, %.8f, %.8f}", test.color, test.expectedL, test.expectedA, test.expectedB, test.gotL, test.gotA, test.gotB)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
72
colorcrop_test.go
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
package colorcrop
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image"
|
||||||
|
"image/color"
|
||||||
|
"image/png"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// epsilon is a maximum permissible error
|
||||||
|
const epsilon = 0.00000001
|
||||||
|
|
||||||
|
func TestCropRectanle(t *testing.T) {
|
||||||
|
type test struct {
|
||||||
|
filename string
|
||||||
|
expected image.Rectangle
|
||||||
|
got image.Rectangle
|
||||||
|
}
|
||||||
|
|
||||||
|
comparators := []comparator{CmpRGBComponents, CmpEuclidean, CmpCIE76}
|
||||||
|
thresold := 0.5
|
||||||
|
|
||||||
|
tests := []test{
|
||||||
|
{filename: "01.png", expected: image.Rectangle{image.Point{0, 0}, image.Point{1, 1}}},
|
||||||
|
{filename: "02.png", expected: image.Rectangle{image.Point{1, 0}, image.Point{2, 1}}},
|
||||||
|
{filename: "03.png", expected: image.Rectangle{image.Point{2, 0}, image.Point{3, 1}}},
|
||||||
|
{filename: "04.png", expected: image.Rectangle{image.Point{3, 0}, image.Point{4, 1}}},
|
||||||
|
{filename: "05.png", expected: image.Rectangle{image.Point{0, 1}, image.Point{1, 2}}},
|
||||||
|
{filename: "06.png", expected: image.Rectangle{image.Point{1, 1}, image.Point{2, 2}}},
|
||||||
|
{filename: "07.png", expected: image.Rectangle{image.Point{2, 1}, image.Point{3, 2}}},
|
||||||
|
{filename: "08.png", expected: image.Rectangle{image.Point{3, 1}, image.Point{4, 2}}},
|
||||||
|
{filename: "09.png", expected: image.Rectangle{image.Point{0, 2}, image.Point{1, 3}}},
|
||||||
|
{filename: "10.png", expected: image.Rectangle{image.Point{1, 2}, image.Point{2, 3}}},
|
||||||
|
{filename: "11.png", expected: image.Rectangle{image.Point{2, 2}, image.Point{3, 3}}},
|
||||||
|
{filename: "12.png", expected: image.Rectangle{image.Point{3, 2}, image.Point{4, 3}}},
|
||||||
|
{filename: "13.png", expected: image.Rectangle{image.Point{0, 3}, image.Point{1, 4}}},
|
||||||
|
{filename: "14.png", expected: image.Rectangle{image.Point{1, 3}, image.Point{2, 4}}},
|
||||||
|
{filename: "15.png", expected: image.Rectangle{image.Point{2, 3}, image.Point{3, 4}}},
|
||||||
|
{filename: "16.png", expected: image.Rectangle{image.Point{3, 3}, image.Point{4, 4}}},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, comparator := range comparators {
|
||||||
|
for _, test := range tests {
|
||||||
|
file, err := os.Open("testimages/" + test.filename)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
image, err := png.Decode(file)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
test.got = cropRectanle(image, color.RGBA{255, 255, 255, 255}, thresold, comparator)
|
||||||
|
if !reflect.DeepEqual(test.expected, test.got) {
|
||||||
|
t.Errorf("expected %v, got %v for comparator: %s, file: %s", test.expected, test.got, getFuncName(comparator), test.filename)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFuncName(i interface{}) string {
|
||||||
|
s := runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
|
||||||
|
p := strings.LastIndex(s, ".")
|
||||||
|
if p > 0 {
|
||||||
|
return string([]rune(s)[p+1:])
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ import (
|
||||||
type comparator func(color.Color, color.Color) float64
|
type comparator func(color.Color, color.Color) float64
|
||||||
|
|
||||||
// CmpEuclidean returns Euclidean difference of two colors.
|
// CmpEuclidean returns Euclidean difference of two colors.
|
||||||
|
//
|
||||||
// https://en.wikipedia.org/wiki/Color_difference#Euclidean
|
// https://en.wikipedia.org/wiki/Color_difference#Euclidean
|
||||||
func CmpEuclidean(color1 color.Color, color2 color.Color) float64 {
|
func CmpEuclidean(color1 color.Color, color2 color.Color) float64 {
|
||||||
const maxDiff = 113509.94967402637 // Difference between black and white colors
|
const maxDiff = 113509.94967402637 // Difference between black and white colors
|
||||||
|
@ -29,8 +30,8 @@ func CmpRGBComponents(color1 color.Color, color2 color.Color) float64 {
|
||||||
r1, g1, b1, _ := color1.RGBA()
|
r1, g1, b1, _ := color1.RGBA()
|
||||||
r2, g2, b2, _ := color2.RGBA()
|
r2, g2, b2, _ := color2.RGBA()
|
||||||
|
|
||||||
r1, g1, b1 = r1/256, g1/256, b1/256
|
r1, g1, b1 = r1>>8, g1>>8, b1>>8
|
||||||
r2, g2, b2 = r2/256, g2/256, b2/256
|
r2, g2, b2 = r2>>8, g2>>8, b2>>8
|
||||||
|
|
||||||
return float64((max(r1, r2)-min(r1, r2))+
|
return float64((max(r1, r2)-min(r1, r2))+
|
||||||
(max(g1, g2)-min(g1, g2))+
|
(max(g1, g2)-min(g1, g2))+
|
||||||
|
@ -38,15 +39,13 @@ func CmpRGBComponents(color1 color.Color, color2 color.Color) float64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CmpCIE76 returns difference of two colors defined in CIE76 standart.
|
// CmpCIE76 returns difference of two colors defined in CIE76 standart.
|
||||||
|
//
|
||||||
// https://en.wikipedia.org/wiki/Color_difference#CIE76
|
// https://en.wikipedia.org/wiki/Color_difference#CIE76
|
||||||
func CmpCIE76(color1 color.Color, color2 color.Color) float64 {
|
func CmpCIE76(color1 color.Color, color2 color.Color) float64 {
|
||||||
const maxDiff = 149.95514755026548 // Difference between blue and white colors
|
const maxDiff = 149.95514755 // Difference between blue and white colors
|
||||||
|
|
||||||
r1, g1, b1, _ := color1.RGBA()
|
cl1, ca1, cb1 := colorToLAB(color1)
|
||||||
r2, g2, b2, _ := color2.RGBA()
|
cl2, ca2, cb2 := colorToLAB(color2)
|
||||||
|
|
||||||
cl1, ca1, cb1 := xyztoLAB(rgbtoXYZ(r1/256, g1/256, b1/256))
|
|
||||||
cl2, ca2, cb2 := xyztoLAB(rgbtoXYZ(r2/256, g2/256, b2/256))
|
|
||||||
|
|
||||||
return math.Sqrt(distance(cl2, cl1)+distance(ca2, ca1)+distance(cb2, cb1)) / maxDiff
|
return math.Sqrt(distance(cl2, cl1)+distance(ca2, ca1)+distance(cb2, cb1)) / maxDiff
|
||||||
}
|
}
|
||||||
|
@ -55,6 +54,7 @@ func distance(x, y float64) float64 {
|
||||||
return (x - y) * (x - y)
|
return (x - y) * (x - y)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// min is minimum of two uint32
|
||||||
func min(a, b uint32) uint32 {
|
func min(a, b uint32) uint32 {
|
||||||
if a < b {
|
if a < b {
|
||||||
return a
|
return a
|
||||||
|
@ -62,6 +62,7 @@ func min(a, b uint32) uint32 {
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// max is maximum of two uint32
|
||||||
func max(a, b uint32) uint32 {
|
func max(a, b uint32) uint32 {
|
||||||
if a > b {
|
if a > b {
|
||||||
return a
|
return a
|
||||||
|
|
|
@ -2,40 +2,102 @@ package colorcrop
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"image/color"
|
"image/color"
|
||||||
"reflect"
|
"math"
|
||||||
"runtime"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestColorComparators(t *testing.T) {
|
func TestLinearComparators(t *testing.T) {
|
||||||
type In struct {
|
|
||||||
color1 color.Color
|
|
||||||
color2 color.Color
|
|
||||||
}
|
|
||||||
|
|
||||||
comparators := []comparator{CmpEuclidean, CmpRGBComponents}
|
comparators := []comparator{CmpEuclidean, CmpRGBComponents}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
in In
|
color1 color.Color
|
||||||
out float64
|
color2 color.Color
|
||||||
commentary string
|
expected float64
|
||||||
|
got float64
|
||||||
}{
|
}{
|
||||||
{in: In{color.RGBA{0, 0, 0, 255}, color.RGBA{255, 255, 255, 255}},
|
{color1: color.RGBA{0, 0, 0, 255}, color2: color.RGBA{0, 0, 0, 255}, expected: 0.00}, // same black colors
|
||||||
out: 1.00,
|
{color1: color.RGBA{255, 255, 255, 255}, color2: color.RGBA{255, 255, 255, 255}, expected: 0.00}, // same white colors
|
||||||
commentary: "Difference between black and white colors"},
|
{color1: color.RGBA{0, 0, 0, 255}, color2: color.RGBA{255, 255, 255, 255}, expected: 1.00}, // different (black and white) colors
|
||||||
{in: In{color.RGBA{255, 255, 255, 255}, color.RGBA{255, 255, 255, 255}},
|
{color1: color.RGBA{255, 255, 255, 255}, color2: color.RGBA{0, 0, 0, 255}, expected: 1.00}, // different (white and black) colors
|
||||||
out: 0.00,
|
{color1: color.RGBA{255, 255, 255, 0}, color2: color.RGBA{255, 255, 255, 255}, expected: 0.00}, // must ignore alpha channel
|
||||||
commentary: "Difference between same colors"},
|
|
||||||
{in: In{color.RGBA{255, 255, 255, 0}, color.RGBA{255, 255, 255, 255}},
|
|
||||||
out: 0.00,
|
|
||||||
commentary: "Difference between same colors with different transparency"},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, comparator := range comparators {
|
for _, comparator := range comparators {
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
if comparator(test.in.color2, test.in.color1) != test.out {
|
test.got = comparator(test.color1, test.color2)
|
||||||
t.Errorf("%s: %s: expected %.2f, got %.2f", runtime.FuncForPC(reflect.ValueOf(comparator).Pointer()).Name(), test.commentary, test.out, comparator(test.in.color2, test.in.color1))
|
if math.Abs(test.got-test.expected) > epsilon {
|
||||||
|
t.Errorf("%v %v: expected %.8f, got %.8f", test.color1, test.color2, test.expected, test.got)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCmpCIE76(t *testing.T) {
|
||||||
|
type test struct {
|
||||||
|
color1 color.Color
|
||||||
|
color2 color.Color
|
||||||
|
expected float64
|
||||||
|
got float64
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []test{
|
||||||
|
{color1: color.RGBA{0, 0, 0, 255}, color2: color.RGBA{0, 0, 0, 255}, expected: 0.00000000 / 149.95514755}, // same black colors
|
||||||
|
{color1: color.RGBA{255, 255, 255, 255}, color2: color.RGBA{255, 255, 255, 255}, expected: 0.00000000 / 149.95514755}, // same white colors
|
||||||
|
{color1: color.RGBA{0, 0, 0, 255}, color2: color.RGBA{255, 255, 255, 255}, expected: 100.00000068 / 149.95514755}, // different (black and white) colors
|
||||||
|
{color1: color.RGBA{255, 255, 255, 255}, color2: color.RGBA{0, 0, 0, 255}, expected: 100.00000068 / 149.95514755}, // different (white and black) colors
|
||||||
|
{color1: color.RGBA{255, 0, 0, 255}, color2: color.RGBA{255, 255, 255, 255}, expected: 114.55897602 / 149.95514755}, // different (red and white) colors
|
||||||
|
{color1: color.RGBA{0, 255, 0, 255}, color2: color.RGBA{255, 255, 255, 255}, expected: 120.41559907 / 149.95514755}, // different (green and white) colors
|
||||||
|
{color1: color.RGBA{0, 0, 255, 255}, color2: color.RGBA{255, 255, 255, 255}, expected: 149.95514755 / 149.95514755}, // different (blue and white) colors
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
test.got = CmpCIE76(test.color1, test.color2)
|
||||||
|
if math.Abs(test.got-test.expected) > epsilon {
|
||||||
|
t.Errorf("%v %v: expected %.8f, got %.8f", test.color1, test.color2, test.expected, test.got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMin(t *testing.T) {
|
||||||
|
type test struct {
|
||||||
|
x uint32
|
||||||
|
y uint32
|
||||||
|
expected uint32
|
||||||
|
got uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []test{
|
||||||
|
{x: 1, y: 2, expected: 1},
|
||||||
|
{x: 3, y: 2, expected: 2},
|
||||||
|
{x: 4, y: 4, expected: 4},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
test.got = min(test.x, test.y)
|
||||||
|
if test.got != test.expected {
|
||||||
|
t.Errorf("min(%d, %d): expected %d, got %d", test.x, test.y, test.expected, test.got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMax(t *testing.T) {
|
||||||
|
type test struct {
|
||||||
|
x uint32
|
||||||
|
y uint32
|
||||||
|
expected uint32
|
||||||
|
got uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []test{
|
||||||
|
{x: 1, y: 2, expected: 2},
|
||||||
|
{x: 3, y: 2, expected: 3},
|
||||||
|
{x: 4, y: 4, expected: 4},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
test.got = max(test.x, test.y)
|
||||||
|
if test.got != test.expected {
|
||||||
|
t.Errorf("max(%d, %d): expected %d, got %d", test.x, test.y, test.expected, test.got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
package colorcrop_test
|
package colorcrop_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -9,7 +12,7 @@ import (
|
||||||
"github.com/nxshock/colorcrop"
|
"github.com/nxshock/colorcrop"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Example() {
|
func ExampleBasicUsage() {
|
||||||
log.SetFlags(0)
|
log.SetFlags(0)
|
||||||
|
|
||||||
// Read source image
|
// Read source image
|
||||||
|
@ -18,8 +21,34 @@ func Example() {
|
||||||
|
|
||||||
sourceImage, _ := png.Decode(sourceFile)
|
sourceImage, _ := png.Decode(sourceFile)
|
||||||
|
|
||||||
// Crop image white border with 50% thresold
|
// Crop white border with 50% thresold
|
||||||
croppedImage := colorcrop.Crop(sourceImage, color.RGBA{255, 255, 255, 255}, 0.5)
|
croppedImage := colorcrop.Crop(
|
||||||
|
sourceImage, // for source image
|
||||||
|
color.RGBA{255, 255, 255, 255}, // crop white border
|
||||||
|
0.5) // with 50% thresold
|
||||||
|
|
||||||
|
// Save cropped image
|
||||||
|
croppedFile, _ := os.Create("cropped.png")
|
||||||
|
defer croppedFile.Close()
|
||||||
|
|
||||||
|
png.Encode(croppedFile, croppedImage)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleCustomComparator() {
|
||||||
|
log.SetFlags(0)
|
||||||
|
|
||||||
|
// Read source image
|
||||||
|
sourceFile, _ := os.Open("img.png")
|
||||||
|
defer sourceFile.Close()
|
||||||
|
|
||||||
|
sourceImage, _ := png.Decode(sourceFile)
|
||||||
|
|
||||||
|
// Crop white border with 50% thresold
|
||||||
|
croppedImage := colorcrop.CropWithComparator(
|
||||||
|
sourceImage, // for source image
|
||||||
|
color.RGBA{255, 255, 255, 255}, // crop white border
|
||||||
|
0.5, // with 50% thresold
|
||||||
|
colorcrop.CmpCIE76) // using CIE76 standart for defining color difference
|
||||||
|
|
||||||
// Save cropped image
|
// Save cropped image
|
||||||
croppedFile, _ := os.Create("cropped.png")
|
croppedFile, _ := os.Create("cropped.png")
|
||||||
|
|
BIN
testimages/01.png
Normal file
After Width: | Height: | Size: 137 B |
BIN
testimages/02.png
Normal file
After Width: | Height: | Size: 140 B |
BIN
testimages/03.png
Normal file
After Width: | Height: | Size: 140 B |
BIN
testimages/04.png
Normal file
After Width: | Height: | Size: 138 B |
BIN
testimages/05.png
Normal file
After Width: | Height: | Size: 138 B |
BIN
testimages/06.png
Normal file
After Width: | Height: | Size: 139 B |
BIN
testimages/07.png
Normal file
After Width: | Height: | Size: 138 B |
BIN
testimages/08.png
Normal file
After Width: | Height: | Size: 138 B |
BIN
testimages/09.png
Normal file
After Width: | Height: | Size: 137 B |
BIN
testimages/10.png
Normal file
After Width: | Height: | Size: 139 B |
BIN
testimages/11.png
Normal file
After Width: | Height: | Size: 137 B |
BIN
testimages/12.png
Normal file
After Width: | Height: | Size: 136 B |
BIN
testimages/13.png
Normal file
After Width: | Height: | Size: 135 B |
BIN
testimages/14.png
Normal file
After Width: | Height: | Size: 136 B |
BIN
testimages/15.png
Normal file
After Width: | Height: | Size: 134 B |
BIN
testimages/16.png
Normal file
After Width: | Height: | Size: 131 B |