xref: /aosp_15_r20/external/zopfli/go/zopflipng/zopflipng.go (revision e47783fd9ac7e78d0523d35be12ee382df490d63)
1// Copyright 2019 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14package zopflipng
15
16import (
17	"fmt"
18)
19
20/*
21#cgo LDFLAGS: -lzopflipng -lzopfli -lstdc++ -lm
22#include <stdlib.h>
23#include <string.h>
24#include "zopflipng_lib.h"
25*/
26import "C"
27import "unsafe"
28
29// Options allows overriding of some internal parameters.
30type Options struct {
31	LossyTransparent   bool
32	Lossy8bit          bool
33	NumIterations      int
34	NumIterationsLarge int
35}
36
37// NewOptions creates an options struct with the default parameters.
38func NewOptions() *Options {
39	ret := &Options{
40		LossyTransparent:   false,
41		Lossy8bit:          false,
42		NumIterations:      15,
43		NumIterationsLarge: 5,
44	}
45	return ret
46}
47
48// Compress recompresses a PNG using Zopfli.
49func Compress(inputSlice []byte) ([]byte, error) {
50	return CompressWithOptions(inputSlice, NewOptions())
51}
52
53// CompressWithOptions allows overriding some internal parameters.
54func CompressWithOptions(inputSlice []byte, options *Options) ([]byte, error) {
55	cOptions := createCOptions(options)
56	input := (*C.uchar)(unsafe.Pointer(&inputSlice[0]))
57	inputSize := (C.size_t)(len(inputSlice))
58	var compressed *C.uchar
59	var compressedLength C.size_t
60	errCode := int(C.CZopfliPNGOptimize(input, inputSize, &cOptions, 0, &compressed, &compressedLength))
61	defer C.free(unsafe.Pointer(compressed))
62	if errCode != 0 {
63		return nil, fmt.Errorf("ZopfliPng failed with code: %d", errCode)
64	}
65
66	result := make([]byte, compressedLength)
67	C.memmove(unsafe.Pointer(&result[0]), unsafe.Pointer(compressed), compressedLength)
68	return result, nil
69}
70
71func createCOptions(options *Options) C.struct_CZopfliPNGOptions {
72	var cOptions C.struct_CZopfliPNGOptions
73	C.CZopfliPNGSetDefaults(&cOptions)
74	cOptions.lossy_transparent = boolToInt(options.LossyTransparent)
75	cOptions.lossy_8bit = boolToInt(options.Lossy8bit)
76	cOptions.num_iterations = C.int(options.NumIterations)
77	cOptions.num_iterations_large = C.int(options.NumIterationsLarge)
78	return cOptions
79}
80
81func boolToInt(b bool) C.int {
82	if b {
83		return C.int(1)
84	}
85	return C.int(0)
86}
87