helpers_test.go 14 KB

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