imagetype.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. package imagetype
  2. import (
  3. "fmt"
  4. "net/url"
  5. "path/filepath"
  6. "strings"
  7. )
  8. type Type int
  9. const (
  10. Unknown Type = iota
  11. JPEG
  12. PNG
  13. WEBP
  14. GIF
  15. ICO
  16. SVG
  17. HEIC
  18. AVIF
  19. BMP
  20. TIFF
  21. )
  22. const contentDispositionFilenameFallback = "image"
  23. var (
  24. Types = map[string]Type{
  25. "jpeg": JPEG,
  26. "jpg": JPEG,
  27. "png": PNG,
  28. "webp": WEBP,
  29. "gif": GIF,
  30. "ico": ICO,
  31. "svg": SVG,
  32. "heic": HEIC,
  33. "avif": AVIF,
  34. "bmp": BMP,
  35. "tiff": TIFF,
  36. }
  37. mimes = map[Type]string{
  38. JPEG: "image/jpeg",
  39. PNG: "image/png",
  40. WEBP: "image/webp",
  41. GIF: "image/gif",
  42. ICO: "image/x-icon",
  43. SVG: "image/svg+xml",
  44. HEIC: "image/heif",
  45. AVIF: "image/avif",
  46. BMP: "image/bmp",
  47. TIFF: "image/tiff",
  48. }
  49. contentDispositionsFmt = map[Type]string{
  50. JPEG: "inline; filename=\"%s.jpg\"",
  51. PNG: "inline; filename=\"%s.png\"",
  52. WEBP: "inline; filename=\"%s.webp\"",
  53. GIF: "inline; filename=\"%s.gif\"",
  54. ICO: "inline; filename=\"%s.ico\"",
  55. SVG: "inline; filename=\"%s.svg\"",
  56. HEIC: "inline; filename=\"%s.heic\"",
  57. AVIF: "inline; filename=\"%s.avif\"",
  58. BMP: "inline; filename=\"%s.bmp\"",
  59. TIFF: "inline; filename=\"%s.tiff\"",
  60. }
  61. )
  62. func (it Type) String() string {
  63. for k, v := range Types {
  64. if v == it {
  65. return k
  66. }
  67. }
  68. return ""
  69. }
  70. func (it Type) MarshalJSON() ([]byte, error) {
  71. for k, v := range Types {
  72. if v == it {
  73. return []byte(fmt.Sprintf("%q", k)), nil
  74. }
  75. }
  76. return []byte("null"), nil
  77. }
  78. func (it Type) Mime() string {
  79. if mime, ok := mimes[it]; ok {
  80. return mime
  81. }
  82. return "application/octet-stream"
  83. }
  84. func (it Type) ContentDisposition(filename string) string {
  85. format, ok := contentDispositionsFmt[it]
  86. if !ok {
  87. return "inline"
  88. }
  89. return fmt.Sprintf(format, strings.ReplaceAll(filename, `"`, "%22"))
  90. }
  91. func (it Type) ContentDispositionFromURL(imageURL string) string {
  92. url, err := url.Parse(imageURL)
  93. if err != nil {
  94. return it.ContentDisposition(contentDispositionFilenameFallback)
  95. }
  96. _, filename := filepath.Split(url.Path)
  97. if len(filename) == 0 {
  98. return it.ContentDisposition(contentDispositionFilenameFallback)
  99. }
  100. return it.ContentDisposition(strings.TrimSuffix(filename, filepath.Ext(filename)))
  101. }
  102. func (it Type) SupportsAlpha() bool {
  103. return it != JPEG && it != BMP
  104. }
  105. func (it Type) SupportsAnimation() bool {
  106. return it == GIF || it == WEBP
  107. }
  108. func (it Type) SupportsColourProfile() bool {
  109. return it == JPEG ||
  110. it == PNG ||
  111. it == WEBP ||
  112. it == AVIF
  113. }