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