mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
[pbm] Normalize some errors, correct .depth
This commit is contained in:
+25
-16
@@ -45,7 +45,7 @@ Image :: struct {
|
|||||||
width: int,
|
width: int,
|
||||||
height: int,
|
height: int,
|
||||||
channels: int,
|
channels: int,
|
||||||
depth: int,
|
depth: int, // Channel depth in bits, typically 8 or 16
|
||||||
pixels: bytes.Buffer,
|
pixels: bytes.Buffer,
|
||||||
/*
|
/*
|
||||||
Some image loaders/writers can return/take an optional background color.
|
Some image loaders/writers can return/take an optional background color.
|
||||||
@@ -141,13 +141,14 @@ Option :: enum {
|
|||||||
alpha_drop_if_present, // Unimplemented for QOI. Returns error.
|
alpha_drop_if_present, // Unimplemented for QOI. Returns error.
|
||||||
alpha_premultiply, // Unimplemented for QOI. Returns error.
|
alpha_premultiply, // Unimplemented for QOI. Returns error.
|
||||||
blend_background, // Ignored for non-PNG formats
|
blend_background, // Ignored for non-PNG formats
|
||||||
|
|
||||||
// Unimplemented
|
// Unimplemented
|
||||||
do_not_expand_grayscale,
|
do_not_expand_grayscale,
|
||||||
do_not_expand_indexed,
|
do_not_expand_indexed,
|
||||||
do_not_expand_channels,
|
do_not_expand_channels,
|
||||||
|
|
||||||
// SAVE OPTIONS
|
// SAVE OPTIONS
|
||||||
qoi_all_channels_linear, // QOI, informative info. If not set, defaults to sRGB with linear alpha.
|
qoi_all_channels_linear, // QOI, informative only. If not set, defaults to sRGB with linear alpha.
|
||||||
}
|
}
|
||||||
Options :: distinct bit_set[Option]
|
Options :: distinct bit_set[Option]
|
||||||
|
|
||||||
@@ -166,12 +167,29 @@ Error :: union #shared_nil {
|
|||||||
|
|
||||||
General_Image_Error :: enum {
|
General_Image_Error :: enum {
|
||||||
None = 0,
|
None = 0,
|
||||||
|
// File I/O
|
||||||
|
Unable_To_Read_File,
|
||||||
|
Unable_To_Write_File,
|
||||||
|
|
||||||
|
// Invalid
|
||||||
|
Invalid_Signature,
|
||||||
|
Invalid_Input_Image,
|
||||||
|
Image_Dimensions_Too_Large,
|
||||||
Invalid_Image_Dimensions,
|
Invalid_Image_Dimensions,
|
||||||
Invalid_Number_Of_Channels,
|
Invalid_Number_Of_Channels,
|
||||||
Image_Dimensions_Too_Large,
|
|
||||||
Image_Does_Not_Adhere_to_Spec,
|
Image_Does_Not_Adhere_to_Spec,
|
||||||
Invalid_Input_Image,
|
Invalid_Image_Depth,
|
||||||
|
Invalid_Bit_Depth,
|
||||||
|
Invalid_Color_Space,
|
||||||
|
|
||||||
|
// More data than pixels to decode into, for example.
|
||||||
|
Corrupt,
|
||||||
|
|
||||||
|
// Output buffer is the wrong size
|
||||||
Invalid_Output,
|
Invalid_Output,
|
||||||
|
|
||||||
|
// Allocation
|
||||||
|
Unable_To_Allocate_Or_Resize,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -201,8 +219,6 @@ Netpbm_Error :: enum {
|
|||||||
None = 0,
|
None = 0,
|
||||||
|
|
||||||
// reading
|
// reading
|
||||||
File_Not_Readable,
|
|
||||||
Invalid_Signature,
|
|
||||||
Invalid_Header_Token_Character,
|
Invalid_Header_Token_Character,
|
||||||
Incomplete_Header,
|
Incomplete_Header,
|
||||||
Invalid_Header_Value,
|
Invalid_Header_Value,
|
||||||
@@ -212,9 +228,7 @@ Netpbm_Error :: enum {
|
|||||||
Invalid_Buffer_Value,
|
Invalid_Buffer_Value,
|
||||||
|
|
||||||
// writing
|
// writing
|
||||||
File_Not_Writable,
|
|
||||||
Invalid_Format,
|
Invalid_Format,
|
||||||
Invalid_Image_Depth,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -222,7 +236,6 @@ Netpbm_Error :: enum {
|
|||||||
*/
|
*/
|
||||||
PNG_Error :: enum {
|
PNG_Error :: enum {
|
||||||
None = 0,
|
None = 0,
|
||||||
Invalid_PNG_Signature,
|
|
||||||
IHDR_Not_First_Chunk,
|
IHDR_Not_First_Chunk,
|
||||||
IHDR_Corrupt,
|
IHDR_Corrupt,
|
||||||
IDAT_Missing,
|
IDAT_Missing,
|
||||||
@@ -338,14 +351,10 @@ PNG_Interlace_Method :: enum u8 {
|
|||||||
*/
|
*/
|
||||||
QOI_Error :: enum {
|
QOI_Error :: enum {
|
||||||
None = 0,
|
None = 0,
|
||||||
Invalid_QOI_Signature,
|
|
||||||
Invalid_Bit_Depth, // QOI supports only 8-bit images, error only returned from writer.
|
|
||||||
Invalid_Color_Space, // QOI allows 0 = sRGB or 1 = linear.
|
|
||||||
Corrupt, // More data than pixels to decode into, for example.
|
|
||||||
Missing_Or_Corrupt_Trailer, // Image seemed to have decoded okay, but trailer is missing or corrupt.
|
Missing_Or_Corrupt_Trailer, // Image seemed to have decoded okay, but trailer is missing or corrupt.
|
||||||
}
|
}
|
||||||
|
|
||||||
QOI_Magic :: u32be(0x716f6966) // "qoif"
|
QOI_Magic :: u32be(0x716f6966) // "qoif"
|
||||||
|
|
||||||
QOI_Color_Space :: enum u8 {
|
QOI_Color_Space :: enum u8 {
|
||||||
sRGB = 0,
|
sRGB = 0,
|
||||||
@@ -1170,10 +1179,10 @@ write_bytes :: proc(buf: ^bytes.Buffer, data: []u8) -> (err: compress.General_Er
|
|||||||
return nil
|
return nil
|
||||||
} else if len(data) == 1 {
|
} else if len(data) == 1 {
|
||||||
if bytes.buffer_write_byte(buf, data[0]) != nil {
|
if bytes.buffer_write_byte(buf, data[0]) != nil {
|
||||||
return compress.General_Error.Resize_Failed
|
return .Resize_Failed
|
||||||
}
|
}
|
||||||
} else if n, _ := bytes.buffer_write(buf, data); n != len(data) {
|
} else if n, _ := bytes.buffer_write(buf, data); n != len(data) {
|
||||||
return compress.General_Error.Resize_Failed
|
return .Resize_Failed
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -9,8 +9,6 @@ import "core:strconv"
|
|||||||
import "core:strings"
|
import "core:strings"
|
||||||
import "core:unicode"
|
import "core:unicode"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Image :: image.Image
|
Image :: image.Image
|
||||||
Format :: image.Netpbm_Format
|
Format :: image.Netpbm_Format
|
||||||
Header :: image.Netpbm_Header
|
Header :: image.Netpbm_Header
|
||||||
@@ -18,8 +16,6 @@ Info :: image.Netpbm_Info
|
|||||||
Error :: image.Error
|
Error :: image.Error
|
||||||
Format_Error :: image.Netpbm_Error
|
Format_Error :: image.Netpbm_Error
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Formats :: bit_set[Format]
|
Formats :: bit_set[Format]
|
||||||
PBM :: Formats{.P1, .P4}
|
PBM :: Formats{.P1, .P4}
|
||||||
PGM :: Formats{.P2, .P5}
|
PGM :: Formats{.P2, .P5}
|
||||||
@@ -30,14 +26,12 @@ PFM :: Formats{.Pf, .PF}
|
|||||||
ASCII :: Formats{.P1, .P2, .P3}
|
ASCII :: Formats{.P1, .P2, .P3}
|
||||||
BINARY :: Formats{.P4, .P5, .P6} + PAM + PFM
|
BINARY :: Formats{.P4, .P5, .P6} + PAM + PFM
|
||||||
|
|
||||||
|
load :: proc {
|
||||||
|
load_from_file,
|
||||||
read :: proc {
|
load_from_buffer,
|
||||||
read_from_file,
|
|
||||||
read_from_buffer,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
read_from_file :: proc(filename: string, allocator := context.allocator) -> (img: Image, err: Error) {
|
load_from_file :: proc(filename: string, allocator := context.allocator) -> (img: Image, err: Error) {
|
||||||
context.allocator = allocator
|
context.allocator = allocator
|
||||||
|
|
||||||
data, ok := os.read_entire_file(filename); defer delete(data)
|
data, ok := os.read_entire_file(filename); defer delete(data)
|
||||||
@@ -49,7 +43,7 @@ read_from_file :: proc(filename: string, allocator := context.allocator) -> (img
|
|||||||
return read_from_buffer(data)
|
return read_from_buffer(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
read_from_buffer :: proc(data: []byte, allocator := context.allocator) -> (img: Image, err: Error) {
|
load_from_buffer :: proc(data: []byte, allocator := context.allocator) -> (img: Image, err: Error) {
|
||||||
context.allocator = allocator
|
context.allocator = allocator
|
||||||
|
|
||||||
header: Header; defer header_destroy(&header)
|
header: Header; defer header_destroy(&header)
|
||||||
@@ -70,14 +64,12 @@ read_from_buffer :: proc(data: []byte, allocator := context.allocator) -> (img:
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
save :: proc {
|
||||||
|
save_to_file,
|
||||||
write :: proc {
|
save_to_buffer,
|
||||||
write_to_file,
|
|
||||||
write_to_buffer,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
write_to_file :: proc(filename: string, img: Image, allocator := context.allocator) -> (err: Error) {
|
save_to_file :: proc(filename: string, img: Image, allocator := context.allocator) -> (err: Error) {
|
||||||
context.allocator = allocator
|
context.allocator = allocator
|
||||||
|
|
||||||
data: []byte; defer delete(data)
|
data: []byte; defer delete(data)
|
||||||
@@ -90,7 +82,7 @@ write_to_file :: proc(filename: string, img: Image, allocator := context.allocat
|
|||||||
return Format_Error.None
|
return Format_Error.None
|
||||||
}
|
}
|
||||||
|
|
||||||
write_to_buffer :: proc(img: Image, allocator := context.allocator) -> (buffer: []byte, err: Error) {
|
save_to_buffer :: proc(img: Image, allocator := context.allocator) -> (buffer: []byte, err: Error) {
|
||||||
context.allocator = allocator
|
context.allocator = allocator
|
||||||
|
|
||||||
info, ok := img.metadata.(^image.Netpbm_Info)
|
info, ok := img.metadata.(^image.Netpbm_Info)
|
||||||
@@ -109,12 +101,12 @@ write_to_buffer :: proc(img: Image, allocator := context.allocator) -> (buffer:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if header.format in (PNM + PAM) {
|
if header.format in (PNM + PAM) {
|
||||||
if header.maxval <= int(max(u8)) && img.depth != 1 \
|
if header.maxval <= int(max(u8)) && img.depth != 8 \
|
||||||
|| header.maxval > int(max(u8)) && header.maxval <= int(max(u16)) && img.depth != 2 {
|
|| header.maxval > int(max(u8)) && header.maxval <= int(max(u16)) && img.depth != 16 {
|
||||||
err = Format_Error.Invalid_Image_Depth
|
err = Format_Error.Invalid_Image_Depth
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else if header.format in PFM && img.depth != 4 {
|
} else if header.format in PFM && img.depth != 32 {
|
||||||
err = Format_Error.Invalid_Image_Depth
|
err = Format_Error.Invalid_Image_Depth
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -179,7 +171,7 @@ write_to_buffer :: proc(img: Image, allocator := context.allocator) -> (buffer:
|
|||||||
mem.copy(raw_data(data.buf[len(header_buf):]), raw_data(pixels), len(pixels))
|
mem.copy(raw_data(data.buf[len(header_buf):]), raw_data(pixels), len(pixels))
|
||||||
|
|
||||||
// convert from native endianness
|
// convert from native endianness
|
||||||
if img.depth == 2 {
|
if img.depth == 16 {
|
||||||
pixels := mem.slice_data_cast([]u16be, data.buf[len(header_buf):])
|
pixels := mem.slice_data_cast([]u16be, data.buf[len(header_buf):])
|
||||||
for p in &pixels {
|
for p in &pixels {
|
||||||
p = u16be(transmute(u16) p)
|
p = u16be(transmute(u16) p)
|
||||||
@@ -212,7 +204,7 @@ write_to_buffer :: proc(img: Image, allocator := context.allocator) -> (buffer:
|
|||||||
// Token ASCII
|
// Token ASCII
|
||||||
case .P2, .P3:
|
case .P2, .P3:
|
||||||
switch img.depth {
|
switch img.depth {
|
||||||
case 1:
|
case 8:
|
||||||
pixels := img.pixels.buf[:]
|
pixels := img.pixels.buf[:]
|
||||||
for y in 0 ..< img.height {
|
for y in 0 ..< img.height {
|
||||||
for x in 0 ..< img.width {
|
for x in 0 ..< img.width {
|
||||||
@@ -226,7 +218,7 @@ write_to_buffer :: proc(img: Image, allocator := context.allocator) -> (buffer:
|
|||||||
fmt.sbprint(&data, "\n")
|
fmt.sbprint(&data, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
case 2:
|
case 16:
|
||||||
pixels := mem.slice_data_cast([]u16, img.pixels.buf[:])
|
pixels := mem.slice_data_cast([]u16, img.pixels.buf[:])
|
||||||
for y in 0 ..< img.height {
|
for y in 0 ..< img.height {
|
||||||
for x in 0 ..< img.width {
|
for x in 0 ..< img.width {
|
||||||
@@ -251,8 +243,6 @@ write_to_buffer :: proc(img: Image, allocator := context.allocator) -> (buffer:
|
|||||||
return data.buf[:], Format_Error.None
|
return data.buf[:], Format_Error.None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
parse_header :: proc(data: []byte, allocator := context.allocator) -> (header: Header, length: int, err: Error) {
|
parse_header :: proc(data: []byte, allocator := context.allocator) -> (header: Header, length: int, err: Error) {
|
||||||
context.allocator = allocator
|
context.allocator = allocator
|
||||||
|
|
||||||
@@ -351,7 +341,7 @@ _parse_header_pnm :: proc(data: []byte) -> (header: Header, length: int, err: Er
|
|||||||
|
|
||||||
// set extra info
|
// set extra info
|
||||||
header.channels = 3 if header.format in PPM else 1
|
header.channels = 3 if header.format in PPM else 1
|
||||||
header.depth = 2 if header.maxval > int(max(u8)) else 1
|
header.depth = 16 if header.maxval > int(max(u8)) else 8
|
||||||
|
|
||||||
// limit checking
|
// limit checking
|
||||||
if current_field < len(header_fields) {
|
if current_field < len(header_fields) {
|
||||||
@@ -448,12 +438,11 @@ _parse_header_pam :: proc(data: []byte, allocator := context.allocator) -> (head
|
|||||||
}
|
}
|
||||||
|
|
||||||
// extra info
|
// extra info
|
||||||
header.depth = 2 if header.maxval > int(max(u8)) else 1
|
header.depth = 16 if header.maxval > int(max(u8)) else 8
|
||||||
|
|
||||||
// limit checking
|
// limit checking
|
||||||
if header.width < 1 \
|
if header.width < 1 \
|
||||||
|| header.height < 1 \
|
|| header.height < 1 \
|
||||||
|| header.depth < 1 \
|
|
||||||
|| header.maxval < 1 \
|
|| header.maxval < 1 \
|
||||||
|| header.maxval > int(max(u16)) {
|
|| header.maxval > int(max(u16)) {
|
||||||
err = Format_Error.Invalid_Header_Value
|
err = Format_Error.Invalid_Header_Value
|
||||||
@@ -484,7 +473,7 @@ _parse_header_pfm :: proc(data: []byte) -> (header: Header, length: int, err: Er
|
|||||||
}
|
}
|
||||||
|
|
||||||
// floating point
|
// floating point
|
||||||
header.depth = 4
|
header.depth = 32
|
||||||
|
|
||||||
// width
|
// width
|
||||||
field, ok = strings.fields_iterator(&field_iterator)
|
field, ok = strings.fields_iterator(&field_iterator)
|
||||||
@@ -542,8 +531,6 @@ _parse_header_pfm :: proc(data: []byte) -> (header: Header, length: int, err: Er
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
decode_image :: proc(header: Header, data: []byte, allocator := context.allocator) -> (img: Image, err: Error) {
|
decode_image :: proc(header: Header, data: []byte, allocator := context.allocator) -> (img: Image, err: Error) {
|
||||||
context.allocator = allocator
|
context.allocator = allocator
|
||||||
|
|
||||||
@@ -554,7 +541,7 @@ decode_image :: proc(header: Header, data: []byte, allocator := context.allocato
|
|||||||
depth = header.depth,
|
depth = header.depth,
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_size := img.width * img.height * img.channels * img.depth
|
buffer_size := image.compute_buffer_size(img.width, img.height, img.channels, img.depth)
|
||||||
|
|
||||||
// we can check data size for binary formats
|
// we can check data size for binary formats
|
||||||
if header.format in BINARY {
|
if header.format in BINARY {
|
||||||
@@ -615,7 +602,7 @@ decode_image :: proc(header: Header, data: []byte, allocator := context.allocato
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if img.depth == 2 {
|
if img.depth == 16 {
|
||||||
pixels := mem.slice_data_cast([]u16, img.pixels.buf[:])
|
pixels := mem.slice_data_cast([]u16, img.pixels.buf[:])
|
||||||
for p in &pixels {
|
for p in &pixels {
|
||||||
p = u16(transmute(u16be) p)
|
p = u16(transmute(u16be) p)
|
||||||
@@ -658,9 +645,9 @@ decode_image :: proc(header: Header, data: []byte, allocator := context.allocato
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch img.depth {
|
switch img.depth {
|
||||||
case 1:
|
case 8:
|
||||||
bytes.buffer_write_byte(&img.pixels, u8(value))
|
bytes.buffer_write_byte(&img.pixels, u8(value))
|
||||||
case 2:
|
case 16:
|
||||||
vb := transmute([2]u8) u16(value)
|
vb := transmute([2]u8) u16(value)
|
||||||
bytes.buffer_write(&img.pixels, vb[:])
|
bytes.buffer_write(&img.pixels, vb[:])
|
||||||
}
|
}
|
||||||
@@ -678,4 +665,4 @@ decode_image :: proc(header: Header, data: []byte, allocator := context.allocato
|
|||||||
|
|
||||||
err = Format_Error.None
|
err = Format_Error.None
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -238,7 +238,7 @@ append_chunk :: proc(list: ^[dynamic]image.PNG_Chunk, src: image.PNG_Chunk, allo
|
|||||||
append(list, c)
|
append(list, c)
|
||||||
if len(list) != length + 1 {
|
if len(list) != length + 1 {
|
||||||
// Resize during append failed.
|
// Resize during append failed.
|
||||||
return mem.Allocator_Error.Out_Of_Memory
|
return .Unable_To_Allocate_Or_Resize
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -347,7 +347,7 @@ load_from_file :: proc(filename: string, options := Options{}, allocator := cont
|
|||||||
return load_from_slice(data, options)
|
return load_from_slice(data, options)
|
||||||
} else {
|
} else {
|
||||||
img = new(Image)
|
img = new(Image)
|
||||||
return img, compress.General_Error.File_Not_Found
|
return img, .Unable_To_Read_File
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,7 +381,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
|
|||||||
|
|
||||||
signature, io_error := compress.read_data(ctx, Signature)
|
signature, io_error := compress.read_data(ctx, Signature)
|
||||||
if io_error != .None || signature != .PNG {
|
if io_error != .None || signature != .PNG {
|
||||||
return img, .Invalid_PNG_Signature
|
return img, .Invalid_Signature
|
||||||
}
|
}
|
||||||
|
|
||||||
idat: []u8
|
idat: []u8
|
||||||
@@ -747,7 +747,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
|
|||||||
dest_raw_size := compute_buffer_size(int(header.width), int(header.height), out_image_channels, 8)
|
dest_raw_size := compute_buffer_size(int(header.width), int(header.height), out_image_channels, 8)
|
||||||
t := bytes.Buffer{}
|
t := bytes.Buffer{}
|
||||||
if !resize(&t.buf, dest_raw_size) {
|
if !resize(&t.buf, dest_raw_size) {
|
||||||
return {}, mem.Allocator_Error.Out_Of_Memory
|
return {}, .Unable_To_Allocate_Or_Resize
|
||||||
}
|
}
|
||||||
|
|
||||||
i := 0; j := 0
|
i := 0; j := 0
|
||||||
@@ -828,7 +828,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
|
|||||||
dest_raw_size := compute_buffer_size(int(header.width), int(header.height), out_image_channels, 16)
|
dest_raw_size := compute_buffer_size(int(header.width), int(header.height), out_image_channels, 16)
|
||||||
t := bytes.Buffer{}
|
t := bytes.Buffer{}
|
||||||
if !resize(&t.buf, dest_raw_size) {
|
if !resize(&t.buf, dest_raw_size) {
|
||||||
return {}, mem.Allocator_Error.Out_Of_Memory
|
return {}, .Unable_To_Allocate_Or_Resize
|
||||||
}
|
}
|
||||||
|
|
||||||
p16 := mem.slice_data_cast([]u16, temp.buf[:])
|
p16 := mem.slice_data_cast([]u16, temp.buf[:])
|
||||||
@@ -1027,7 +1027,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
|
|||||||
dest_raw_size := compute_buffer_size(int(header.width), int(header.height), out_image_channels, 8)
|
dest_raw_size := compute_buffer_size(int(header.width), int(header.height), out_image_channels, 8)
|
||||||
t := bytes.Buffer{}
|
t := bytes.Buffer{}
|
||||||
if !resize(&t.buf, dest_raw_size) {
|
if !resize(&t.buf, dest_raw_size) {
|
||||||
return {}, mem.Allocator_Error.Out_Of_Memory
|
return {}, .Unable_To_Allocate_Or_Resize
|
||||||
}
|
}
|
||||||
|
|
||||||
p := mem.slice_data_cast([]u8, temp.buf[:])
|
p := mem.slice_data_cast([]u8, temp.buf[:])
|
||||||
@@ -1535,7 +1535,7 @@ defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^image.PNG_IH
|
|||||||
|
|
||||||
num_bytes := compute_buffer_size(width, height, channels, depth == 16 ? 16 : 8)
|
num_bytes := compute_buffer_size(width, height, channels, depth == 16 ? 16 : 8)
|
||||||
if !resize(&img.pixels.buf, num_bytes) {
|
if !resize(&img.pixels.buf, num_bytes) {
|
||||||
return mem.Allocator_Error.Out_Of_Memory
|
return .Unable_To_Allocate_Or_Resize
|
||||||
}
|
}
|
||||||
|
|
||||||
filter_ok: bool
|
filter_ok: bool
|
||||||
@@ -1577,7 +1577,7 @@ defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^image.PNG_IH
|
|||||||
temp: bytes.Buffer
|
temp: bytes.Buffer
|
||||||
temp_len := compute_buffer_size(x, y, channels, depth == 16 ? 16 : 8)
|
temp_len := compute_buffer_size(x, y, channels, depth == 16 ? 16 : 8)
|
||||||
if !resize(&temp.buf, temp_len) {
|
if !resize(&temp.buf, temp_len) {
|
||||||
return mem.Allocator_Error.Out_Of_Memory
|
return .Unable_To_Allocate_Or_Resize
|
||||||
}
|
}
|
||||||
|
|
||||||
params := Filter_Params{
|
params := Filter_Params{
|
||||||
|
|||||||
@@ -12,14 +12,12 @@
|
|||||||
// The QOI specification is at https://qoiformat.org.
|
// The QOI specification is at https://qoiformat.org.
|
||||||
package qoi
|
package qoi
|
||||||
|
|
||||||
import "core:mem"
|
|
||||||
import "core:image"
|
import "core:image"
|
||||||
import "core:compress"
|
import "core:compress"
|
||||||
import "core:bytes"
|
import "core:bytes"
|
||||||
import "core:os"
|
import "core:os"
|
||||||
|
|
||||||
Error :: image.Error
|
Error :: image.Error
|
||||||
General :: compress.General_Error
|
|
||||||
Image :: image.Image
|
Image :: image.Image
|
||||||
Options :: image.Options
|
Options :: image.Options
|
||||||
|
|
||||||
@@ -57,7 +55,7 @@ save_to_memory :: proc(output: ^bytes.Buffer, img: ^Image, options := Options{}
|
|||||||
max_size := pixels * (img.channels + 1) + size_of(image.QOI_Header) + size_of(u64be)
|
max_size := pixels * (img.channels + 1) + size_of(image.QOI_Header) + size_of(u64be)
|
||||||
|
|
||||||
if !resize(&output.buf, max_size) {
|
if !resize(&output.buf, max_size) {
|
||||||
return General.Resize_Failed
|
return .Unable_To_Allocate_Or_Resize
|
||||||
}
|
}
|
||||||
|
|
||||||
header := image.QOI_Header{
|
header := image.QOI_Header{
|
||||||
@@ -177,7 +175,7 @@ save_to_file :: proc(output: string, img: ^Image, options := Options{}, allocato
|
|||||||
save_to_memory(out, img, options) or_return
|
save_to_memory(out, img, options) or_return
|
||||||
write_ok := os.write_entire_file(output, out.buf[:])
|
write_ok := os.write_entire_file(output, out.buf[:])
|
||||||
|
|
||||||
return nil if write_ok else General.Cannot_Open_File
|
return nil if write_ok else .Unable_To_Write_File
|
||||||
}
|
}
|
||||||
|
|
||||||
save :: proc{save_to_memory, save_to_file}
|
save :: proc{save_to_memory, save_to_file}
|
||||||
@@ -201,7 +199,7 @@ load_from_file :: proc(filename: string, options := Options{}, allocator := cont
|
|||||||
return load_from_slice(data, options)
|
return load_from_slice(data, options)
|
||||||
} else {
|
} else {
|
||||||
img = new(Image)
|
img = new(Image)
|
||||||
return img, compress.General_Error.File_Not_Found
|
return img, .Unable_To_Read_File
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,7 +219,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
|
|||||||
|
|
||||||
header := image.read_data(ctx, image.QOI_Header) or_return
|
header := image.read_data(ctx, image.QOI_Header) or_return
|
||||||
if header.magic != image.QOI_Magic {
|
if header.magic != image.QOI_Magic {
|
||||||
return img, .Invalid_QOI_Signature
|
return img, .Invalid_Signature
|
||||||
}
|
}
|
||||||
|
|
||||||
if img == nil {
|
if img == nil {
|
||||||
@@ -264,7 +262,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
|
|||||||
bytes_needed := image.compute_buffer_size(int(header.width), int(header.height), img.channels, 8)
|
bytes_needed := image.compute_buffer_size(int(header.width), int(header.height), img.channels, 8)
|
||||||
|
|
||||||
if !resize(&img.pixels.buf, bytes_needed) {
|
if !resize(&img.pixels.buf, bytes_needed) {
|
||||||
return img, mem.Allocator_Error.Out_Of_Memory
|
return img, .Unable_To_Allocate_Or_Resize
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import "core:bytes"
|
|||||||
import "core:os"
|
import "core:os"
|
||||||
|
|
||||||
Error :: image.Error
|
Error :: image.Error
|
||||||
General :: compress.General_Error
|
|
||||||
Image :: image.Image
|
Image :: image.Image
|
||||||
Options :: image.Options
|
Options :: image.Options
|
||||||
|
|
||||||
@@ -55,7 +54,7 @@ save_to_memory :: proc(output: ^bytes.Buffer, img: ^Image, options := Options{}
|
|||||||
necessary := pixels * img.channels + size_of(image.TGA_Header)
|
necessary := pixels * img.channels + size_of(image.TGA_Header)
|
||||||
|
|
||||||
if !resize(&output.buf, necessary) {
|
if !resize(&output.buf, necessary) {
|
||||||
return General.Resize_Failed
|
return .Unable_To_Allocate_Or_Resize
|
||||||
}
|
}
|
||||||
|
|
||||||
header := image.TGA_Header{
|
header := image.TGA_Header{
|
||||||
@@ -97,7 +96,7 @@ save_to_file :: proc(output: string, img: ^Image, options := Options{}, allocato
|
|||||||
save_to_memory(out, img, options) or_return
|
save_to_memory(out, img, options) or_return
|
||||||
write_ok := os.write_entire_file(output, out.buf[:])
|
write_ok := os.write_entire_file(output, out.buf[:])
|
||||||
|
|
||||||
return nil if write_ok else General.Cannot_Open_File
|
return nil if write_ok else .Unable_To_Write_File
|
||||||
}
|
}
|
||||||
|
|
||||||
save :: proc{save_to_memory, save_to_file}
|
save :: proc{save_to_memory, save_to_file}
|
||||||
@@ -1199,37 +1199,37 @@ Corrupt_PNG_Tests := []PNG_Test{
|
|||||||
{
|
{
|
||||||
"xs1n0g01", // signature byte 1 MSBit reset to zero
|
"xs1n0g01", // signature byte 1 MSBit reset to zero
|
||||||
{
|
{
|
||||||
{Default, .Invalid_PNG_Signature, {}, 0x_0000_0000},
|
{Default, .Invalid_Signature, {}, 0x_0000_0000},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"xs2n0g01", // signature byte 2 is a 'Q'
|
"xs2n0g01", // signature byte 2 is a 'Q'
|
||||||
{
|
{
|
||||||
{Default, .Invalid_PNG_Signature, {}, 0x_0000_0000},
|
{Default, .Invalid_Signature, {}, 0x_0000_0000},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"xs4n0g01", // signature byte 4 lowercase
|
"xs4n0g01", // signature byte 4 lowercase
|
||||||
{
|
{
|
||||||
{Default, .Invalid_PNG_Signature, {}, 0x_0000_0000},
|
{Default, .Invalid_Signature, {}, 0x_0000_0000},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"xs7n0g01", // 7th byte a space instead of control-Z
|
"xs7n0g01", // 7th byte a space instead of control-Z
|
||||||
{
|
{
|
||||||
{Default, .Invalid_PNG_Signature, {}, 0x_0000_0000},
|
{Default, .Invalid_Signature, {}, 0x_0000_0000},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"xcrn0g04", // added cr bytes
|
"xcrn0g04", // added cr bytes
|
||||||
{
|
{
|
||||||
{Default, .Invalid_PNG_Signature, {}, 0x_0000_0000},
|
{Default, .Invalid_Signature, {}, 0x_0000_0000},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"xlfn0g04", // added lf bytes
|
"xlfn0g04", // added lf bytes
|
||||||
{
|
{
|
||||||
{Default, .Invalid_PNG_Signature, {}, 0x_0000_0000},
|
{Default, .Invalid_Signature, {}, 0x_0000_0000},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user