Full Mattermost server source with integrated Community Enterprise features. Includes vendor directory for offline/air-gapped builds. Structure: - enterprise-impl/: Enterprise feature implementations - enterprise-community/: Init files that register implementations - enterprise/: Bridge imports (community_imports.go) - vendor/: All dependencies for offline builds Build (online): go build ./cmd/mattermost Build (offline/air-gapped): go build -mod=vendor ./cmd/mattermost 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
158 lines
3.9 KiB
Go
158 lines
3.9 KiB
Go
/*Package clone provides image cloning function.*/
|
|
package clone
|
|
|
|
import (
|
|
"image"
|
|
"image/draw"
|
|
|
|
"github.com/anthonynsimon/bild/parallel"
|
|
)
|
|
|
|
// PadMethod is the method used to fill padded pixels.
|
|
type PadMethod uint8
|
|
|
|
const (
|
|
// NoFill leaves the padded pixels empty.
|
|
NoFill = iota
|
|
// EdgeExtend extends the closest edge pixel.
|
|
EdgeExtend
|
|
// EdgeWrap wraps around the pixels of an image.
|
|
EdgeWrap
|
|
)
|
|
|
|
// AsRGBA returns an RGBA copy of the supplied image.
|
|
func AsRGBA(src image.Image) *image.RGBA {
|
|
bounds := src.Bounds()
|
|
img := image.NewRGBA(bounds)
|
|
draw.Draw(img, bounds, src, bounds.Min, draw.Src)
|
|
return img
|
|
}
|
|
|
|
// AsShallowRGBA tries to cast to image.RGBA to get reference. Otherwise makes a copy
|
|
func AsShallowRGBA(src image.Image) *image.RGBA {
|
|
if rgba, ok := src.(*image.RGBA); ok {
|
|
return rgba
|
|
}
|
|
return AsRGBA(src)
|
|
}
|
|
|
|
// Pad returns an RGBA copy of the src image parameter with its edges padded
|
|
// using the supplied PadMethod.
|
|
// Parameter padX and padY correspond to the amount of padding to be applied
|
|
// on each side.
|
|
// Parameter m is the PadMethod to fill the new pixels.
|
|
//
|
|
// Usage example:
|
|
//
|
|
// result := Pad(img, 5,5, EdgeExtend)
|
|
func Pad(src image.Image, padX, padY int, m PadMethod) *image.RGBA {
|
|
var result *image.RGBA
|
|
|
|
switch m {
|
|
case EdgeExtend:
|
|
result = extend(src, padX, padY)
|
|
case NoFill:
|
|
result = noFill(src, padX, padY)
|
|
case EdgeWrap:
|
|
result = wrap(src, padX, padY)
|
|
default:
|
|
result = extend(src, padX, padY)
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
func noFill(img image.Image, padX, padY int) *image.RGBA {
|
|
srcBounds := img.Bounds()
|
|
paddedW, paddedH := srcBounds.Dx()+2*padX, srcBounds.Dy()+2*padY
|
|
newBounds := image.Rect(0, 0, paddedW, paddedH)
|
|
fillBounds := image.Rect(padX, padY, padX+srcBounds.Dx(), padY+srcBounds.Dy())
|
|
|
|
dst := image.NewRGBA(newBounds)
|
|
draw.Draw(dst, fillBounds, img, srcBounds.Min, draw.Src)
|
|
|
|
return dst
|
|
}
|
|
|
|
func extend(img image.Image, padX, padY int) *image.RGBA {
|
|
dst := noFill(img, padX, padY)
|
|
paddedW, paddedH := dst.Bounds().Dx(), dst.Bounds().Dy()
|
|
|
|
parallel.Line(paddedH, func(start, end int) {
|
|
for y := start; y < end; y++ {
|
|
iy := y
|
|
if iy < padY {
|
|
iy = padY
|
|
} else if iy >= paddedH-padY {
|
|
iy = paddedH - padY - 1
|
|
}
|
|
|
|
for x := 0; x < paddedW; x++ {
|
|
ix := x
|
|
if ix < padX {
|
|
ix = padX
|
|
} else if x >= paddedW-padX {
|
|
ix = paddedW - padX - 1
|
|
} else if iy == y {
|
|
// This only enters if we are not in a y-padded area or
|
|
// x-padded area, so nothing to extend here.
|
|
// So simply jump to the next padded-x index.
|
|
x = paddedW - padX - 1
|
|
continue
|
|
}
|
|
|
|
dstPos := y*dst.Stride + x*4
|
|
edgePos := iy*dst.Stride + ix*4
|
|
|
|
dst.Pix[dstPos+0] = dst.Pix[edgePos+0]
|
|
dst.Pix[dstPos+1] = dst.Pix[edgePos+1]
|
|
dst.Pix[dstPos+2] = dst.Pix[edgePos+2]
|
|
dst.Pix[dstPos+3] = dst.Pix[edgePos+3]
|
|
}
|
|
}
|
|
})
|
|
|
|
return dst
|
|
}
|
|
|
|
func wrap(img image.Image, padX, padY int) *image.RGBA {
|
|
dst := noFill(img, padX, padY)
|
|
paddedW, paddedH := dst.Bounds().Dx(), dst.Bounds().Dy()
|
|
|
|
parallel.Line(paddedH, func(start, end int) {
|
|
for y := start; y < end; y++ {
|
|
iy := y
|
|
if iy < padY {
|
|
iy = (paddedH - padY) - ((padY - y) % (paddedH - padY*2))
|
|
} else if iy >= paddedH-padY {
|
|
iy = padY - ((padY - y) % (paddedH - padY*2))
|
|
}
|
|
|
|
for x := 0; x < paddedW; x++ {
|
|
ix := x
|
|
if ix < padX {
|
|
ix = (paddedW - padX) - ((padX - x) % (paddedW - padX*2))
|
|
} else if ix >= paddedW-padX {
|
|
ix = padX - ((padX - x) % (paddedW - padX*2))
|
|
} else if iy == y {
|
|
// This only enters if we are not in a y-padded area or
|
|
// x-padded area, so nothing to extend here.
|
|
// So simply jump to the next padded-x index.
|
|
x = paddedW - padX - 1
|
|
continue
|
|
}
|
|
|
|
dstPos := y*dst.Stride + x*4
|
|
edgePos := iy*dst.Stride + ix*4
|
|
|
|
dst.Pix[dstPos+0] = dst.Pix[edgePos+0]
|
|
dst.Pix[dstPos+1] = dst.Pix[edgePos+1]
|
|
dst.Pix[dstPos+2] = dst.Pix[edgePos+2]
|
|
dst.Pix[dstPos+3] = dst.Pix[edgePos+3]
|
|
}
|
|
}
|
|
})
|
|
|
|
return dst
|
|
}
|