processing_test.go 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044
  1. package processing
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "path/filepath"
  7. "testing"
  8. "unsafe"
  9. "github.com/stretchr/testify/suite"
  10. "github.com/imgproxy/imgproxy/v3/fetcher"
  11. "github.com/imgproxy/imgproxy/v3/ierrors"
  12. "github.com/imgproxy/imgproxy/v3/imagedata"
  13. "github.com/imgproxy/imgproxy/v3/logger"
  14. "github.com/imgproxy/imgproxy/v3/options"
  15. "github.com/imgproxy/imgproxy/v3/security"
  16. "github.com/imgproxy/imgproxy/v3/testutil"
  17. "github.com/imgproxy/imgproxy/v3/vips"
  18. )
  19. type ProcessingTestSuite struct {
  20. testutil.LazySuite
  21. imageDataFactory testutil.LazyObj[*imagedata.Factory]
  22. securityConfig testutil.LazyObj[*security.Config]
  23. security testutil.LazyObj[*security.Checker]
  24. poConfig testutil.LazyObj[*options.Config]
  25. po testutil.LazyObj[*options.Factory]
  26. }
  27. func (s *ProcessingTestSuite) SetupSuite() {
  28. s.Require().NoError(vips.Init())
  29. logger.Mute()
  30. s.imageDataFactory, _ = testutil.NewLazySuiteObj(s, func() (*imagedata.Factory, error) {
  31. c := fetcher.NewDefaultConfig()
  32. f, err := fetcher.New(&c)
  33. if err != nil {
  34. return nil, err
  35. }
  36. return imagedata.NewFactory(f), nil
  37. })
  38. s.securityConfig, _ = testutil.NewLazySuiteObj(s, func() (*security.Config, error) {
  39. c := security.NewDefaultConfig()
  40. c.DefaultOptions.MaxSrcResolution = 10 * 1024 * 1024
  41. c.DefaultOptions.MaxSrcFileSize = 10 * 1024 * 1024
  42. c.DefaultOptions.MaxAnimationFrames = 100
  43. c.DefaultOptions.MaxAnimationFrameResolution = 10 * 1024 * 1024
  44. return &c, nil
  45. })
  46. s.security, _ = testutil.NewLazySuiteObj(s, func() (*security.Checker, error) {
  47. return security.New(s.securityConfig())
  48. })
  49. s.poConfig, _ = testutil.NewLazySuiteObj(s, func() (*options.Config, error) {
  50. c := options.NewDefaultConfig()
  51. return &c, nil
  52. })
  53. s.po, _ = testutil.NewLazySuiteObj(s, func() (*options.Factory, error) {
  54. return options.NewFactory(s.poConfig(), s.security())
  55. })
  56. }
  57. func (s *ProcessingTestSuite) TearDownSuite() {
  58. logger.Unmute()
  59. }
  60. func (s *ProcessingTestSuite) openFile(name string) imagedata.ImageData {
  61. wd, err := os.Getwd()
  62. s.Require().NoError(err)
  63. path := filepath.Join(wd, "..", "testdata", name)
  64. imagedata, err := s.imageDataFactory().NewFromPath(path)
  65. s.Require().NoError(err)
  66. return imagedata
  67. }
  68. func (s *ProcessingTestSuite) checkSize(r *Result, width, height int) {
  69. s.Require().NotNil(r)
  70. s.Require().Equal(width, r.ResultWidth, "Width mismatch")
  71. s.Require().Equal(height, r.ResultHeight, "Height mismatch")
  72. }
  73. func (s *ProcessingTestSuite) TestResizeToFit() {
  74. imgdata := s.openFile("test2.jpg")
  75. po := s.po().NewProcessingOptions()
  76. po.ResizingType = options.ResizeFit
  77. testCases := []struct {
  78. width int
  79. height int
  80. outWidth int
  81. outHeight int
  82. }{
  83. {width: 50, height: 50, outWidth: 50, outHeight: 25},
  84. {width: 50, height: 20, outWidth: 40, outHeight: 20},
  85. {width: 20, height: 50, outWidth: 20, outHeight: 10},
  86. {width: 300, height: 300, outWidth: 200, outHeight: 100},
  87. {width: 300, height: 50, outWidth: 100, outHeight: 50},
  88. {width: 100, height: 300, outWidth: 100, outHeight: 50},
  89. {width: 0, height: 50, outWidth: 100, outHeight: 50},
  90. {width: 50, height: 0, outWidth: 50, outHeight: 25},
  91. {width: 0, height: 200, outWidth: 200, outHeight: 100},
  92. {width: 300, height: 0, outWidth: 200, outHeight: 100},
  93. }
  94. for _, tc := range testCases {
  95. s.Run(fmt.Sprintf("%dx%d", tc.width, tc.height), func() {
  96. po.Width = tc.width
  97. po.Height = tc.height
  98. result, err := ProcessImage(context.Background(), imgdata, po, nil)
  99. s.Require().NoError(err)
  100. s.Require().NotNil(result)
  101. s.checkSize(result, tc.outWidth, tc.outHeight)
  102. })
  103. }
  104. }
  105. func (s *ProcessingTestSuite) TestResizeToFitEnlarge() {
  106. imgdata := s.openFile("test2.jpg")
  107. po := s.po().NewProcessingOptions()
  108. po.ResizingType = options.ResizeFit
  109. po.Enlarge = true
  110. testCases := []struct {
  111. width int
  112. height int
  113. outWidth int
  114. outHeight int
  115. }{
  116. {width: 50, height: 50, outWidth: 50, outHeight: 25},
  117. {width: 50, height: 20, outWidth: 40, outHeight: 20},
  118. {width: 20, height: 50, outWidth: 20, outHeight: 10},
  119. {width: 300, height: 300, outWidth: 300, outHeight: 150},
  120. {width: 300, height: 125, outWidth: 250, outHeight: 125},
  121. {width: 250, height: 300, outWidth: 250, outHeight: 125},
  122. {width: 0, height: 50, outWidth: 100, outHeight: 50},
  123. {width: 50, height: 0, outWidth: 50, outHeight: 25},
  124. {width: 0, height: 200, outWidth: 400, outHeight: 200},
  125. {width: 300, height: 0, outWidth: 300, outHeight: 150},
  126. }
  127. for _, tc := range testCases {
  128. s.Run(fmt.Sprintf("%dx%d", tc.width, tc.height), func() {
  129. po.Width = tc.width
  130. po.Height = tc.height
  131. result, err := ProcessImage(context.Background(), imgdata, po, nil)
  132. s.Require().NoError(err)
  133. s.Require().NotNil(result)
  134. s.checkSize(result, tc.outWidth, tc.outHeight)
  135. })
  136. }
  137. }
  138. func (s *ProcessingTestSuite) TestResizeToFitExtend() {
  139. imgdata := s.openFile("test2.jpg")
  140. po := s.po().NewProcessingOptions()
  141. po.ResizingType = options.ResizeFit
  142. po.Extend = options.ExtendOptions{
  143. Enabled: true,
  144. Gravity: options.GravityOptions{
  145. Type: options.GravityCenter,
  146. },
  147. }
  148. testCases := []struct {
  149. width int
  150. height int
  151. outWidth int
  152. outHeight int
  153. }{
  154. {width: 50, height: 50, outWidth: 50, outHeight: 50},
  155. {width: 50, height: 20, outWidth: 50, outHeight: 20},
  156. {width: 20, height: 50, outWidth: 20, outHeight: 50},
  157. {width: 300, height: 300, outWidth: 300, outHeight: 300},
  158. {width: 300, height: 125, outWidth: 300, outHeight: 125},
  159. {width: 250, height: 300, outWidth: 250, outHeight: 300},
  160. {width: 0, height: 50, outWidth: 100, outHeight: 50},
  161. {width: 50, height: 0, outWidth: 50, outHeight: 25},
  162. {width: 0, height: 200, outWidth: 200, outHeight: 200},
  163. {width: 300, height: 0, outWidth: 300, outHeight: 100},
  164. }
  165. for _, tc := range testCases {
  166. s.Run(fmt.Sprintf("%dx%d", tc.width, tc.height), func() {
  167. po.Width = tc.width
  168. po.Height = tc.height
  169. result, err := ProcessImage(context.Background(), imgdata, po, nil)
  170. s.Require().NoError(err)
  171. s.Require().NotNil(result)
  172. s.checkSize(result, tc.outWidth, tc.outHeight)
  173. })
  174. }
  175. }
  176. func (s *ProcessingTestSuite) TestResizeToFitExtendAR() {
  177. imgdata := s.openFile("test2.jpg")
  178. po := s.po().NewProcessingOptions()
  179. po.ResizingType = options.ResizeFit
  180. po.ExtendAspectRatio = options.ExtendOptions{
  181. Enabled: true,
  182. Gravity: options.GravityOptions{
  183. Type: options.GravityCenter,
  184. },
  185. }
  186. testCases := []struct {
  187. width int
  188. height int
  189. outWidth int
  190. outHeight int
  191. }{
  192. {width: 50, height: 50, outWidth: 50, outHeight: 50},
  193. {width: 50, height: 20, outWidth: 50, outHeight: 20},
  194. {width: 20, height: 50, outWidth: 20, outHeight: 50},
  195. {width: 300, height: 300, outWidth: 200, outHeight: 200},
  196. {width: 300, height: 125, outWidth: 240, outHeight: 100},
  197. {width: 250, height: 500, outWidth: 200, outHeight: 400},
  198. {width: 0, height: 50, outWidth: 100, outHeight: 50},
  199. {width: 50, height: 0, outWidth: 50, outHeight: 25},
  200. {width: 0, height: 200, outWidth: 200, outHeight: 100},
  201. {width: 300, height: 0, outWidth: 200, outHeight: 100},
  202. }
  203. for _, tc := range testCases {
  204. s.Run(fmt.Sprintf("%dx%d", tc.width, tc.height), func() {
  205. po.Width = tc.width
  206. po.Height = tc.height
  207. result, err := ProcessImage(context.Background(), imgdata, po, nil)
  208. s.Require().NoError(err)
  209. s.Require().NotNil(result)
  210. s.checkSize(result, tc.outWidth, tc.outHeight)
  211. var i vips.Image
  212. s.Require().NoError(i.Load(result.OutData, 1, 1.0, 1))
  213. h, err := testutil.ImageDifferenceHash(unsafe.Pointer(i.VipsImage))
  214. s.Require().NoError(err)
  215. fmt.Println(h.ToString())
  216. })
  217. }
  218. }
  219. func (s *ProcessingTestSuite) TestResizeToFill() {
  220. imgdata := s.openFile("test2.jpg")
  221. po := s.po().NewProcessingOptions()
  222. po.ResizingType = options.ResizeFill
  223. testCases := []struct {
  224. width int
  225. height int
  226. outWidth int
  227. outHeight int
  228. }{
  229. {width: 50, height: 50, outWidth: 50, outHeight: 50},
  230. {width: 50, height: 20, outWidth: 50, outHeight: 20},
  231. {width: 20, height: 50, outWidth: 20, outHeight: 50},
  232. {width: 300, height: 300, outWidth: 200, outHeight: 100},
  233. {width: 300, height: 50, outWidth: 200, outHeight: 50},
  234. {width: 100, height: 300, outWidth: 100, outHeight: 100},
  235. {width: 0, height: 50, outWidth: 100, outHeight: 50},
  236. {width: 50, height: 0, outWidth: 50, outHeight: 25},
  237. {width: 0, height: 200, outWidth: 200, outHeight: 100},
  238. {width: 300, height: 0, outWidth: 200, outHeight: 100},
  239. }
  240. for _, tc := range testCases {
  241. s.Run(fmt.Sprintf("%dx%d", tc.width, tc.height), func() {
  242. po.Width = tc.width
  243. po.Height = tc.height
  244. result, err := ProcessImage(context.Background(), imgdata, po, nil)
  245. s.Require().NoError(err)
  246. s.Require().NotNil(result)
  247. s.checkSize(result, tc.outWidth, tc.outHeight)
  248. })
  249. }
  250. }
  251. func (s *ProcessingTestSuite) TestResizeToFillEnlarge() {
  252. imgdata := s.openFile("test2.jpg")
  253. po := s.po().NewProcessingOptions()
  254. po.ResizingType = options.ResizeFill
  255. po.Enlarge = true
  256. testCases := []struct {
  257. width int
  258. height int
  259. outWidth int
  260. outHeight int
  261. }{
  262. {width: 50, height: 50, outWidth: 50, outHeight: 50},
  263. {width: 50, height: 20, outWidth: 50, outHeight: 20},
  264. {width: 20, height: 50, outWidth: 20, outHeight: 50},
  265. {width: 300, height: 300, outWidth: 300, outHeight: 300},
  266. {width: 300, height: 125, outWidth: 300, outHeight: 125},
  267. {width: 250, height: 300, outWidth: 250, outHeight: 300},
  268. {width: 0, height: 50, outWidth: 100, outHeight: 50},
  269. {width: 50, height: 0, outWidth: 50, outHeight: 25},
  270. {width: 0, height: 200, outWidth: 400, outHeight: 200},
  271. {width: 300, height: 0, outWidth: 300, outHeight: 150},
  272. }
  273. for _, tc := range testCases {
  274. s.Run(fmt.Sprintf("%dx%d", tc.width, tc.height), func() {
  275. po.Width = tc.width
  276. po.Height = tc.height
  277. result, err := ProcessImage(context.Background(), imgdata, po, nil)
  278. s.Require().NoError(err)
  279. s.Require().NotNil(result)
  280. s.checkSize(result, tc.outWidth, tc.outHeight)
  281. })
  282. }
  283. }
  284. func (s *ProcessingTestSuite) TestResizeToFillExtend() {
  285. imgdata := s.openFile("test2.jpg")
  286. po := s.po().NewProcessingOptions()
  287. po.ResizingType = options.ResizeFill
  288. po.Extend = options.ExtendOptions{
  289. Enabled: true,
  290. Gravity: options.GravityOptions{
  291. Type: options.GravityCenter,
  292. },
  293. }
  294. testCases := []struct {
  295. width int
  296. height int
  297. outWidth int
  298. outHeight int
  299. }{
  300. {width: 50, height: 50, outWidth: 50, outHeight: 50},
  301. {width: 50, height: 20, outWidth: 50, outHeight: 20},
  302. {width: 20, height: 50, outWidth: 20, outHeight: 50},
  303. {width: 300, height: 300, outWidth: 300, outHeight: 300},
  304. {width: 300, height: 125, outWidth: 300, outHeight: 125},
  305. {width: 250, height: 300, outWidth: 250, outHeight: 300},
  306. {width: 300, height: 50, outWidth: 300, outHeight: 50},
  307. {width: 100, height: 300, outWidth: 100, outHeight: 300},
  308. {width: 0, height: 50, outWidth: 100, outHeight: 50},
  309. {width: 50, height: 0, outWidth: 50, outHeight: 25},
  310. {width: 0, height: 200, outWidth: 200, outHeight: 200},
  311. {width: 300, height: 0, outWidth: 300, outHeight: 100},
  312. }
  313. for _, tc := range testCases {
  314. s.Run(fmt.Sprintf("%dx%d", tc.width, tc.height), func() {
  315. po.Width = tc.width
  316. po.Height = tc.height
  317. result, err := ProcessImage(context.Background(), imgdata, po, nil)
  318. s.Require().NoError(err)
  319. s.Require().NotNil(result)
  320. s.checkSize(result, tc.outWidth, tc.outHeight)
  321. })
  322. }
  323. }
  324. func (s *ProcessingTestSuite) TestResizeToFillExtendAR() {
  325. imgdata := s.openFile("test2.jpg")
  326. po := s.po().NewProcessingOptions()
  327. po.ResizingType = options.ResizeFill
  328. po.ExtendAspectRatio = options.ExtendOptions{
  329. Enabled: true,
  330. Gravity: options.GravityOptions{
  331. Type: options.GravityCenter,
  332. },
  333. }
  334. testCases := []struct {
  335. width int
  336. height int
  337. outWidth int
  338. outHeight int
  339. }{
  340. {width: 50, height: 50, outWidth: 50, outHeight: 50},
  341. {width: 50, height: 20, outWidth: 50, outHeight: 20},
  342. {width: 20, height: 50, outWidth: 20, outHeight: 50},
  343. {width: 300, height: 300, outWidth: 200, outHeight: 200},
  344. {width: 300, height: 125, outWidth: 240, outHeight: 100},
  345. {width: 250, height: 500, outWidth: 200, outHeight: 400},
  346. {width: 300, height: 50, outWidth: 300, outHeight: 50},
  347. {width: 100, height: 300, outWidth: 100, outHeight: 300},
  348. {width: 0, height: 50, outWidth: 100, outHeight: 50},
  349. {width: 50, height: 0, outWidth: 50, outHeight: 25},
  350. {width: 0, height: 200, outWidth: 200, outHeight: 100},
  351. {width: 300, height: 0, outWidth: 200, outHeight: 100},
  352. }
  353. for _, tc := range testCases {
  354. s.Run(fmt.Sprintf("%dx%d", tc.width, tc.height), func() {
  355. po.Width = tc.width
  356. po.Height = tc.height
  357. result, err := ProcessImage(context.Background(), imgdata, po, nil)
  358. s.Require().NoError(err)
  359. s.Require().NotNil(result)
  360. s.checkSize(result, tc.outWidth, tc.outHeight)
  361. })
  362. }
  363. }
  364. func (s *ProcessingTestSuite) TestResizeToFillDown() {
  365. imgdata := s.openFile("test2.jpg")
  366. po := s.po().NewProcessingOptions()
  367. po.ResizingType = options.ResizeFillDown
  368. testCases := []struct {
  369. width int
  370. height int
  371. outWidth int
  372. outHeight int
  373. }{
  374. {width: 50, height: 50, outWidth: 50, outHeight: 50},
  375. {width: 50, height: 20, outWidth: 50, outHeight: 20},
  376. {width: 20, height: 50, outWidth: 20, outHeight: 50},
  377. {width: 300, height: 300, outWidth: 100, outHeight: 100},
  378. {width: 300, height: 125, outWidth: 200, outHeight: 83},
  379. {width: 250, height: 300, outWidth: 83, outHeight: 100},
  380. {width: 0, height: 50, outWidth: 100, outHeight: 50},
  381. {width: 50, height: 0, outWidth: 50, outHeight: 25},
  382. {width: 0, height: 200, outWidth: 200, outHeight: 100},
  383. {width: 300, height: 0, outWidth: 200, outHeight: 100},
  384. }
  385. for _, tc := range testCases {
  386. s.Run(fmt.Sprintf("%dx%d", tc.width, tc.height), func() {
  387. po.Width = tc.width
  388. po.Height = tc.height
  389. result, err := ProcessImage(context.Background(), imgdata, po, nil)
  390. s.Require().NoError(err)
  391. s.Require().NotNil(result)
  392. s.checkSize(result, tc.outWidth, tc.outHeight)
  393. })
  394. }
  395. }
  396. func (s *ProcessingTestSuite) TestResizeToFillDownEnlarge() {
  397. imgdata := s.openFile("test2.jpg")
  398. po := s.po().NewProcessingOptions()
  399. po.ResizingType = options.ResizeFillDown
  400. po.Enlarge = true
  401. testCases := []struct {
  402. width int
  403. height int
  404. outWidth int
  405. outHeight int
  406. }{
  407. {width: 50, height: 50, outWidth: 50, outHeight: 50},
  408. {width: 50, height: 20, outWidth: 50, outHeight: 20},
  409. {width: 20, height: 50, outWidth: 20, outHeight: 50},
  410. {width: 300, height: 300, outWidth: 300, outHeight: 300},
  411. {width: 300, height: 125, outWidth: 300, outHeight: 125},
  412. {width: 250, height: 300, outWidth: 250, outHeight: 300},
  413. {width: 0, height: 50, outWidth: 100, outHeight: 50},
  414. {width: 50, height: 0, outWidth: 50, outHeight: 25},
  415. {width: 0, height: 200, outWidth: 400, outHeight: 200},
  416. {width: 300, height: 0, outWidth: 300, outHeight: 150},
  417. }
  418. for _, tc := range testCases {
  419. s.Run(fmt.Sprintf("%dx%d", tc.width, tc.height), func() {
  420. po.Width = tc.width
  421. po.Height = tc.height
  422. result, err := ProcessImage(context.Background(), imgdata, po, nil)
  423. s.Require().NoError(err)
  424. s.Require().NotNil(result)
  425. s.checkSize(result, tc.outWidth, tc.outHeight)
  426. })
  427. }
  428. }
  429. func (s *ProcessingTestSuite) TestResizeToFillDownExtend() {
  430. imgdata := s.openFile("test2.jpg")
  431. po := s.po().NewProcessingOptions()
  432. po.ResizingType = options.ResizeFillDown
  433. po.Extend = options.ExtendOptions{
  434. Enabled: true,
  435. Gravity: options.GravityOptions{
  436. Type: options.GravityCenter,
  437. },
  438. }
  439. testCases := []struct {
  440. width int
  441. height int
  442. outWidth int
  443. outHeight int
  444. }{
  445. {width: 50, height: 50, outWidth: 50, outHeight: 50},
  446. {width: 50, height: 20, outWidth: 50, outHeight: 20},
  447. {width: 20, height: 50, outWidth: 20, outHeight: 50},
  448. {width: 300, height: 300, outWidth: 300, outHeight: 300},
  449. {width: 300, height: 125, outWidth: 300, outHeight: 125},
  450. {width: 250, height: 300, outWidth: 250, outHeight: 300},
  451. {width: 300, height: 50, outWidth: 300, outHeight: 50},
  452. {width: 100, height: 300, outWidth: 100, outHeight: 300},
  453. {width: 0, height: 50, outWidth: 100, outHeight: 50},
  454. {width: 50, height: 0, outWidth: 50, outHeight: 25},
  455. {width: 0, height: 200, outWidth: 200, outHeight: 200},
  456. {width: 300, height: 0, outWidth: 300, outHeight: 100},
  457. }
  458. for _, tc := range testCases {
  459. s.Run(fmt.Sprintf("%dx%d", tc.width, tc.height), func() {
  460. po.Width = tc.width
  461. po.Height = tc.height
  462. result, err := ProcessImage(context.Background(), imgdata, po, nil)
  463. s.Require().NoError(err)
  464. s.Require().NotNil(result)
  465. s.checkSize(result, tc.outWidth, tc.outHeight)
  466. })
  467. }
  468. }
  469. func (s *ProcessingTestSuite) TestResizeToFillDownExtendAR() {
  470. imgdata := s.openFile("test2.jpg")
  471. po := s.po().NewProcessingOptions()
  472. po.ResizingType = options.ResizeFillDown
  473. po.ExtendAspectRatio = options.ExtendOptions{
  474. Enabled: true,
  475. Gravity: options.GravityOptions{
  476. Type: options.GravityCenter,
  477. },
  478. }
  479. testCases := []struct {
  480. width int
  481. height int
  482. outWidth int
  483. outHeight int
  484. }{
  485. {width: 50, height: 50, outWidth: 50, outHeight: 50},
  486. {width: 50, height: 20, outWidth: 50, outHeight: 20},
  487. {width: 20, height: 50, outWidth: 20, outHeight: 50},
  488. {width: 300, height: 300, outWidth: 100, outHeight: 100},
  489. {width: 300, height: 125, outWidth: 200, outHeight: 83},
  490. {width: 250, height: 300, outWidth: 83, outHeight: 100},
  491. {width: 0, height: 50, outWidth: 100, outHeight: 50},
  492. {width: 50, height: 0, outWidth: 50, outHeight: 25},
  493. {width: 0, height: 200, outWidth: 200, outHeight: 100},
  494. {width: 300, height: 0, outWidth: 200, outHeight: 100},
  495. }
  496. for _, tc := range testCases {
  497. s.Run(fmt.Sprintf("%dx%d", tc.width, tc.height), func() {
  498. po.Width = tc.width
  499. po.Height = tc.height
  500. result, err := ProcessImage(context.Background(), imgdata, po, nil)
  501. s.Require().NoError(err)
  502. s.Require().NotNil(result)
  503. s.checkSize(result, tc.outWidth, tc.outHeight)
  504. })
  505. }
  506. }
  507. func (s *ProcessingTestSuite) TestResultSizeLimit() {
  508. imgdata := s.openFile("test2.jpg")
  509. po := s.po().NewProcessingOptions()
  510. testCases := []struct {
  511. limit int
  512. width int
  513. height int
  514. resizingType options.ResizeType
  515. enlarge bool
  516. extend bool
  517. extendAR bool
  518. padding options.PaddingOptions
  519. rotate int
  520. outWidth int
  521. outHeight int
  522. }{
  523. {
  524. limit: 1000,
  525. width: 100,
  526. height: 100,
  527. resizingType: options.ResizeFit,
  528. outWidth: 100,
  529. outHeight: 50,
  530. },
  531. {
  532. limit: 50,
  533. width: 100,
  534. height: 100,
  535. resizingType: options.ResizeFit,
  536. outWidth: 50,
  537. outHeight: 25,
  538. },
  539. {
  540. limit: 50,
  541. width: 0,
  542. height: 0,
  543. resizingType: options.ResizeFit,
  544. outWidth: 50,
  545. outHeight: 25,
  546. },
  547. {
  548. limit: 100,
  549. width: 0,
  550. height: 100,
  551. resizingType: options.ResizeFit,
  552. outWidth: 100,
  553. outHeight: 50,
  554. },
  555. {
  556. limit: 50,
  557. width: 150,
  558. height: 0,
  559. resizingType: options.ResizeFit,
  560. outWidth: 50,
  561. outHeight: 25,
  562. },
  563. {
  564. limit: 100,
  565. width: 1000,
  566. height: 1000,
  567. resizingType: options.ResizeFit,
  568. outWidth: 100,
  569. outHeight: 50,
  570. },
  571. {
  572. limit: 100,
  573. width: 1000,
  574. height: 1000,
  575. resizingType: options.ResizeFit,
  576. enlarge: true,
  577. outWidth: 100,
  578. outHeight: 50,
  579. },
  580. {
  581. limit: 100,
  582. width: 1000,
  583. height: 2000,
  584. resizingType: options.ResizeFit,
  585. extend: true,
  586. outWidth: 50,
  587. outHeight: 100,
  588. },
  589. {
  590. limit: 100,
  591. width: 1000,
  592. height: 2000,
  593. resizingType: options.ResizeFit,
  594. extendAR: true,
  595. outWidth: 50,
  596. outHeight: 100,
  597. },
  598. {
  599. limit: 100,
  600. width: 100,
  601. height: 150,
  602. resizingType: options.ResizeFit,
  603. rotate: 90,
  604. outWidth: 50,
  605. outHeight: 100,
  606. },
  607. {
  608. limit: 100,
  609. width: 0,
  610. height: 0,
  611. resizingType: options.ResizeFit,
  612. rotate: 90,
  613. outWidth: 50,
  614. outHeight: 100,
  615. },
  616. {
  617. limit: 200,
  618. width: 100,
  619. height: 100,
  620. resizingType: options.ResizeFit,
  621. padding: options.PaddingOptions{
  622. Enabled: true,
  623. Top: 100,
  624. Right: 200,
  625. Bottom: 300,
  626. Left: 400,
  627. },
  628. outWidth: 200,
  629. outHeight: 129,
  630. },
  631. {
  632. limit: 1000,
  633. width: 100,
  634. height: 100,
  635. resizingType: options.ResizeFill,
  636. outWidth: 100,
  637. outHeight: 100,
  638. },
  639. {
  640. limit: 50,
  641. width: 100,
  642. height: 100,
  643. resizingType: options.ResizeFill,
  644. outWidth: 50,
  645. outHeight: 50,
  646. },
  647. {
  648. limit: 50,
  649. width: 1000,
  650. height: 50,
  651. resizingType: options.ResizeFill,
  652. outWidth: 50,
  653. outHeight: 13,
  654. },
  655. {
  656. limit: 50,
  657. width: 100,
  658. height: 1000,
  659. resizingType: options.ResizeFill,
  660. outWidth: 50,
  661. outHeight: 50,
  662. },
  663. {
  664. limit: 50,
  665. width: 0,
  666. height: 0,
  667. resizingType: options.ResizeFill,
  668. outWidth: 50,
  669. outHeight: 25,
  670. },
  671. {
  672. limit: 100,
  673. width: 0,
  674. height: 100,
  675. resizingType: options.ResizeFill,
  676. outWidth: 100,
  677. outHeight: 50,
  678. },
  679. {
  680. limit: 50,
  681. width: 150,
  682. height: 0,
  683. resizingType: options.ResizeFill,
  684. outWidth: 50,
  685. outHeight: 25,
  686. },
  687. {
  688. limit: 100,
  689. width: 1000,
  690. height: 1000,
  691. resizingType: options.ResizeFill,
  692. outWidth: 100,
  693. outHeight: 50,
  694. },
  695. {
  696. limit: 100,
  697. width: 1000,
  698. height: 1000,
  699. resizingType: options.ResizeFill,
  700. enlarge: true,
  701. outWidth: 100,
  702. outHeight: 100,
  703. },
  704. {
  705. limit: 100,
  706. width: 1000,
  707. height: 2000,
  708. resizingType: options.ResizeFill,
  709. extend: true,
  710. outWidth: 50,
  711. outHeight: 100,
  712. },
  713. {
  714. limit: 100,
  715. width: 1000,
  716. height: 2000,
  717. resizingType: options.ResizeFill,
  718. extendAR: true,
  719. outWidth: 50,
  720. outHeight: 100,
  721. },
  722. {
  723. limit: 100,
  724. width: 100,
  725. height: 150,
  726. resizingType: options.ResizeFill,
  727. rotate: 90,
  728. outWidth: 67,
  729. outHeight: 100,
  730. },
  731. {
  732. limit: 100,
  733. width: 0,
  734. height: 0,
  735. resizingType: options.ResizeFill,
  736. rotate: 90,
  737. outWidth: 50,
  738. outHeight: 100,
  739. },
  740. {
  741. limit: 200,
  742. width: 100,
  743. height: 100,
  744. resizingType: options.ResizeFill,
  745. padding: options.PaddingOptions{
  746. Enabled: true,
  747. Top: 100,
  748. Right: 200,
  749. Bottom: 300,
  750. Left: 400,
  751. },
  752. outWidth: 200,
  753. outHeight: 144,
  754. },
  755. {
  756. limit: 1000,
  757. width: 100,
  758. height: 100,
  759. resizingType: options.ResizeFillDown,
  760. outWidth: 100,
  761. outHeight: 100,
  762. },
  763. {
  764. limit: 50,
  765. width: 100,
  766. height: 100,
  767. resizingType: options.ResizeFillDown,
  768. outWidth: 50,
  769. outHeight: 50,
  770. },
  771. {
  772. limit: 50,
  773. width: 1000,
  774. height: 50,
  775. resizingType: options.ResizeFillDown,
  776. outWidth: 50,
  777. outHeight: 3,
  778. },
  779. {
  780. limit: 50,
  781. width: 100,
  782. height: 1000,
  783. resizingType: options.ResizeFillDown,
  784. outWidth: 5,
  785. outHeight: 50,
  786. },
  787. {
  788. limit: 50,
  789. width: 0,
  790. height: 0,
  791. resizingType: options.ResizeFillDown,
  792. outWidth: 50,
  793. outHeight: 25,
  794. },
  795. {
  796. limit: 100,
  797. width: 0,
  798. height: 100,
  799. resizingType: options.ResizeFillDown,
  800. outWidth: 100,
  801. outHeight: 50,
  802. },
  803. {
  804. limit: 50,
  805. width: 150,
  806. height: 0,
  807. resizingType: options.ResizeFillDown,
  808. outWidth: 50,
  809. outHeight: 25,
  810. },
  811. {
  812. limit: 100,
  813. width: 1000,
  814. height: 1000,
  815. resizingType: options.ResizeFillDown,
  816. outWidth: 100,
  817. outHeight: 100,
  818. },
  819. {
  820. limit: 100,
  821. width: 1000,
  822. height: 1000,
  823. resizingType: options.ResizeFillDown,
  824. enlarge: true,
  825. outWidth: 100,
  826. outHeight: 100,
  827. },
  828. {
  829. limit: 100,
  830. width: 1000,
  831. height: 2000,
  832. resizingType: options.ResizeFillDown,
  833. extend: true,
  834. outWidth: 50,
  835. outHeight: 100,
  836. },
  837. {
  838. limit: 100,
  839. width: 1000,
  840. height: 2000,
  841. resizingType: options.ResizeFillDown,
  842. extendAR: true,
  843. outWidth: 50,
  844. outHeight: 100,
  845. },
  846. {
  847. limit: 100,
  848. width: 1000,
  849. height: 1500,
  850. resizingType: options.ResizeFillDown,
  851. rotate: 90,
  852. outWidth: 67,
  853. outHeight: 100,
  854. },
  855. {
  856. limit: 100,
  857. width: 0,
  858. height: 0,
  859. resizingType: options.ResizeFillDown,
  860. rotate: 90,
  861. outWidth: 50,
  862. outHeight: 100,
  863. },
  864. {
  865. limit: 200,
  866. width: 100,
  867. height: 100,
  868. resizingType: options.ResizeFillDown,
  869. padding: options.PaddingOptions{
  870. Enabled: true,
  871. Top: 100,
  872. Right: 200,
  873. Bottom: 300,
  874. Left: 400,
  875. },
  876. outWidth: 200,
  877. outHeight: 144,
  878. },
  879. {
  880. limit: 200,
  881. width: 1000,
  882. height: 1000,
  883. resizingType: options.ResizeFillDown,
  884. padding: options.PaddingOptions{
  885. Enabled: true,
  886. Top: 100,
  887. Right: 200,
  888. Bottom: 300,
  889. Left: 400,
  890. },
  891. outWidth: 200,
  892. outHeight: 144,
  893. },
  894. }
  895. for _, tc := range testCases {
  896. name := fmt.Sprintf("%s_%dx%d_limit_%d", tc.resizingType, tc.width, tc.height, tc.limit)
  897. if tc.enlarge {
  898. name += "_enlarge"
  899. }
  900. if tc.extend {
  901. name += "_extend"
  902. }
  903. if tc.extendAR {
  904. name += "_extendAR"
  905. }
  906. if tc.rotate != 0 {
  907. name += fmt.Sprintf("_rot_%d", tc.rotate)
  908. }
  909. if tc.padding.Enabled {
  910. name += fmt.Sprintf("_padding_%dx%dx%dx%d", tc.padding.Top, tc.padding.Right, tc.padding.Bottom, tc.padding.Left)
  911. }
  912. s.Run(name, func() {
  913. po.SecurityOptions.MaxResultDimension = tc.limit
  914. po.Width = tc.width
  915. po.Height = tc.height
  916. po.ResizingType = tc.resizingType
  917. po.Enlarge = tc.enlarge
  918. po.Extend.Enabled = tc.extend
  919. po.ExtendAspectRatio.Enabled = tc.extendAR
  920. po.Rotate = tc.rotate
  921. po.Padding = tc.padding
  922. result, err := ProcessImage(context.Background(), imgdata, po, nil)
  923. s.Require().NoError(err)
  924. s.Require().NotNil(result)
  925. s.checkSize(result, tc.outWidth, tc.outHeight)
  926. })
  927. }
  928. }
  929. func (s *ProcessingTestSuite) TestImageResolutionTooLarge() {
  930. po := s.po().NewProcessingOptions()
  931. po.SecurityOptions.MaxSrcResolution = 1
  932. imgdata := s.openFile("test2.jpg")
  933. _, err := ProcessImage(context.Background(), imgdata, po, nil)
  934. s.Require().Error(err)
  935. s.Require().Equal(422, ierrors.Wrap(err, 0).StatusCode())
  936. }
  937. func TestProcessing(t *testing.T) {
  938. suite.Run(t, new(ProcessingTestSuite))
  939. }