stbi: add image writing functions (#12754)
parent
a19dd36473
commit
7a0b63e795
|
@ -561,6 +561,7 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const ch
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
|
|
||||||
#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR)
|
#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR)
|
||||||
#include <math.h> // ldexp, pow
|
#include <math.h> // ldexp, pow
|
||||||
#endif
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,6 @@
|
||||||
|
/*
|
||||||
|
* stbi set globals var functions
|
||||||
|
*/
|
||||||
|
void set_png_compression_level(int level);
|
||||||
|
void write_force_png_filter(int level);
|
||||||
|
void write_tga_with_rle(int level);
|
|
@ -1,3 +1,22 @@
|
||||||
|
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
#include "stb_image.h"
|
#include "stb_image.h"
|
||||||
|
#include "stb_image_write.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
void set_png_compression_level(int level);
|
||||||
|
void write_force_png_filter(int level);
|
||||||
|
void write_tga_with_rle(int level);
|
||||||
|
*/
|
||||||
|
|
||||||
|
void set_png_compression_level(int level) {
|
||||||
|
stbi_write_png_compression_level = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_force_png_filter(int level){
|
||||||
|
stbi_write_force_png_filter = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_tga_with_rle(int level) {
|
||||||
|
stbi_write_tga_with_rle = level;
|
||||||
|
}
|
|
@ -6,6 +6,8 @@ module stbi
|
||||||
|
|
||||||
#flag -I @VEXEROOT/thirdparty/stb_image
|
#flag -I @VEXEROOT/thirdparty/stb_image
|
||||||
#include "stb_image.h"
|
#include "stb_image.h"
|
||||||
|
#include "stb_image_write.h"
|
||||||
|
#include "stb_v_header.h"
|
||||||
#flag @VEXEROOT/thirdparty/stb_image/stbi.o
|
#flag @VEXEROOT/thirdparty/stb_image/stbi.o
|
||||||
|
|
||||||
pub struct Image {
|
pub struct Image {
|
||||||
|
@ -18,20 +20,71 @@ pub mut:
|
||||||
ext string
|
ext string
|
||||||
}
|
}
|
||||||
|
|
||||||
fn C.stbi_load(filename &char, x &int, y &int, channels_in_file &int, desired_channels int) &byte
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
fn C.stbi_load_from_file(f voidptr, x &int, y &int, channels_in_file &int, desired_channels int) &byte
|
// Configuration functions
|
||||||
|
//
|
||||||
fn C.stbi_load_from_memory(buffer &byte, len int, x &int, y &int, channels_in_file &int, desired_channels int) &byte
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
fn C.stbi_image_free(retval_from_stbi_load &byte)
|
|
||||||
|
|
||||||
fn C.stbi_set_flip_vertically_on_load(should_flip int)
|
fn C.stbi_set_flip_vertically_on_load(should_flip int)
|
||||||
|
fn C.stbi_flip_vertically_on_write(flag int)
|
||||||
|
fn C.set_png_compression_level(level int)
|
||||||
|
fn C.write_force_png_filter(level int)
|
||||||
|
fn C.write_tga_with_rle(level int)
|
||||||
|
|
||||||
fn init() {
|
pub fn set_flip_vertically_on_load(val bool) {
|
||||||
set_flip_vertically_on_load(false)
|
C.stbi_set_flip_vertically_on_load(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_flip_vertically_on_write(val bool) {
|
||||||
|
C.stbi_flip_vertically_on_write(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
// set_png_compression_level set the PNG compression level during the writing process
|
||||||
|
// defaults to 8; set to higher for more compression
|
||||||
|
pub fn set_png_compression_level(level int) {
|
||||||
|
C.set_png_compression_level(level)
|
||||||
|
}
|
||||||
|
|
||||||
|
// write_force_png_filter defaults to -1; set to 0..5 to force a filter mode
|
||||||
|
// the filter algorithms that can be applied before compression. The purpose of these filters is to prepare the image data for optimum compression.
|
||||||
|
// Type Name
|
||||||
|
//
|
||||||
|
// 0 None
|
||||||
|
// 1 Sub
|
||||||
|
// 2 Up
|
||||||
|
// 3 Average
|
||||||
|
// 4 Paeth
|
||||||
|
pub fn write_force_png_filter(level int) {
|
||||||
|
C.write_force_png_filter(level)
|
||||||
|
}
|
||||||
|
|
||||||
|
// stbi_write_tga_with_rle enable/disable the TGA RLE during the writing process
|
||||||
|
// defaults to true; set to false to disable RLE in tga
|
||||||
|
pub fn write_tga_with_rle(flag bool) {
|
||||||
|
C.write_tga_with_rle(if flag { 1 } else { 0 })
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Utility functions
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
fn C.stbi_image_free(retval_from_stbi_load &byte)
|
||||||
|
|
||||||
|
pub fn (img &Image) free() {
|
||||||
|
C.stbi_image_free(img.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Load functions
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
fn C.stbi_load(filename &char, x &int, y &int, channels_in_file &int, desired_channels int) &byte
|
||||||
|
fn C.stbi_load_from_file(f voidptr, x &int, y &int, channels_in_file &int, desired_channels int) &byte
|
||||||
|
fn C.stbi_load_from_memory(buffer &byte, len int, x &int, y &int, channels_in_file &int, desired_channels int) &byte
|
||||||
|
|
||||||
|
// load load an image from a path
|
||||||
pub fn load(path string) ?Image {
|
pub fn load(path string) ?Image {
|
||||||
ext := path.all_after_last('.')
|
ext := path.all_after_last('.')
|
||||||
mut res := Image{
|
mut res := Image{
|
||||||
|
@ -48,11 +101,12 @@ pub fn load(path string) ?Image {
|
||||||
res.nr_channels = 4
|
res.nr_channels = 4
|
||||||
}
|
}
|
||||||
if isnil(res.data) {
|
if isnil(res.data) {
|
||||||
return error('stbi image failed to load from "$path"')
|
return error('stbi_image failed to load from "$path"')
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// load_from_memory load an image from a memory buffer
|
||||||
pub fn load_from_memory(buf &byte, bufsize int) ?Image {
|
pub fn load_from_memory(buf &byte, bufsize int) ?Image {
|
||||||
mut res := Image{
|
mut res := Image{
|
||||||
ok: true
|
ok: true
|
||||||
|
@ -62,26 +116,58 @@ pub fn load_from_memory(buf &byte, bufsize int) ?Image {
|
||||||
res.data = C.stbi_load_from_memory(buf, bufsize, &res.width, &res.height, &res.nr_channels,
|
res.data = C.stbi_load_from_memory(buf, bufsize, &res.width, &res.height, &res.nr_channels,
|
||||||
flag)
|
flag)
|
||||||
if isnil(res.data) {
|
if isnil(res.data) {
|
||||||
return error('stbi image failed to load from memory')
|
return error('stbi_image failed to load from memory')
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (img &Image) free() {
|
//-----------------------------------------------------------------------------
|
||||||
C.stbi_image_free(img.data)
|
//
|
||||||
|
// Write functions
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
fn C.stbi_write_png(filename &char, w int, h int, comp int, buffer &byte, stride_in_bytes int) int
|
||||||
|
fn C.stbi_write_bmp(filename &char, w int, h int, comp int, buffer &byte) int
|
||||||
|
fn C.stbi_write_tga(filename &char, w int, h int, comp int, buffer &byte) int
|
||||||
|
fn C.stbi_write_jpg(filename &char, w int, h int, comp int, buffer &byte, quality int) int
|
||||||
|
|
||||||
|
// fn C.stbi_write_hdr(filename &char, w int, h int, comp int, buffer &byte) int // buffer &byte => buffer &f32
|
||||||
|
|
||||||
|
// stbi_write_png write on path a PNG file
|
||||||
|
// row_stride_in_bytes is usually equal to: w * comp
|
||||||
|
pub fn stbi_write_png(path string, w int, h int, comp int, buf &byte, row_stride_in_bytes int) ? {
|
||||||
|
if 0 == C.stbi_write_png(&char(path.str), w, h, comp, buf, row_stride_in_bytes) {
|
||||||
|
return error('stbi_image failed to write png file to "$path"')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// stbi_write_png write on path a BMP file
|
||||||
|
pub fn stbi_write_bmp(path string, w int, h int, comp int, buf &byte) ? {
|
||||||
|
if 0 == C.stbi_write_bmp(&char(path.str), w, h, comp, buf) {
|
||||||
|
return error('stbi_image failed to write bmp file to "$path"')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// stbi_write_png write on path a TGA file
|
||||||
|
pub fn stbi_write_tga(path string, w int, h int, comp int, buf &byte) ? {
|
||||||
|
if 0 == C.stbi_write_tga(&char(path.str), w, h, comp, buf) {
|
||||||
|
return error('stbi_image failed to write tga file to "$path"')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// stbi_write_png write on path a JPG file
|
||||||
|
// quality select teh compression quality of the JPG
|
||||||
|
// quality is between 1 and 100. Higher quality looks better but results in a bigger image.
|
||||||
|
pub fn stbi_write_jpg(path string, w int, h int, comp int, buf &byte, quality int) ? {
|
||||||
|
if 0 == C.stbi_write_jpg(&char(path.str), w, h, comp, buf, quality) {
|
||||||
|
return error('stbi_image failed to write jpg file to "$path"')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
pub fn (img Image) tex_image_2d() {
|
pub fn stbi_write_hdr(path string, w int, h int, comp int, buf &byte) ? {
|
||||||
mut rgb_flag := C.GL_RGB
|
if 0 == C.stbi_write_hdr(&char(path.str), w , h , comp , buf){
|
||||||
if img.ext == 'png' {
|
return error('stbi_image failed to write hdr file to "$path"')
|
||||||
rgb_flag = C.GL_RGBA
|
|
||||||
}
|
}
|
||||||
C.glTexImage2D(C.GL_TEXTURE_2D, 0, rgb_flag, img.width, img.height, 0,
|
|
||||||
rgb_flag, C.GL_UNSIGNED_BYTE, img.data)
|
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pub fn set_flip_vertically_on_load(val bool) {
|
|
||||||
C.stbi_set_flip_vertically_on_load(val)
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
import os
|
||||||
|
import stbi
|
||||||
|
|
||||||
|
fn test_stbi_read_write() {
|
||||||
|
vroot := @VEXEROOT
|
||||||
|
path := os.join_path(vroot, 'examples', 'assets', 'logo.png')
|
||||||
|
println('Source path: $path')
|
||||||
|
d_s := stbi.load(path) or { panic(err) }
|
||||||
|
println('Image source data:\n $d_s')
|
||||||
|
|
||||||
|
out_path := os.join_path(os.temp_dir(), 'test.png')
|
||||||
|
println('Out path: $out_path')
|
||||||
|
stbi.stbi_write_png(out_path, d_s.width, d_s.height, 4, d_s.data, d_s.width * 4) or {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d_d := stbi.load(out_path) or { panic(err) }
|
||||||
|
println('Image dest data:\n $d_d')
|
||||||
|
|
||||||
|
assert d_s.width == d_d.width
|
||||||
|
assert d_s.height == d_d.height
|
||||||
|
assert d_s.nr_channels == d_d.nr_channels
|
||||||
|
|
||||||
|
mut v_s := &u32(d_s.data)
|
||||||
|
mut v_d := &u32(d_d.data)
|
||||||
|
mut delta := i64(0)
|
||||||
|
for index in 0 .. (d_d.width * d_d.width) {
|
||||||
|
unsafe {
|
||||||
|
delta += v_s[index] - v_d[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert 0 == delta
|
||||||
|
os.rm(out_path) or {}
|
||||||
|
}
|
Loading…
Reference in New Issue