finalize.go 2.4 KB

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