strip_metadata.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. package processing
  2. import (
  3. "bytes"
  4. "github.com/trimmer-io/go-xmp/xmp"
  5. "github.com/imgproxy/imgproxy/v3/imagemeta/iptc"
  6. "github.com/imgproxy/imgproxy/v3/imagemeta/photoshop"
  7. "github.com/imgproxy/imgproxy/v3/vips"
  8. )
  9. func stripPS3(img *vips.Image) []byte {
  10. ps3Data, err := img.GetBlob("iptc-data")
  11. if err != nil || len(ps3Data) == 0 {
  12. return nil
  13. }
  14. ps3Map := make(photoshop.PhotoshopMap)
  15. photoshop.Parse(ps3Data, ps3Map)
  16. iptcData, found := ps3Map[photoshop.IptcKey]
  17. if !found {
  18. return nil
  19. }
  20. iptcMap := make(iptc.IptcMap)
  21. err = iptc.Parse(iptcData, iptcMap)
  22. if err != nil {
  23. return nil
  24. }
  25. for key := range iptcMap {
  26. if key.RecordID == 2 && key.TagID != 80 && key.TagID != 110 && key.TagID != 116 {
  27. delete(iptcMap, key)
  28. }
  29. }
  30. if len(iptcMap) == 0 {
  31. return nil
  32. }
  33. ps3Map = photoshop.PhotoshopMap{
  34. photoshop.IptcKey: iptcMap.Dump(),
  35. }
  36. return ps3Map.Dump()
  37. }
  38. func stripXMP(img *vips.Image) []byte {
  39. xmpData, err := img.GetBlob("xmp-data")
  40. if err != nil || len(xmpData) == 0 {
  41. return nil
  42. }
  43. xmpDoc, err := xmp.Read(bytes.NewReader(xmpData))
  44. if err != nil {
  45. return nil
  46. }
  47. namespaces := xmpDoc.Namespaces()
  48. filteredNs := namespaces[:0]
  49. for _, ns := range namespaces {
  50. if ns.Name == "dc" || ns.Name == "xmpRights" || ns.Name == "cc" {
  51. filteredNs = append(filteredNs, ns)
  52. }
  53. }
  54. xmpDoc.FilterNamespaces(filteredNs)
  55. nodes := xmpDoc.Nodes()
  56. for _, n := range nodes {
  57. if n.Name() == "dc" {
  58. filteredNodes := n.Nodes[:0]
  59. for _, nn := range n.Nodes {
  60. name := nn.Name()
  61. if name == "rights" || name == "contributor" || name == "creator" || name == "publisher" {
  62. filteredNodes = append(filteredNodes, nn)
  63. }
  64. }
  65. n.Nodes = filteredNodes
  66. filteredAttrs := n.Attr[:0]
  67. for _, a := range n.Attr {
  68. name := a.Name.Local
  69. if name == "dc:rights" || name == "dc:contributor" || name == "dc:creator" || name == "dc:publisher" {
  70. filteredAttrs = append(filteredAttrs, a)
  71. }
  72. }
  73. n.Attr = filteredAttrs
  74. }
  75. }
  76. if len(xmpDoc.Nodes()) == 0 {
  77. return nil
  78. }
  79. xmpData, err = xmp.Marshal(xmpDoc)
  80. if err != nil {
  81. return nil
  82. }
  83. return xmpData
  84. }
  85. func (p *Processor) stripMetadata(c *Context) error {
  86. if !c.PO.StripMetadata() {
  87. return nil
  88. }
  89. keepCopyright := c.PO.KeepCopyright()
  90. var ps3Data, xmpData []byte
  91. if keepCopyright {
  92. ps3Data = stripPS3(c.Img)
  93. xmpData = stripXMP(c.Img)
  94. }
  95. if err := c.Img.Strip(keepCopyright); err != nil {
  96. return err
  97. }
  98. if keepCopyright {
  99. if len(ps3Data) > 0 {
  100. c.Img.SetBlob("iptc-data", ps3Data)
  101. }
  102. if len(xmpData) > 0 {
  103. c.Img.SetBlob("xmp-data", xmpData)
  104. }
  105. }
  106. return nil
  107. }