pipeline.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. package processing
  2. import (
  3. "context"
  4. "github.com/imgproxy/imgproxy/v3/auximageprovider"
  5. "github.com/imgproxy/imgproxy/v3/imagedata"
  6. "github.com/imgproxy/imgproxy/v3/options"
  7. "github.com/imgproxy/imgproxy/v3/processing/pipeline"
  8. "github.com/imgproxy/imgproxy/v3/server"
  9. "github.com/imgproxy/imgproxy/v3/vips"
  10. )
  11. // NOTE: this will be called pipeline.Context in the separate package
  12. type Context struct {
  13. // The runner that runs this pipeline
  14. runner *Runner
  15. Ctx context.Context
  16. // Global processing configuration which could be used by individual steps
  17. Config *pipeline.Config
  18. // VIPS image
  19. Img *vips.Image
  20. // Processing options this pipeline runs with
  21. PO *options.ProcessingOptions
  22. // Source image data
  23. ImgData imagedata.ImageData
  24. // The watermark image provider, if any watermarking is to be done.
  25. WatermarkProvider auximageprovider.Provider
  26. SrcWidth int
  27. SrcHeight int
  28. Angle int
  29. Flip bool
  30. CropWidth int
  31. CropHeight int
  32. CropGravity options.GravityOptions
  33. WScale float64
  34. HScale float64
  35. DprScale float64
  36. // The base scale factor for vector images.
  37. // It is used to downscale the input vector image to the maximum allowed resolution
  38. VectorBaseScale float64
  39. // The width we aim to get.
  40. // Based on the requested width scaled according to processing options.
  41. // Can be 0 if width is not specified in the processing options.
  42. TargetWidth int
  43. // The height we aim to get.
  44. // Based on the requested height scaled according to processing options.
  45. // Can be 0 if height is not specified in the processing options.
  46. TargetHeight int
  47. // The width of the image after cropping, scaling and rotating
  48. ScaledWidth int
  49. // The height of the image after cropping, scaling and rotating
  50. ScaledHeight int
  51. // The width of the result crop according to the resizing type
  52. ResultCropWidth int
  53. // The height of the result crop according to the resizing type
  54. ResultCropHeight int
  55. // The width of the image extended to the requested aspect ratio.
  56. // Can be 0 if any of the dimensions is not specified in the processing options
  57. // or if the image already has the requested aspect ratio.
  58. ExtendAspectRatioWidth int
  59. // The width of the image extended to the requested aspect ratio.
  60. // Can be 0 if any of the dimensions is not specified in the processing options
  61. // or if the image already has the requested aspect ratio.
  62. ExtendAspectRatioHeight int
  63. }
  64. // NOTE: same, pipeline.Step, pipeline.Pipeline, pipeline.Runner
  65. type Step func(ctx *Context) error
  66. type Pipeline []Step
  67. // Runner is responsible for running a processing pipeline
  68. type Runner struct {
  69. config *pipeline.Config
  70. watermark auximageprovider.Provider
  71. }
  72. // New creates a new Runner instance with the given configuration and watermark provider
  73. func New(config *pipeline.Config, watermark auximageprovider.Provider) *Runner {
  74. return &Runner{
  75. config: config,
  76. watermark: watermark,
  77. }
  78. }
  79. // Run runs the given pipeline with the given parameters
  80. func (f *Runner) Run(
  81. p Pipeline,
  82. ctx context.Context,
  83. img *vips.Image,
  84. po *options.ProcessingOptions,
  85. imgdata imagedata.ImageData,
  86. ) error {
  87. pctx := f.newContext(ctx, img, po, imgdata)
  88. for _, step := range p {
  89. if err := step(&pctx); err != nil {
  90. return err
  91. }
  92. if err := server.CheckTimeout(ctx); err != nil {
  93. return err
  94. }
  95. }
  96. img.SetDouble("imgproxy-dpr-scale", pctx.DprScale)
  97. return nil
  98. }
  99. func (r *Runner) newContext(
  100. ctx context.Context,
  101. img *vips.Image,
  102. po *options.ProcessingOptions,
  103. imgdata imagedata.ImageData,
  104. ) Context {
  105. pctx := Context{
  106. runner: r,
  107. Ctx: ctx,
  108. Config: r.config,
  109. Img: img,
  110. PO: po,
  111. ImgData: imgdata,
  112. WScale: 1.0,
  113. HScale: 1.0,
  114. DprScale: 1.0,
  115. VectorBaseScale: 1.0,
  116. CropGravity: po.Crop.Gravity,
  117. WatermarkProvider: r.watermark,
  118. }
  119. if pctx.CropGravity.Type == options.GravityUnknown {
  120. pctx.CropGravity = po.Gravity
  121. }
  122. return pctx
  123. }
  124. func (c *Context) Runner() *Runner {
  125. return c.runner
  126. }