1
0

helpers_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. package imaging
  2. import (
  3. "bytes"
  4. "image"
  5. "image/color"
  6. "testing"
  7. )
  8. func compareNRGBA(img1, img2 *image.NRGBA, delta int) bool {
  9. if !img1.Rect.Eq(img2.Rect) {
  10. return false
  11. }
  12. if len(img1.Pix) != len(img2.Pix) {
  13. return false
  14. }
  15. for i := 0; i < len(img1.Pix); i++ {
  16. if absint(int(img1.Pix[i])-int(img2.Pix[i])) > delta {
  17. return false
  18. }
  19. }
  20. return true
  21. }
  22. func TestEncodeDecode(t *testing.T) {
  23. imgWithAlpha := image.NewNRGBA(image.Rect(0, 0, 3, 3))
  24. imgWithAlpha.Pix = []uint8{
  25. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
  26. 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
  27. 244, 245, 246, 247, 248, 249, 250, 252, 252, 253, 254, 255,
  28. }
  29. imgWithoutAlpha := image.NewNRGBA(image.Rect(0, 0, 3, 3))
  30. imgWithoutAlpha.Pix = []uint8{
  31. 0, 1, 2, 255, 4, 5, 6, 255, 8, 9, 10, 255,
  32. 127, 128, 129, 255, 131, 132, 133, 255, 135, 136, 137, 255,
  33. 244, 245, 246, 255, 248, 249, 250, 255, 252, 253, 254, 255,
  34. }
  35. for _, format := range []Format{JPEG, PNG, GIF, BMP, TIFF} {
  36. img := imgWithoutAlpha
  37. if format == PNG {
  38. img = imgWithAlpha
  39. }
  40. buf := &bytes.Buffer{}
  41. err := Encode(buf, img, format)
  42. if err != nil {
  43. t.Errorf("fail encoding format %s", format)
  44. continue
  45. }
  46. img2, err := Decode(buf)
  47. if err != nil {
  48. t.Errorf("fail decoding format %s", format)
  49. continue
  50. }
  51. img2cloned := Clone(img2)
  52. delta := 0
  53. if format == JPEG {
  54. delta = 3
  55. } else if format == GIF {
  56. delta = 16
  57. }
  58. if !compareNRGBA(img, img2cloned, delta) {
  59. t.Errorf("test [DecodeEncode %s] failed: %#v %#v", format, img, img2cloned)
  60. continue
  61. }
  62. }
  63. buf := &bytes.Buffer{}
  64. err := Encode(buf, imgWithAlpha, JPEG)
  65. if err != nil {
  66. t.Errorf("failed encoding alpha to JPEG format %s", err)
  67. }
  68. buf = &bytes.Buffer{}
  69. err = Encode(buf, imgWithAlpha, Format(100))
  70. if err != ErrUnsupportedFormat {
  71. t.Errorf("expected ErrUnsupportedFormat")
  72. }
  73. buf = bytes.NewBuffer([]byte("bad data"))
  74. _, err = Decode(buf)
  75. if err == nil {
  76. t.Errorf("decoding bad data, expected error")
  77. }
  78. }
  79. func TestNew(t *testing.T) {
  80. td := []struct {
  81. desc string
  82. w, h int
  83. c color.Color
  84. dstBounds image.Rectangle
  85. dstPix []uint8
  86. }{
  87. {
  88. "New 1x1 black",
  89. 1, 1,
  90. color.NRGBA{0, 0, 0, 0},
  91. image.Rect(0, 0, 1, 1),
  92. []uint8{0x00, 0x00, 0x00, 0x00},
  93. },
  94. {
  95. "New 1x2 red",
  96. 1, 2,
  97. color.NRGBA{255, 0, 0, 255},
  98. image.Rect(0, 0, 1, 2),
  99. []uint8{0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff},
  100. },
  101. {
  102. "New 2x1 white",
  103. 2, 1,
  104. color.NRGBA{255, 255, 255, 255},
  105. image.Rect(0, 0, 2, 1),
  106. []uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
  107. },
  108. {
  109. "New 0x0 white",
  110. 0, 0,
  111. color.NRGBA{255, 255, 255, 255},
  112. image.Rect(0, 0, 0, 0),
  113. nil,
  114. },
  115. }
  116. for _, d := range td {
  117. got := New(d.w, d.h, d.c)
  118. want := image.NewNRGBA(d.dstBounds)
  119. want.Pix = d.dstPix
  120. if !compareNRGBA(got, want, 0) {
  121. t.Errorf("test [%s] failed: %#v", d.desc, got)
  122. }
  123. }
  124. }
  125. func TestClone(t *testing.T) {
  126. td := []struct {
  127. desc string
  128. src image.Image
  129. want *image.NRGBA
  130. }{
  131. {
  132. "Clone NRGBA",
  133. &image.NRGBA{
  134. Rect: image.Rect(-1, -1, 0, 1),
  135. Stride: 1 * 4,
  136. Pix: []uint8{0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff},
  137. },
  138. &image.NRGBA{
  139. Rect: image.Rect(0, 0, 1, 2),
  140. Stride: 1 * 4,
  141. Pix: []uint8{0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff},
  142. },
  143. },
  144. {
  145. "Clone NRGBA64",
  146. &image.NRGBA64{
  147. Rect: image.Rect(-1, -1, 0, 1),
  148. Stride: 1 * 8,
  149. Pix: []uint8{
  150. 0x00, 0x00, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33,
  151. 0xcc, 0xcc, 0xdd, 0xdd, 0xee, 0xee, 0xff, 0xff,
  152. },
  153. },
  154. &image.NRGBA{
  155. Rect: image.Rect(0, 0, 1, 2),
  156. Stride: 1 * 4,
  157. Pix: []uint8{0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff},
  158. },
  159. },
  160. {
  161. "Clone RGBA",
  162. &image.RGBA{
  163. Rect: image.Rect(-1, -1, 0, 2),
  164. Stride: 1 * 4,
  165. Pix: []uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff},
  166. },
  167. &image.NRGBA{
  168. Rect: image.Rect(0, 0, 1, 3),
  169. Stride: 1 * 4,
  170. Pix: []uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa, 0x33, 0xcc, 0xdd, 0xee, 0xff},
  171. },
  172. },
  173. {
  174. "Clone RGBA64",
  175. &image.RGBA64{
  176. Rect: image.Rect(-1, -1, 0, 2),
  177. Stride: 1 * 8,
  178. Pix: []uint8{
  179. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  180. 0x00, 0x00, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33,
  181. 0xcc, 0xcc, 0xdd, 0xdd, 0xee, 0xee, 0xff, 0xff,
  182. },
  183. },
  184. &image.NRGBA{
  185. Rect: image.Rect(0, 0, 1, 3),
  186. Stride: 1 * 4,
  187. Pix: []uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa, 0x33, 0xcc, 0xdd, 0xee, 0xff},
  188. },
  189. },
  190. {
  191. "Clone Gray",
  192. &image.Gray{
  193. Rect: image.Rect(-1, -1, 0, 1),
  194. Stride: 1 * 1,
  195. Pix: []uint8{0x11, 0xee},
  196. },
  197. &image.NRGBA{
  198. Rect: image.Rect(0, 0, 1, 2),
  199. Stride: 1 * 4,
  200. Pix: []uint8{0x11, 0x11, 0x11, 0xff, 0xee, 0xee, 0xee, 0xff},
  201. },
  202. },
  203. {
  204. "Clone Gray16",
  205. &image.Gray16{
  206. Rect: image.Rect(-1, -1, 0, 1),
  207. Stride: 1 * 2,
  208. Pix: []uint8{0x11, 0x11, 0xee, 0xee},
  209. },
  210. &image.NRGBA{
  211. Rect: image.Rect(0, 0, 1, 2),
  212. Stride: 1 * 4,
  213. Pix: []uint8{0x11, 0x11, 0x11, 0xff, 0xee, 0xee, 0xee, 0xff},
  214. },
  215. },
  216. {
  217. "Clone Alpha",
  218. &image.Alpha{
  219. Rect: image.Rect(-1, -1, 0, 1),
  220. Stride: 1 * 1,
  221. Pix: []uint8{0x11, 0xee},
  222. },
  223. &image.NRGBA{
  224. Rect: image.Rect(0, 0, 1, 2),
  225. Stride: 1 * 4,
  226. Pix: []uint8{0xff, 0xff, 0xff, 0x11, 0xff, 0xff, 0xff, 0xee},
  227. },
  228. },
  229. {
  230. "Clone YCbCr",
  231. &image.YCbCr{
  232. Rect: image.Rect(-1, -1, 5, 0),
  233. SubsampleRatio: image.YCbCrSubsampleRatio444,
  234. YStride: 6,
  235. CStride: 6,
  236. Y: []uint8{0x00, 0xff, 0x7f, 0x26, 0x4b, 0x0e},
  237. Cb: []uint8{0x80, 0x80, 0x80, 0x6b, 0x56, 0xc0},
  238. Cr: []uint8{0x80, 0x80, 0x80, 0xc0, 0x4b, 0x76},
  239. },
  240. &image.NRGBA{
  241. Rect: image.Rect(0, 0, 6, 1),
  242. Stride: 6 * 4,
  243. Pix: []uint8{
  244. 0x00, 0x00, 0x00, 0xff,
  245. 0xff, 0xff, 0xff, 0xff,
  246. 0x7f, 0x7f, 0x7f, 0xff,
  247. 0x7f, 0x00, 0x00, 0xff,
  248. 0x00, 0x7f, 0x00, 0xff,
  249. 0x00, 0x00, 0x7f, 0xff,
  250. },
  251. },
  252. },
  253. {
  254. "Clone YCbCr 444",
  255. &image.YCbCr{
  256. Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff},
  257. Cb: []uint8{0x55, 0xd4, 0xff, 0x8e, 0x2c, 0x01, 0x6b, 0xaa, 0xc0, 0x95, 0x56, 0x40, 0x80, 0x80, 0x80, 0x80},
  258. Cr: []uint8{0xff, 0xeb, 0x6b, 0x36, 0x15, 0x95, 0xc0, 0xb5, 0x76, 0x41, 0x4b, 0x8c, 0x80, 0x80, 0x80, 0x80},
  259. YStride: 4,
  260. CStride: 4,
  261. SubsampleRatio: image.YCbCrSubsampleRatio444,
  262. Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
  263. },
  264. &image.NRGBA{
  265. Pix: []uint8{0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x49, 0xe1, 0xca, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0xff, 0x0, 0xff, 0x7f, 0x0, 0x0, 0xff, 0x7f, 0x0, 0x7f, 0xff, 0x0, 0x0, 0x7f, 0xff, 0x0, 0x7f, 0x7f, 0xff, 0x0, 0x7f, 0x0, 0xff, 0x82, 0x7f, 0x0, 0xff, 0x0, 0x0, 0x0, 0xff, 0x4c, 0x4c, 0x4c, 0xff, 0x99, 0x99, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff},
  266. Stride: 16,
  267. Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
  268. },
  269. },
  270. {
  271. "Clone YCbCr 440",
  272. &image.YCbCr{
  273. Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff},
  274. Cb: []uint8{0x2c, 0x01, 0x6b, 0xaa, 0x80, 0x80, 0x80, 0x80},
  275. Cr: []uint8{0x15, 0x95, 0xc0, 0xb5, 0x80, 0x80, 0x80, 0x80},
  276. YStride: 4,
  277. CStride: 4,
  278. SubsampleRatio: image.YCbCrSubsampleRatio440,
  279. Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
  280. },
  281. &image.NRGBA{
  282. Pix: []uint8{0x0, 0xb5, 0x0, 0xff, 0x86, 0x86, 0x0, 0xff, 0x77, 0x0, 0x0, 0xff, 0xfb, 0x7d, 0xfb, 0xff, 0x0, 0xff, 0x1, 0xff, 0xff, 0xff, 0x1, 0xff, 0x80, 0x0, 0x1, 0xff, 0x7e, 0x0, 0x7e, 0xff, 0xe, 0xe, 0xe, 0xff, 0x59, 0x59, 0x59, 0xff, 0x4b, 0x4b, 0x4b, 0xff, 0x71, 0x71, 0x71, 0xff, 0x0, 0x0, 0x0, 0xff, 0x4c, 0x4c, 0x4c, 0xff, 0x99, 0x99, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff},
  283. Stride: 16,
  284. Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
  285. },
  286. },
  287. {
  288. "Clone YCbCr 422",
  289. &image.YCbCr{
  290. Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff},
  291. Cb: []uint8{0xd4, 0x8e, 0x01, 0xaa, 0x95, 0x40, 0x80, 0x80},
  292. Cr: []uint8{0xeb, 0x36, 0x95, 0xb5, 0x41, 0x8c, 0x80, 0x80},
  293. YStride: 4,
  294. CStride: 2,
  295. SubsampleRatio: image.YCbCrSubsampleRatio422,
  296. Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
  297. },
  298. &image.NRGBA{
  299. Pix: []uint8{0xe2, 0x0, 0xe1, 0xff, 0xff, 0x0, 0xfe, 0xff, 0x0, 0x4d, 0x36, 0xff, 0x49, 0xe1, 0xca, 0xff, 0xb3, 0xb3, 0x0, 0xff, 0xff, 0xff, 0x1, 0xff, 0x70, 0x0, 0x70, 0xff, 0x7e, 0x0, 0x7e, 0xff, 0x0, 0x34, 0x33, 0xff, 0x1, 0x7f, 0x7e, 0xff, 0x5c, 0x58, 0x0, 0xff, 0x82, 0x7e, 0x0, 0xff, 0x0, 0x0, 0x0, 0xff, 0x4c, 0x4c, 0x4c, 0xff, 0x99, 0x99, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff},
  300. Stride: 16,
  301. Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
  302. },
  303. },
  304. {
  305. "Clone YCbCr 420",
  306. &image.YCbCr{
  307. Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff},
  308. Cb: []uint8{0x01, 0xaa, 0x80, 0x80},
  309. Cr: []uint8{0x95, 0xb5, 0x80, 0x80},
  310. YStride: 4, CStride: 2,
  311. SubsampleRatio: image.YCbCrSubsampleRatio420,
  312. Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
  313. },
  314. &image.NRGBA{
  315. Pix: []uint8{0x69, 0x69, 0x0, 0xff, 0x86, 0x86, 0x0, 0xff, 0x67, 0x0, 0x67, 0xff, 0xfb, 0x7d, 0xfb, 0xff, 0xb3, 0xb3, 0x0, 0xff, 0xff, 0xff, 0x1, 0xff, 0x70, 0x0, 0x70, 0xff, 0x7e, 0x0, 0x7e, 0xff, 0xe, 0xe, 0xe, 0xff, 0x59, 0x59, 0x59, 0xff, 0x4b, 0x4b, 0x4b, 0xff, 0x71, 0x71, 0x71, 0xff, 0x0, 0x0, 0x0, 0xff, 0x4c, 0x4c, 0x4c, 0xff, 0x99, 0x99, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff},
  316. Stride: 16,
  317. Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
  318. },
  319. },
  320. {
  321. "Clone Paletted",
  322. &image.Paletted{
  323. Rect: image.Rect(-1, -1, 5, 0),
  324. Stride: 6 * 1,
  325. Palette: color.Palette{
  326. color.NRGBA{R: 0x00, G: 0x00, B: 0x00, A: 0xff},
  327. color.NRGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff},
  328. color.NRGBA{R: 0x7f, G: 0x7f, B: 0x7f, A: 0xff},
  329. color.NRGBA{R: 0x7f, G: 0x00, B: 0x00, A: 0xff},
  330. color.NRGBA{R: 0x00, G: 0x7f, B: 0x00, A: 0xff},
  331. color.NRGBA{R: 0x00, G: 0x00, B: 0x7f, A: 0xff},
  332. },
  333. Pix: []uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5},
  334. },
  335. &image.NRGBA{
  336. Rect: image.Rect(0, 0, 6, 1),
  337. Stride: 6 * 4,
  338. Pix: []uint8{
  339. 0x00, 0x00, 0x00, 0xff,
  340. 0xff, 0xff, 0xff, 0xff,
  341. 0x7f, 0x7f, 0x7f, 0xff,
  342. 0x7f, 0x00, 0x00, 0xff,
  343. 0x00, 0x7f, 0x00, 0xff,
  344. 0x00, 0x00, 0x7f, 0xff,
  345. },
  346. },
  347. },
  348. }
  349. for _, d := range td {
  350. got := Clone(d.src)
  351. want := d.want
  352. delta := 0
  353. if _, ok := d.src.(*image.YCbCr); ok {
  354. delta = 1
  355. }
  356. if !compareNRGBA(got, want, delta) {
  357. t.Errorf("test [%s] failed: %#v", d.desc, got)
  358. }
  359. }
  360. }
  361. func TestFormats(t *testing.T) {
  362. formatNames := map[Format]string{
  363. JPEG: "JPEG",
  364. PNG: "PNG",
  365. GIF: "GIF",
  366. BMP: "BMP",
  367. TIFF: "TIFF",
  368. Format(-1): "Unsupported",
  369. }
  370. for format, name := range formatNames {
  371. got := format.String()
  372. if got != name {
  373. t.Errorf("test [Format names] failed: got %#v want %#v", got, name)
  374. continue
  375. }
  376. }
  377. }