1//go:build cgo
2
3package clib
4
5/*
6#cgo LDFLAGS: -lm
7#include "imgconv.h"
8#include <stdlib.h>
9*/
10import "C"
11import "unsafe"
12
13// DecodeToPNG takes raw image bytes (JPEG, PNG, BMP, GIF, etc.) and returns
14// PNG-encoded bytes along with image dimensions. Uses stb_image for decoding
15// and stb_image_write for PNG encoding in C, which is faster than Go's
16// image stdlib for large images.
17func DecodeToPNG(data []byte) (ImageConvertResult, bool) {
18 if len(data) == 0 {
19 return ImageConvertResult{}, false
20 }
21
22 cData := C.CBytes(data)
23 defer C.free(cData)
24
25 result := C.decode_to_png((*C.uchar)(cData), C.size_t(len(data)))
26 if result.ok == 0 {
27 return ImageConvertResult{}, false
28 }
29 defer C.free_image_result(&result) //nolint:gocritic
30
31 pngData := C.GoBytes(unsafe.Pointer(result.png_data), C.int(result.png_len))
32
33 return ImageConvertResult{
34 PNGData: pngData,
35 Width: int(result.width),
36 Height: int(result.height),
37 }, true
38}
39
40// ImageDimensions returns the width and height of an image without fully
41// decoding pixel data. This is faster than DecodeToPNG when you only need
42// the dimensions (e.g. to calculate terminal row count).
43func ImageDimensions(data []byte) (width, height int, ok bool) {
44 if len(data) == 0 {
45 return 0, 0, false
46 }
47
48 cData := C.CBytes(data)
49 defer C.free(cData)
50
51 var cw, ch C.int
52 ret := C.image_dimensions((*C.uchar)(cData), C.size_t(len(data)), &cw, &ch)
53 if ret == 0 {
54 return 0, 0, false
55 }
56 return int(cw), int(ch), true
57}