1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

stbi: add image writing functions (#12754)

This commit is contained in:
penguindark 2021-12-07 23:31:37 +01:00 committed by GitHub
parent a19dd36473
commit 7a0b63e795
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 1901 additions and 25 deletions

View File

@ -561,6 +561,7 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const ch
#include <string.h>
#include <limits.h>
#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR)
#include <math.h> // ldexp, pow
#endif

1730
thirdparty/stb_image/stb_image_write.h vendored Normal file

File diff suppressed because it is too large Load Diff

6
thirdparty/stb_image/stb_v_header.h vendored Normal file
View File

@ -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);

View File

@ -1,3 +1,22 @@
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#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;
}

View File

@ -6,6 +6,8 @@ module stbi
#flag -I @VEXEROOT/thirdparty/stb_image
#include "stb_image.h"
#include "stb_image_write.h"
#include "stb_v_header.h"
#flag @VEXEROOT/thirdparty/stb_image/stbi.o
pub struct Image {
@ -18,20 +20,71 @@ pub mut:
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
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)
//-----------------------------------------------------------------------------
//
// Configuration functions
//
//-----------------------------------------------------------------------------
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() {
set_flip_vertically_on_load(false)
pub fn set_flip_vertically_on_load(val bool) {
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 {
ext := path.all_after_last('.')
mut res := Image{
@ -48,11 +101,12 @@ pub fn load(path string) ?Image {
res.nr_channels = 4
}
if isnil(res.data) {
return error('stbi image failed to load from "$path"')
return error('stbi_image failed to load from "$path"')
}
return res
}
// load_from_memory load an image from a memory buffer
pub fn load_from_memory(buf &byte, bufsize int) ?Image {
mut res := Image{
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,
flag)
if isnil(res.data) {
return error('stbi image failed to load from memory')
return error('stbi_image failed to load from memory')
}
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() {
mut rgb_flag := C.GL_RGB
if img.ext == 'png' {
rgb_flag = C.GL_RGBA
pub fn stbi_write_hdr(path string, w int, h int, comp int, buf &byte) ? {
if 0 == C.stbi_write_hdr(&char(path.str), w , h , comp , buf){
return error('stbi_image failed to write hdr file to "$path"')
}
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)
}

34
vlib/stbi/stbi_test.v Normal file
View File

@ -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 {}
}