1
0

image_data.go 2.8 KB

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