helpers_test.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. package imaging
  2. import (
  3. "bytes"
  4. "errors"
  5. "image"
  6. "image/color"
  7. "image/color/palette"
  8. "image/draw"
  9. "io"
  10. "io/ioutil"
  11. "os"
  12. "path/filepath"
  13. "testing"
  14. )
  15. var (
  16. errCreate = errors.New("failed to create file")
  17. errClose = errors.New("failed to close file")
  18. errOpen = errors.New("failed to open file")
  19. )
  20. type badFS struct{}
  21. func (badFS) Create(name string) (io.WriteCloser, error) {
  22. if name == "badFile.jpg" {
  23. return badFile{ioutil.Discard}, nil
  24. }
  25. return nil, errCreate
  26. }
  27. func (badFS) Open(name string) (io.ReadCloser, error) {
  28. return nil, errOpen
  29. }
  30. type badFile struct {
  31. io.Writer
  32. }
  33. func (badFile) Close() error {
  34. return errClose
  35. }
  36. type quantizer struct {
  37. palette []color.Color
  38. }
  39. func (q quantizer) Quantize(p color.Palette, m image.Image) color.Palette {
  40. pal := make([]color.Color, len(p), cap(p))
  41. copy(pal, p)
  42. n := cap(p) - len(p)
  43. if n > len(q.palette) {
  44. n = len(q.palette)
  45. }
  46. for i := 0; i < n; i++ {
  47. pal = append(pal, q.palette[i])
  48. }
  49. return pal
  50. }
  51. func TestOpenSave(t *testing.T) {
  52. imgWithoutAlpha := image.NewNRGBA(image.Rect(0, 0, 4, 6))
  53. imgWithoutAlpha.Pix = []uint8{
  54. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  55. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  56. 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
  57. 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
  58. 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x88, 0x88, 0x88, 0xff, 0x88, 0x88, 0x88, 0xff,
  59. 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x88, 0x88, 0x88, 0xff, 0x88, 0x88, 0x88, 0xff,
  60. }
  61. imgWithAlpha := image.NewNRGBA(image.Rect(0, 0, 4, 6))
  62. imgWithAlpha.Pix = []uint8{
  63. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  64. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  65. 0xff, 0x00, 0x00, 0x80, 0xff, 0x00, 0x00, 0x80, 0x00, 0xff, 0x00, 0x80, 0x00, 0xff, 0x00, 0x80,
  66. 0xff, 0x00, 0x00, 0x80, 0xff, 0x00, 0x00, 0x80, 0x00, 0xff, 0x00, 0x80, 0x00, 0xff, 0x00, 0x80,
  67. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x88, 0x88, 0x88, 0x00, 0x88, 0x88, 0x88, 0x00,
  68. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x88, 0x88, 0x88, 0x00, 0x88, 0x88, 0x88, 0x00,
  69. }
  70. options := [][]EncodeOption{
  71. {
  72. JPEGQuality(100),
  73. },
  74. {
  75. JPEGQuality(99),
  76. GIFDrawer(draw.FloydSteinberg),
  77. GIFNumColors(256),
  78. GIFQuantizer(quantizer{palette.Plan9}),
  79. },
  80. }
  81. dir, err := ioutil.TempDir("", "imaging")
  82. if err != nil {
  83. t.Fatalf("failed to create temporary directory: %v", err)
  84. }
  85. defer os.RemoveAll(dir)
  86. for _, ext := range []string{"jpg", "jpeg", "png", "gif", "bmp", "tif", "tiff"} {
  87. filename := filepath.Join(dir, "test."+ext)
  88. img := imgWithoutAlpha
  89. if ext == "png" {
  90. img = imgWithAlpha
  91. }
  92. for _, opts := range options {
  93. err := Save(img, filename, opts...)
  94. if err != nil {
  95. t.Fatalf("failed to save image (%q): %v", filename, err)
  96. }
  97. img2, err := Open(filename)
  98. if err != nil {
  99. t.Fatalf("failed to open image (%q): %v", filename, err)
  100. }
  101. got := Clone(img2)
  102. delta := 0
  103. if ext == "jpg" || ext == "jpeg" || ext == "gif" {
  104. delta = 3
  105. }
  106. if !compareNRGBA(got, img, delta) {
  107. t.Fatalf("bad encode-decode result (ext=%q): got %#v want %#v", ext, got, img)
  108. }
  109. }
  110. }
  111. buf := &bytes.Buffer{}
  112. err = Encode(buf, imgWithAlpha, JPEG)
  113. if err != nil {
  114. t.Fatalf("failed to encode alpha to JPEG: %v", err)
  115. }
  116. buf = &bytes.Buffer{}
  117. err = Encode(buf, imgWithAlpha, Format(100))
  118. if err != ErrUnsupportedFormat {
  119. t.Fatalf("got %v want ErrUnsupportedFormat", err)
  120. }
  121. buf = bytes.NewBuffer([]byte("bad data"))
  122. _, err = Decode(buf)
  123. if err == nil {
  124. t.Fatalf("decoding bad data: expected error got nil")
  125. }
  126. err = Save(imgWithAlpha, filepath.Join(dir, "test.unknown"))
  127. if err != ErrUnsupportedFormat {
  128. t.Fatalf("got %v want ErrUnsupportedFormat", err)
  129. }
  130. prevFS := fs
  131. fs = badFS{}
  132. defer func() { fs = prevFS }()
  133. err = Save(imgWithAlpha, "test.jpg")
  134. if err != errCreate {
  135. t.Fatalf("got error %v want errCreate", err)
  136. }
  137. err = Save(imgWithAlpha, "badFile.jpg")
  138. if err != errClose {
  139. t.Fatalf("got error %v want errClose", err)
  140. }
  141. _, err = Open("test.jpg")
  142. if err != errOpen {
  143. t.Fatalf("got error %v want errOpen", err)
  144. }
  145. }
  146. func TestNew(t *testing.T) {
  147. testCases := []struct {
  148. name string
  149. w, h int
  150. c color.Color
  151. dstBounds image.Rectangle
  152. dstPix []uint8
  153. }{
  154. {
  155. "New 1x1 black",
  156. 1, 1,
  157. color.NRGBA{0, 0, 0, 0},
  158. image.Rect(0, 0, 1, 1),
  159. []uint8{0x00, 0x00, 0x00, 0x00},
  160. },
  161. {
  162. "New 1x2 red",
  163. 1, 2,
  164. color.NRGBA{255, 0, 0, 255},
  165. image.Rect(0, 0, 1, 2),
  166. []uint8{0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff},
  167. },
  168. {
  169. "New 2x1 white",
  170. 2, 1,
  171. color.NRGBA{255, 255, 255, 255},
  172. image.Rect(0, 0, 2, 1),
  173. []uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
  174. },
  175. {
  176. "New 3x3 with alpha",
  177. 3, 3,
  178. color.NRGBA{0x01, 0x23, 0x45, 0x67},
  179. image.Rect(0, 0, 3, 3),
  180. []uint8{
  181. 0x01, 0x23, 0x45, 0x67, 0x01, 0x23, 0x45, 0x67, 0x01, 0x23, 0x45, 0x67,
  182. 0x01, 0x23, 0x45, 0x67, 0x01, 0x23, 0x45, 0x67, 0x01, 0x23, 0x45, 0x67,
  183. 0x01, 0x23, 0x45, 0x67, 0x01, 0x23, 0x45, 0x67, 0x01, 0x23, 0x45, 0x67,
  184. },
  185. },
  186. {
  187. "New 0x0 white",
  188. 0, 0,
  189. color.NRGBA{255, 255, 255, 255},
  190. image.Rect(0, 0, 0, 0),
  191. nil,
  192. },
  193. }
  194. for _, tc := range testCases {
  195. t.Run(tc.name, func(t *testing.T) {
  196. got := New(tc.w, tc.h, tc.c)
  197. want := image.NewNRGBA(tc.dstBounds)
  198. want.Pix = tc.dstPix
  199. if !compareNRGBA(got, want, 0) {
  200. t.Fatalf("got result %#v want %#v", got, want)
  201. }
  202. })
  203. }
  204. }
  205. func BenchmarkNew(b *testing.B) {
  206. b.ReportAllocs()
  207. for i := 0; i < b.N; i++ {
  208. New(1024, 1024, color.White)
  209. }
  210. }
  211. func TestFormats(t *testing.T) {
  212. formatNames := map[Format]string{
  213. JPEG: "JPEG",
  214. PNG: "PNG",
  215. GIF: "GIF",
  216. BMP: "BMP",
  217. TIFF: "TIFF",
  218. Format(-1): "Unsupported",
  219. }
  220. for format, name := range formatNames {
  221. got := format.String()
  222. if got != name {
  223. t.Fatalf("got format name %q want %q", got, name)
  224. }
  225. }
  226. }
  227. func TestClone(t *testing.T) {
  228. testCases := []struct {
  229. name string
  230. src image.Image
  231. want *image.NRGBA
  232. }{
  233. {
  234. "Clone NRGBA",
  235. &image.NRGBA{
  236. Rect: image.Rect(-1, -1, 0, 1),
  237. Stride: 1 * 4,
  238. Pix: []uint8{0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff},
  239. },
  240. &image.NRGBA{
  241. Rect: image.Rect(0, 0, 1, 2),
  242. Stride: 1 * 4,
  243. Pix: []uint8{0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff},
  244. },
  245. },
  246. {
  247. "Clone NRGBA64",
  248. &image.NRGBA64{
  249. Rect: image.Rect(-1, -1, 0, 1),
  250. Stride: 1 * 8,
  251. Pix: []uint8{
  252. 0x00, 0x00, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33,
  253. 0xcc, 0xcc, 0xdd, 0xdd, 0xee, 0xee, 0xff, 0xff,
  254. },
  255. },
  256. &image.NRGBA{
  257. Rect: image.Rect(0, 0, 1, 2),
  258. Stride: 1 * 4,
  259. Pix: []uint8{0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff},
  260. },
  261. },
  262. {
  263. "Clone RGBA",
  264. &image.RGBA{
  265. Rect: image.Rect(-1, -1, 0, 2),
  266. Stride: 1 * 4,
  267. Pix: []uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff},
  268. },
  269. &image.NRGBA{
  270. Rect: image.Rect(0, 0, 1, 3),
  271. Stride: 1 * 4,
  272. Pix: []uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa, 0x33, 0xcc, 0xdd, 0xee, 0xff},
  273. },
  274. },
  275. {
  276. "Clone RGBA64",
  277. &image.RGBA64{
  278. Rect: image.Rect(-1, -1, 0, 2),
  279. Stride: 1 * 8,
  280. Pix: []uint8{
  281. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  282. 0x00, 0x00, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33,
  283. 0xcc, 0xcc, 0xdd, 0xdd, 0xee, 0xee, 0xff, 0xff,
  284. },
  285. },
  286. &image.NRGBA{
  287. Rect: image.Rect(0, 0, 1, 3),
  288. Stride: 1 * 4,
  289. Pix: []uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa, 0x33, 0xcc, 0xdd, 0xee, 0xff},
  290. },
  291. },
  292. {
  293. "Clone Gray",
  294. &image.Gray{
  295. Rect: image.Rect(-1, -1, 0, 1),
  296. Stride: 1 * 1,
  297. Pix: []uint8{0x11, 0xee},
  298. },
  299. &image.NRGBA{
  300. Rect: image.Rect(0, 0, 1, 2),
  301. Stride: 1 * 4,
  302. Pix: []uint8{0x11, 0x11, 0x11, 0xff, 0xee, 0xee, 0xee, 0xff},
  303. },
  304. },
  305. {
  306. "Clone Gray16",
  307. &image.Gray16{
  308. Rect: image.Rect(-1, -1, 0, 1),
  309. Stride: 1 * 2,
  310. Pix: []uint8{0x11, 0x11, 0xee, 0xee},
  311. },
  312. &image.NRGBA{
  313. Rect: image.Rect(0, 0, 1, 2),
  314. Stride: 1 * 4,
  315. Pix: []uint8{0x11, 0x11, 0x11, 0xff, 0xee, 0xee, 0xee, 0xff},
  316. },
  317. },
  318. {
  319. "Clone Alpha",
  320. &image.Alpha{
  321. Rect: image.Rect(-1, -1, 0, 1),
  322. Stride: 1 * 1,
  323. Pix: []uint8{0x11, 0xee},
  324. },
  325. &image.NRGBA{
  326. Rect: image.Rect(0, 0, 1, 2),
  327. Stride: 1 * 4,
  328. Pix: []uint8{0xff, 0xff, 0xff, 0x11, 0xff, 0xff, 0xff, 0xee},
  329. },
  330. },
  331. {
  332. "Clone YCbCr",
  333. &image.YCbCr{
  334. Rect: image.Rect(-1, -1, 5, 0),
  335. SubsampleRatio: image.YCbCrSubsampleRatio444,
  336. YStride: 6,
  337. CStride: 6,
  338. Y: []uint8{0x00, 0xff, 0x7f, 0x26, 0x4b, 0x0e},
  339. Cb: []uint8{0x80, 0x80, 0x80, 0x6b, 0x56, 0xc0},
  340. Cr: []uint8{0x80, 0x80, 0x80, 0xc0, 0x4b, 0x76},
  341. },
  342. &image.NRGBA{
  343. Rect: image.Rect(0, 0, 6, 1),
  344. Stride: 6 * 4,
  345. Pix: []uint8{
  346. 0x00, 0x00, 0x00, 0xff,
  347. 0xff, 0xff, 0xff, 0xff,
  348. 0x7f, 0x7f, 0x7f, 0xff,
  349. 0x7f, 0x00, 0x00, 0xff,
  350. 0x00, 0x7f, 0x00, 0xff,
  351. 0x00, 0x00, 0x7f, 0xff,
  352. },
  353. },
  354. },
  355. {
  356. "Clone YCbCr 444",
  357. &image.YCbCr{
  358. Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff},
  359. Cb: []uint8{0x55, 0xd4, 0xff, 0x8e, 0x2c, 0x01, 0x6b, 0xaa, 0xc0, 0x95, 0x56, 0x40, 0x80, 0x80, 0x80, 0x80},
  360. Cr: []uint8{0xff, 0xeb, 0x6b, 0x36, 0x15, 0x95, 0xc0, 0xb5, 0x76, 0x41, 0x4b, 0x8c, 0x80, 0x80, 0x80, 0x80},
  361. YStride: 4,
  362. CStride: 4,
  363. SubsampleRatio: image.YCbCrSubsampleRatio444,
  364. Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
  365. },
  366. &image.NRGBA{
  367. 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},
  368. Stride: 16,
  369. Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
  370. },
  371. },
  372. {
  373. "Clone YCbCr 440",
  374. &image.YCbCr{
  375. Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff},
  376. Cb: []uint8{0x2c, 0x01, 0x6b, 0xaa, 0x80, 0x80, 0x80, 0x80},
  377. Cr: []uint8{0x15, 0x95, 0xc0, 0xb5, 0x80, 0x80, 0x80, 0x80},
  378. YStride: 4,
  379. CStride: 4,
  380. SubsampleRatio: image.YCbCrSubsampleRatio440,
  381. Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
  382. },
  383. &image.NRGBA{
  384. 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},
  385. Stride: 16,
  386. Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
  387. },
  388. },
  389. {
  390. "Clone YCbCr 422",
  391. &image.YCbCr{
  392. Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff},
  393. Cb: []uint8{0xd4, 0x8e, 0x01, 0xaa, 0x95, 0x40, 0x80, 0x80},
  394. Cr: []uint8{0xeb, 0x36, 0x95, 0xb5, 0x41, 0x8c, 0x80, 0x80},
  395. YStride: 4,
  396. CStride: 2,
  397. SubsampleRatio: image.YCbCrSubsampleRatio422,
  398. Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
  399. },
  400. &image.NRGBA{
  401. 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},
  402. Stride: 16,
  403. Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
  404. },
  405. },
  406. {
  407. "Clone YCbCr 420",
  408. &image.YCbCr{
  409. Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff},
  410. Cb: []uint8{0x01, 0xaa, 0x80, 0x80},
  411. Cr: []uint8{0x95, 0xb5, 0x80, 0x80},
  412. YStride: 4, CStride: 2,
  413. SubsampleRatio: image.YCbCrSubsampleRatio420,
  414. Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
  415. },
  416. &image.NRGBA{
  417. 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},
  418. Stride: 16,
  419. Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
  420. },
  421. },
  422. {
  423. "Clone Paletted",
  424. &image.Paletted{
  425. Rect: image.Rect(-1, -1, 5, 0),
  426. Stride: 6 * 1,
  427. Palette: color.Palette{
  428. color.NRGBA{R: 0x00, G: 0x00, B: 0x00, A: 0xff},
  429. color.NRGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff},
  430. color.NRGBA{R: 0x7f, G: 0x7f, B: 0x7f, A: 0xff},
  431. color.NRGBA{R: 0x7f, G: 0x00, B: 0x00, A: 0xff},
  432. color.NRGBA{R: 0x00, G: 0x7f, B: 0x00, A: 0xff},
  433. color.NRGBA{R: 0x00, G: 0x00, B: 0x7f, A: 0xff},
  434. },
  435. Pix: []uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5},
  436. },
  437. &image.NRGBA{
  438. Rect: image.Rect(0, 0, 6, 1),
  439. Stride: 6 * 4,
  440. Pix: []uint8{
  441. 0x00, 0x00, 0x00, 0xff,
  442. 0xff, 0xff, 0xff, 0xff,
  443. 0x7f, 0x7f, 0x7f, 0xff,
  444. 0x7f, 0x00, 0x00, 0xff,
  445. 0x00, 0x7f, 0x00, 0xff,
  446. 0x00, 0x00, 0x7f, 0xff,
  447. },
  448. },
  449. },
  450. }
  451. for _, tc := range testCases {
  452. t.Run(tc.name, func(t *testing.T) {
  453. got := Clone(tc.src)
  454. delta := 0
  455. if _, ok := tc.src.(*image.YCbCr); ok {
  456. delta = 1
  457. }
  458. if !compareNRGBA(got, tc.want, delta) {
  459. t.Fatalf("got result %#v want %#v", got, tc.want)
  460. }
  461. })
  462. }
  463. }