image_data.go 2.5 KB

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