image_data.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. package imagedata
  2. import (
  3. "context"
  4. "encoding/base64"
  5. "fmt"
  6. "net/http"
  7. "os"
  8. "strings"
  9. "sync"
  10. "github.com/imgproxy/imgproxy/v3/config"
  11. "github.com/imgproxy/imgproxy/v3/ierrors"
  12. "github.com/imgproxy/imgproxy/v3/imagetype"
  13. )
  14. var (
  15. Watermark *ImageData
  16. FallbackImage *ImageData
  17. )
  18. type ImageData struct {
  19. Type imagetype.Type
  20. Data []byte
  21. Headers map[string]string
  22. cancel context.CancelFunc
  23. cancelOnce sync.Once
  24. }
  25. func (d *ImageData) Close() {
  26. d.cancelOnce.Do(func() {
  27. if d.cancel != nil {
  28. d.cancel()
  29. }
  30. })
  31. }
  32. func (d *ImageData) SetCancel(cancel context.CancelFunc) {
  33. d.cancel = cancel
  34. }
  35. func Init() error {
  36. initRead()
  37. if err := initDownloading(); err != nil {
  38. return err
  39. }
  40. if err := loadWatermark(); err != nil {
  41. return err
  42. }
  43. if err := loadFallbackImage(); err != nil {
  44. return err
  45. }
  46. return nil
  47. }
  48. func loadWatermark() (err error) {
  49. if len(config.WatermarkData) > 0 {
  50. Watermark, err = FromBase64(config.WatermarkData, "watermark")
  51. return
  52. }
  53. if len(config.WatermarkPath) > 0 {
  54. Watermark, err = FromFile(config.WatermarkPath, "watermark")
  55. return
  56. }
  57. if len(config.WatermarkURL) > 0 {
  58. Watermark, err = Download(config.WatermarkURL, "watermark", nil)
  59. return
  60. }
  61. return nil
  62. }
  63. func loadFallbackImage() (err error) {
  64. if len(config.FallbackImageData) > 0 {
  65. FallbackImage, err = FromBase64(config.FallbackImageData, "fallback image")
  66. return
  67. }
  68. if len(config.FallbackImagePath) > 0 {
  69. FallbackImage, err = FromFile(config.FallbackImagePath, "fallback image")
  70. return
  71. }
  72. if len(config.FallbackImageURL) > 0 {
  73. FallbackImage, err = Download(config.FallbackImageURL, "fallback image", nil)
  74. return
  75. }
  76. return nil
  77. }
  78. func FromBase64(encoded, desc string) (*ImageData, error) {
  79. dec := base64.NewDecoder(base64.StdEncoding, strings.NewReader(encoded))
  80. size := 4 * (len(encoded)/3 + 1)
  81. imgdata, err := readAndCheckImage(dec, size)
  82. if err != nil {
  83. return nil, fmt.Errorf("Can't decode %s: %s", desc, err)
  84. }
  85. return imgdata, nil
  86. }
  87. func FromFile(path, desc string) (*ImageData, error) {
  88. f, err := os.Open(path)
  89. if err != nil {
  90. return nil, fmt.Errorf("Can't read %s: %s", desc, err)
  91. }
  92. fi, err := f.Stat()
  93. if err != nil {
  94. return nil, fmt.Errorf("Can't read %s: %s", desc, err)
  95. }
  96. imgdata, err := readAndCheckImage(f, int(fi.Size()))
  97. if err != nil {
  98. return nil, fmt.Errorf("Can't read %s: %s", desc, err)
  99. }
  100. return imgdata, nil
  101. }
  102. func Download(imageURL, desc string, header http.Header) (*ImageData, error) {
  103. imgdata, err := download(imageURL, header)
  104. if err != nil {
  105. return nil, ierrors.WrapWithMessage(err, 1, fmt.Sprintf("Can't download %s: %s", desc, err))
  106. }
  107. return imgdata, nil
  108. }