modifications to vertical flip API:

more consistent name,
 refactor stbi_load_main to preserve old code,
 support float HDR path,
 minor bugfix
This commit is contained in:
Sean Barrett 2015-04-12 09:20:31 -07:00
parent e3214d7ff7
commit 040df963c8

View File

@ -181,7 +181,7 @@
James "moose2000" Brown (iPhone PNG) Roy Eltham James "moose2000" Brown (iPhone PNG) Roy Eltham
Ben "Disch" Wenger (io callbacks) Luke Graham Ben "Disch" Wenger (io callbacks) Luke Graham
Omar Cornut (1/2/4-bit PNG) Thomas Ruf Omar Cornut (1/2/4-bit PNG) Thomas Ruf
John Bartholomew Nicolas Guillemot (vertical flip) John Bartholomew
Ken Hamada Ken Hamada
Optimizations & bugfixes Cort Stratton Optimizations & bugfixes Cort Stratton
Fabian "ryg" Giesen Blazej Dariusz Roszkowski Fabian "ryg" Giesen Blazej Dariusz Roszkowski
@ -489,8 +489,8 @@ STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultipl
// or just pass them through "as-is" // or just pass them through "as-is"
STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert);
// flip the image vertically. useful for opengl image loading. // flip the image vertically, so the first pixel in the output array is the bottom left
STBIDEF void stbi_vertically_flip_on_load(int flag_true_if_should_flip); STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip);
// ZLIB client - used by PNG, available for other purposes // ZLIB client - used by PNG, available for other purposes
@ -891,66 +891,68 @@ static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp);
static int stbi__vertically_flip_on_load = 0; static int stbi__vertically_flip_on_load = 0;
STBIDEF void stbi_vertically_flip_on_load(int flag_true_if_should_flip) STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip)
{ {
stbi__vertically_flip_on_load = flag_true_if_should_flip; stbi__vertically_flip_on_load = flag_true_if_should_flip;
} }
static unsigned char *stbi_load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) static unsigned char *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp)
{ {
unsigned char *result = NULL;
if (0); // get the test chain started
#ifndef STBI_NO_JPEG #ifndef STBI_NO_JPEG
else if (stbi__jpeg_test(s)) result = stbi__jpeg_load(s,x,y,comp,req_comp); if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp);
#endif #endif
#ifndef STBI_NO_PNG #ifndef STBI_NO_PNG
else if (stbi__png_test(s)) result = stbi__png_load(s,x,y,comp,req_comp); if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp);
#endif #endif
#ifndef STBI_NO_BMP #ifndef STBI_NO_BMP
else if (stbi__bmp_test(s)) result = stbi__bmp_load(s,x,y,comp,req_comp); if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp);
#endif #endif
#ifndef STBI_NO_GIF #ifndef STBI_NO_GIF
else if (stbi__gif_test(s)) result = stbi__gif_load(s,x,y,comp,req_comp); if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp);
#endif #endif
#ifndef STBI_NO_PSD #ifndef STBI_NO_PSD
else if (stbi__psd_test(s)) result = stbi__psd_load(s,x,y,comp,req_comp); if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp);
#endif #endif
#ifndef STBI_NO_PIC #ifndef STBI_NO_PIC
else if (stbi__pic_test(s)) result = stbi__pic_load(s,x,y,comp,req_comp); if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp);
#endif #endif
#ifndef STBI_NO_PNM #ifndef STBI_NO_PNM
else if (stbi__pnm_test(s)) result = stbi__pnm_load(s,x,y,comp,req_comp); if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp);
#endif #endif
#ifndef STBI_NO_HDR #ifndef STBI_NO_HDR
else if (stbi__hdr_test(s)) { if (stbi__hdr_test(s)) {
float *hdr = stbi__hdr_load(s, x,y,comp,req_comp); float *hdr = stbi__hdr_load(s, x,y,comp,req_comp);
result = stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp);
} }
#endif #endif
#ifndef STBI_NO_TGA #ifndef STBI_NO_TGA
// test tga last because it's a crappy test! // test tga last because it's a crappy test!
else if (stbi__tga_test(s)) if (stbi__tga_test(s))
result = stbi__tga_load(s,x,y,comp,req_comp); return stbi__tga_load(s,x,y,comp,req_comp);
#endif #endif
else
return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt");
}
// post-processing static unsigned char *stbi__load_flip(stbi__context *s, int *x, int *y, int *comp, int req_comp)
if (stbi__vertically_flip_on_load) { {
unsigned char *result = stbi__load_main(s, x, y, comp, req_comp);
if (stbi__vertically_flip_on_load && result != NULL) {
int w = *x, h = *y;
int depth = req_comp ? req_comp : *comp; int depth = req_comp ? req_comp : *comp;
int row,col,z; int row,col,z;
stbi_uc temp; stbi_uc temp;
for (row = 0; row < *y / 2; row++) { // @OPTIMIZE: use a bigger temp buffer and memcpy multiple pixels at once
for (col = 0; col < *x; col++) { for (row = 0; row < (h>>1); row++) {
for (col = 0; col < w; col++) {
for (z = 0; z < depth; z++) { for (z = 0; z < depth; z++) {
temp = result[(row * (*x) + col) * depth + z]; temp = result[(row * w + col) * depth + z];
result[(row * (*x) + col) * depth + z] = result[((*y - row - 1) * (*x) + col) * depth + z]; result[(row * w + col) * depth + z] = result[((h - row - 1) * w + col) * depth + z];
result[((*y - row - 1) * (*x) + col) * depth + z] = temp; result[((h - row - 1) * w + col) * depth + z] = temp;
} }
} }
} }
@ -959,6 +961,28 @@ static unsigned char *stbi_load_main(stbi__context *s, int *x, int *y, int *comp
return result; return result;
} }
static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp)
{
if (stbi__vertically_flip_on_load && result != NULL) {
int w = *x, h = *y;
int depth = req_comp ? req_comp : *comp;
int row,col,z;
float temp;
// @OPTIMIZE: use a bigger temp buffer and memcpy multiple pixels at once
for (row = 0; row < (h>>1); row++) {
for (col = 0; col < w; col++) {
for (z = 0; z < depth; z++) {
temp = result[(row * w + col) * depth + z];
result[(row * w + col) * depth + z] = result[((h - row - 1) * w + col) * depth + z];
result[((h - row - 1) * w + col) * depth + z] = temp;
}
}
}
}
}
#ifndef STBI_NO_STDIO #ifndef STBI_NO_STDIO
static FILE *stbi__fopen(char const *filename, char const *mode) static FILE *stbi__fopen(char const *filename, char const *mode)
@ -989,7 +1013,7 @@ STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req
unsigned char *result; unsigned char *result;
stbi__context s; stbi__context s;
stbi__start_file(&s,f); stbi__start_file(&s,f);
result = stbi_load_main(&s,x,y,comp,req_comp); result = stbi__load_flip(&s,x,y,comp,req_comp);
if (result) { if (result) {
// need to 'unget' all the characters in the IO buffer // need to 'unget' all the characters in the IO buffer
fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR);
@ -1002,25 +1026,29 @@ STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, i
{ {
stbi__context s; stbi__context s;
stbi__start_mem(&s,buffer,len); stbi__start_mem(&s,buffer,len);
return stbi_load_main(&s,x,y,comp,req_comp); return stbi__load_flip(&s,x,y,comp,req_comp);
} }
STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp)
{ {
stbi__context s; stbi__context s;
stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
return stbi_load_main(&s,x,y,comp,req_comp); return stbi__load_flip(&s,x,y,comp,req_comp);
} }
#ifndef STBI_NO_LINEAR #ifndef STBI_NO_LINEAR
static float *stbi_loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp)
{ {
unsigned char *data; unsigned char *data;
#ifndef STBI_NO_HDR #ifndef STBI_NO_HDR
if (stbi__hdr_test(s)) if (stbi__hdr_test(s)) {
return stbi__hdr_load(s,x,y,comp,req_comp); float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp);
if (hdr_data)
stbi__float_postprocess(hdr_data,x,y,comp,req_comp);
return hdr_data;
}
#endif #endif
data = stbi_load_main(s, x, y, comp, req_comp); data = stbi__load_flip(s, x, y, comp, req_comp);
if (data) if (data)
return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp);
return stbi__errpf("unknown image type", "Image not of any known type, or corrupt"); return stbi__errpf("unknown image type", "Image not of any known type, or corrupt");
@ -1030,14 +1058,14 @@ STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, in
{ {
stbi__context s; stbi__context s;
stbi__start_mem(&s,buffer,len); stbi__start_mem(&s,buffer,len);
return stbi_loadf_main(&s,x,y,comp,req_comp); return stbi__loadf_main(&s,x,y,comp,req_comp);
} }
STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp)
{ {
stbi__context s; stbi__context s;
stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
return stbi_loadf_main(&s,x,y,comp,req_comp); return stbi__loadf_main(&s,x,y,comp,req_comp);
} }
#ifndef STBI_NO_STDIO #ifndef STBI_NO_STDIO
@ -1055,7 +1083,7 @@ STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_
{ {
stbi__context s; stbi__context s;
stbi__start_file(&s,f); stbi__start_file(&s,f);
return stbi_loadf_main(&s,x,y,comp,req_comp); return stbi__loadf_main(&s,x,y,comp,req_comp);
} }
#endif // !STBI_NO_STDIO #endif // !STBI_NO_STDIO