( ctx context.Context, img *vips.Image, po ProcessingOptions, offsetScale float64, framesCount int, )
| 104 | } |
| 105 | |
| 106 | func (p *Processor) applyWatermark( |
| 107 | ctx context.Context, |
| 108 | img *vips.Image, |
| 109 | po ProcessingOptions, |
| 110 | offsetScale float64, |
| 111 | framesCount int, |
| 112 | ) error { |
| 113 | if p.watermarkProvider == nil { |
| 114 | return nil |
| 115 | } |
| 116 | |
| 117 | wmData, _, err := p.watermarkProvider.Get(ctx, po.Options) |
| 118 | if err != nil { |
| 119 | return err |
| 120 | } |
| 121 | if wmData == nil { |
| 122 | return nil |
| 123 | } |
| 124 | defer wmData.Close() |
| 125 | |
| 126 | wm := new(vips.Image) |
| 127 | defer wm.Clear() |
| 128 | |
| 129 | width := img.Width() |
| 130 | height := img.Height() |
| 131 | frameHeight := height / framesCount |
| 132 | |
| 133 | if err := p.prepareWatermark( |
| 134 | ctx, wm, wmData, po, width, frameHeight, offsetScale, framesCount, |
| 135 | ); err != nil { |
| 136 | return err |
| 137 | } |
| 138 | |
| 139 | opacity := po.WatermarkOpacity() * p.config.WatermarkOpacity |
| 140 | |
| 141 | position := po.WatermarkPosition() |
| 142 | shouldReplicate := shouldReplicateWatermark(position) |
| 143 | |
| 144 | // If we replicated the watermark and need to apply it to an animated image, |
| 145 | // it is faster to replicate the watermark to all the image and apply it single-pass |
| 146 | if shouldReplicate && framesCount > 1 { |
| 147 | if err := wm.Replicate(width, height, false); err != nil { |
| 148 | return err |
| 149 | } |
| 150 | |
| 151 | return img.ApplyWatermark(wm, 0, 0, opacity) |
| 152 | } |
| 153 | |
| 154 | left, top := 0, 0 |
| 155 | wmWidth := wm.Width() |
| 156 | wmHeight := wm.Height() |
| 157 | |
| 158 | if !shouldReplicate { |
| 159 | gr := GravityOptions{ |
| 160 | Type: position, |
| 161 | X: po.WatermarkXOffset(), |
| 162 | Y: po.WatermarkYOffset(), |
| 163 | } |
no test coverage detected