finalize.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  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. if nn.Name() == "rights" || nn.Name() == "contributor" || nn.Name() == "creator" || nn.Name() == "publisher" {
  53. filteredNodes = append(filteredNodes, nn)
  54. }
  55. }
  56. n.Nodes = filteredNodes
  57. }
  58. }
  59. if len(xmpDoc.Nodes()) == 0 {
  60. return nil
  61. }
  62. xmpData, err = xmp.Marshal(xmpDoc)
  63. if err != nil {
  64. return nil
  65. }
  66. return xmpData
  67. }
  68. func finalize(pctx *pipelineContext, img *vips.Image, po *options.ProcessingOptions, imgdata *imagedata.ImageData) error {
  69. if po.StripMetadata {
  70. var iptcData, xmpData []byte
  71. if po.KeepCopyright {
  72. iptcData = stripIPTC(img)
  73. xmpData = stripXMP(img)
  74. }
  75. if err := img.Strip(po.KeepCopyright); err != nil {
  76. return err
  77. }
  78. if po.KeepCopyright {
  79. if len(iptcData) > 0 {
  80. img.SetBlob("iptc-data", iptcData)
  81. }
  82. if len(xmpData) > 0 {
  83. img.SetBlob("xmp-data", xmpData)
  84. }
  85. }
  86. }
  87. return img.CopyMemory()
  88. }