Documentation
¶
Overview ¶
Example (Batch) ¶
package main
import (
"context"
"fmt"
"image"
watermark "github.com/yyyoichi/watermark_zero"
"github.com/yyyoichi/watermark_zero/mark"
)
func main() {
ctx := context.Background()
img := image.NewGray(image.Rect(0, 0, 200, 200))
opts := []watermark.Option{
watermark.WithBlockShape(4, 4),
watermark.WithD1D2(21, 11),
}
batch := watermark.NewBatch(img)
for _, m := range []string{"Hello!", "こんにちは!"} {
mark := mark.NewString(m)
markedImg, _ := batch.Embed(ctx, mark, opts...)
extractedMark, _ := watermark.Extract(ctx, markedImg, mark, opts...)
fmt.Println(extractedMark.DecodeToString())
}
}
Output: Hello! こんにちは!
Example (MismatchedMarkOptions) ¶
package main
import (
"context"
"fmt"
"image"
watermark "github.com/yyyoichi/watermark_zero"
"github.com/yyyoichi/watermark_zero/mark"
)
func main() {
ctx := context.Background()
img := image.NewGray(image.Rect(0, 0, 200, 200))
w, _ := watermark.New(
watermark.WithBlockShape(4, 4),
watermark.WithD1D2(21, 11),
)
// Embed a mark with Golay encoding (default seed)
embedMark := mark.NewString("Test")
markedImg, _ := w.Embed(ctx, img, embedMark)
// Try to extract with different options (WithoutECC)
wrongExtractMark1 := mark.NewExtract(embedMark.ExtractSize(), mark.WithoutECC())
wrongDecoded1, _ := w.Extract(ctx, markedImg, wrongExtractMark1)
result1 := wrongDecoded1.DecodeToString()
fmt.Printf("WithoutECC matches 'Test': %v\n", result1 == "Test")
// Try to extract with different seed
wrongExtractMark2 := mark.NewExtract(embedMark.ExtractSize(), mark.WithGolay(99999))
wrongDecoded2, _ := w.Extract(ctx, markedImg, wrongExtractMark2)
result2 := wrongDecoded2.DecodeToString()
fmt.Printf("Different seed matches 'Test': %v\n", result2 == "Test")
// Extract with correct options (same as embedding)
correctExtractMark := mark.NewExtract(embedMark.ExtractSize()) // Uses default Golay encoding and default seed
correctDecoded, _ := w.Extract(ctx, markedImg, correctExtractMark)
result3 := correctDecoded.DecodeToString()
fmt.Printf("Correct options matches 'Test': %v\n", result3 == "Test")
}
Output: WithoutECC matches 'Test': false Different seed matches 'Test': false Correct options matches 'Test': true
Example (Watermark) ¶
package main
import (
"context"
"fmt"
"image"
watermark "github.com/yyyoichi/watermark_zero"
"github.com/yyyoichi/watermark_zero/mark"
)
func main() {
ctx := context.Background()
img := image.NewGray(image.Rect(0, 0, 200, 200))
// Initialize watermark processor with default settings
w, _ := watermark.New(
watermark.WithBlockShape(4, 4),
watermark.WithD1D2(21, 11),
)
// Define a bit sequence to embed
m := mark.NewString("Test-Mark")
// Embed the watermark
markedImg, _ := w.Embed(ctx, img, m)
// Extract the watermark
extractedMark, _ := w.Extract(ctx, markedImg, m)
fmt.Println(extractedMark.DecodeToString())
exM := mark.NewExtract(m.ExtractSize())
extractedMark, _ = w.Extract(ctx, markedImg, exM)
fmt.Println(extractedMark.DecodeToString())
}
Output: Test-Mark Test-Mark
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var (
ErrTooSmallImage = errors.New("image is too small for embedding or extracting")
)
Functions ¶
Types ¶
type Batch ¶ added in v0.2.0
type Batch struct {
// contains filtered or unexported fields
}
Batch enables efficient multiple watermark operations on a single image by caching intermediate computation results (wavelets and DCT).
func NewBatch ¶ added in v0.2.0
NewBatch creates a new Batch instance and pre-computes wavelet transforms and initializes DCT cache for the given image.
type EmbedMark ¶ added in v0.2.0
type EmbedMark interface {
// GetBit returns the bit value at the specified position as a float64.
GetBit(at int) float64
MarkCore
}
EmbedMark defines the interface for embedding watermarks. It provides methods to retrieve mark bits for embedding into media.
type ExtractMark ¶ added in v0.2.0
type ExtractMark interface {
// NewDecoder receives the extracted bit sequence and initializes a MarkDecoder.
NewDecoder([]bool) MarkDecoder
MarkCore
}
ExtractMark defines the interface for extracting watermarks. It provides methods to initialize a decoder from extracted bit sequences.
type MarkCore ¶ added in v0.2.0
type MarkCore interface {
// Len returns the bit length of the encoded mark after applying error correction.
Len() int
// ExtractSize returns the bit length required for watermark extraction.
ExtractSize() int
}
MarkCore defines the core interface for mark operations. It provides methods to get the encoded mark length and the extraction size.
type MarkDecoder ¶ added in v0.2.0
type MarkDecoder interface {
// DecodeToBytes decodes the watermark data and returns it as a byte slice.
DecodeToBytes() []byte
// DecodeToString decodes the watermark data and returns it as a string.
DecodeToString() string
// DecodeToBools decodes the watermark data and returns it as a boolean slice.
DecodeToBools() []bool
}
MarkDecoder defines the interface for decoding extracted watermark data. It provides methods to convert the decoded data into various formats.
func Extract ¶ added in v0.2.0
func Extract(ctx context.Context, src image.Image, mark ExtractMark, opts ...Option) (MarkDecoder, error)
Extract extracts a bit sequence from an image with the specified options. This is a convenience function that creates a Watermark instance and calls its Extract method.
type Option ¶
func WithBlockShape ¶
WithBlockShape divides the image into blocks of the specified size for processing. For example, for a 600x480 image with an 8x6 block shape, it creates 75 horizontal and 80 vertical blocks.
Block shapes must be specified with even numbers, with a minimum size of 4x4. If odd numbers are provided, they are automatically rounded up to the next even number. If values smaller than 4 are provided, they are set to 4.
type Watermark ¶
type Watermark struct {
// contains filtered or unexported fields
}
func New ¶
New initializes a watermark processing structure. The blockShape and watermark coefficients d1, d2 can be optionally specified. For default values, refer to the init function.
func (*Watermark) Embed ¶
func (w *Watermark) Embed(ctx context.Context, src image.Image, mark EmbedMark) (image.Image, error)
Embed embeds a bit sequence into an image.
Process:
- Converts the image to YUV color channels.
- Applies Haar wavelet transform to each channel.
- Divides the low-frequency region (cA) of each channel into blocks.
- Embeds one bit per block using Discrete Cosine Transform and SVD.
- Applies inverse transforms.
- Reconstructs the image.
Returns an error if the image is too small for the bit sequence to be embedded.
func (*Watermark) Extract ¶
func (w *Watermark) Extract(ctx context.Context, src image.Image, mark ExtractMark) (MarkDecoder, error)
Extract extracts a bit sequence from an image.
Process:
- Converts the image to YUV color channels.
- Applies Haar wavelet transform to each channel.
- Divides the low-frequency region (cA) of each channel into blocks.
- Extracts one bit per block using Discrete Cosine Transform and SVD.
- Determines boolean values using k-means clustering on the average values of each block's bits.
Returns an error if the image is too small for the expected bit sequence length.


