allow disabling stb_image

This commit is contained in:
nothings.org 2007-10-20 19:27:24 +00:00
parent 0a3e77f187
commit 7f397fb30d
3 changed files with 83 additions and 18 deletions

98
imv.c
View File

@ -17,10 +17,12 @@
*/ */
// Set section alignment to minimize alignment overhead // Set section alignment to minimize alignment overhead
#if (_MSC_VER < 1300)
#pragma comment(linker, "/FILEALIGN:0x200") #pragma comment(linker, "/FILEALIGN:0x200")
#endif
#define _WIN32_WINNT 0x0500 #define _WIN32_WINNT 0x0500
//#define WINVER 0x0500 // produces an annoying warning message, so we do it the hard way
#include <windows.h> #include <windows.h>
#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
@ -30,18 +32,37 @@
#define STB_DEFINE #define STB_DEFINE
#include "stb.h" /* http://nothings.org/stb.h */ #include "stb.h" /* http://nothings.org/stb.h */
// general configuration options
#ifndef USE_STBI
#define USE_STBI 1
#endif
#ifndef USE_GDIPLUS
#define USE_GDIPLUS 1
#endif
#ifndef USE_FREEIMAGE
#define USE_FREEIMAGE 1
#endif
#ifndef ALLOW_RECOLORING
#define ALLOW_RECOLORING 1
#endif
// implement USE_STBI
#if USE_STBI
#define STBI_FAILURE_USERMSG #define STBI_FAILURE_USERMSG
#define STBI_NO_STDIO #define STBI_NO_STDIO
#define STBI_NO_WRITE
#include "stb_image.c" /* http://nothings.org/stb_image.c */ #include "stb_image.c" /* http://nothings.org/stb_image.c */
#endif
#include "resource.h" #include "resource.h"
typedef int Bool; typedef int Bool;
// general configuration options
#define USE_GDIPLUS
#define USE_FREEIMAGE
// size of border in pixels // size of border in pixels
#define FRAME 3 #define FRAME 3
@ -343,7 +364,9 @@ static unsigned char alpha_background[2][3] =
// given raw decoded data from stbi_load, make it into a proper Image (e.g. creating a // given raw decoded data from stbi_load, make it into a proper Image (e.g. creating a
// windows-compatible bitmap with 4-byte aligned rows and BGR color order) // windows-compatible bitmap with 4-byte aligned rows and BGR color order)
#if ALLOW_RECOLORING
float lmin=0,lmax=1; float lmin=0,lmax=1;
#endif
void make_image(Image *z, int image_x, int image_y, uint8 *image_data, BOOL image_loaded_as_rgb, int image_n) void make_image(Image *z, int image_x, int image_y, uint8 *image_data, BOOL image_loaded_as_rgb, int image_n)
{ {
int i,j,k=0; int i,j,k=0;
@ -364,6 +387,7 @@ void make_image(Image *z, int image_x, int image_y, uint8 *image_data, BOOL imag
image_data[k+2] = t; image_data[k+2] = t;
} }
#if ALLOW_RECOLORING
if (lmin > 0 || lmax < 1) { if (lmin > 0 || lmax < 1) {
int c; int c;
for (c=0; c < 3; ++c) { for (c=0; c < 3; ++c) {
@ -371,6 +395,7 @@ void make_image(Image *z, int image_x, int image_y, uint8 *image_data, BOOL imag
image_data[k+c] = stb_clamp(z, 0, 255); image_data[k+c] = stb_clamp(z, 0, 255);
} }
} }
#endif
#if BPP==4 #if BPP==4
// if image had an alpha channel, pre-blend with background // if image had an alpha channel, pre-blend with background
@ -1792,7 +1817,9 @@ int reg_set(char *str, void *data, int len)
return (ERROR_SUCCESS == RegSetValueEx(zreg, str, 0, REG_BINARY, data, len)); return (ERROR_SUCCESS == RegSetValueEx(zreg, str, 0, REG_BINARY, data, len));
} }
#ifdef USE_STBI
int only_stbi=FALSE; int only_stbi=FALSE;
#endif
// we use very short strings for these to avoid wasting space, since // we use very short strings for these to avoid wasting space, since
// people shouldn't be mucking with them directly anyway! // people shouldn't be mucking with them directly anyway!
@ -1806,7 +1833,9 @@ void reg_save(void)
reg_set("cache", &temp, 4); reg_set("cache", &temp, 4);
reg_set("lfs", &label_font_height, 4); reg_set("lfs", &label_font_height, 4);
reg_set("label", &show_label, 4); reg_set("label", &show_label, 4);
#if USE_STBI
reg_set("stbi", &only_stbi, 4); reg_set("stbi", &only_stbi, 4);
#endif
reg_set("border", &show_frame, 4); reg_set("border", &show_frame, 4);
reg_set("stime", &delay_time, 4); reg_set("stime", &delay_time, 4);
RegCloseKey(zreg); RegCloseKey(zreg);
@ -1824,7 +1853,9 @@ void reg_load(void)
reg_get("label", &show_label, 4); reg_get("label", &show_label, 4);
if (reg_get("cache", &temp, 4)) if (reg_get("cache", &temp, 4))
max_cache_bytes = temp << 20; max_cache_bytes = temp << 20;
#if USE_STBI
reg_get("stbi", &only_stbi, 4); reg_get("stbi", &only_stbi, 4);
#endif
reg_get("border", &show_frame, 4); reg_get("border", &show_frame, 4);
extra_border = show_frame; extra_border = show_frame;
reg_get("stime", &delay_time, 4); reg_get("stime", &delay_time, 4);
@ -1924,8 +1955,10 @@ BOOL CALLBACK PrefDlgProc(HWND hdlg, UINT imsg, WPARAM wparam, LPARAM lparam)
case WM_INITDIALOG: { case WM_INITDIALOG: {
// pick a random preference image // pick a random preference image
int n = ((rand() >> 6) % 3); int n = ((rand() >> 6) % 3);
int x,y,i,j,k; int x, y;
// decode it // decode it
#if USE_STBI
int i, j, k;
uint8 *data = stbi_load_from_memory(rom_images[n],2000,&x,&y,NULL,1); uint8 *data = stbi_load_from_memory(rom_images[n],2000,&x,&y,NULL,1);
pref_image = bmp_alloc(x,y); pref_image = bmp_alloc(x,y);
if (data && pref_image) { if (data && pref_image) {
@ -1936,11 +1969,22 @@ BOOL CALLBACK PrefDlgProc(HWND hdlg, UINT imsg, WPARAM wparam, LPARAM lparam)
pref_image->pixels[pref_image->stride*j + BPP*i + k] = data[j*x+i]; pref_image->pixels[pref_image->stride*j + BPP*i + k] = data[j*x+i];
} }
if (data) free(data); if (data) free(data);
#else
int channels;
Bool loaded_as_rgb;
uint8 *data = imv_decode_from_memory(rom_images[n], 2000, &x, &y, &loaded_as_rgb, &channels, BPP);
assert(channels == BPP);
pref_image = bmp_alloc(x, y);
pref_image->pixels = data;
#endif
// copy preferences into dialog // copy preferences into dialog
SendMessage(GetDlgItem(hdlg, DIALOG_upsample), BM_SETCHECK, upsample_cubic, 0); SendMessage(GetDlgItem(hdlg, DIALOG_upsample), BM_SETCHECK, upsample_cubic, 0);
SendMessage(GetDlgItem(hdlg, DIALOG_showlabel), BM_SETCHECK, show_label, 0); SendMessage(GetDlgItem(hdlg, DIALOG_showlabel), BM_SETCHECK, show_label, 0);
#if USE_STBI
SendMessage(GetDlgItem(hdlg, DIALOG_stbi_only), BM_SETCHECK, only_stbi, 0); SendMessage(GetDlgItem(hdlg, DIALOG_stbi_only), BM_SETCHECK, only_stbi, 0);
#else
EnableWindow(GetDlgItem(hdlg, DIALOG_stbi_only), FALSE);
#endif
SendMessage(GetDlgItem(hdlg, DIALOG_showborder), BM_SETCHECK, show_frame, 0); SendMessage(GetDlgItem(hdlg, DIALOG_showborder), BM_SETCHECK, show_frame, 0);
for (i=0; i < 6; ++i) for (i=0; i < 6; ++i)
set_dialog_number(DIALOG_r1+i, alpha_background[0][i]); set_dialog_number(DIALOG_r1+i, alpha_background[0][i]);
@ -2002,7 +2046,9 @@ BOOL CALLBACK PrefDlgProc(HWND hdlg, UINT imsg, WPARAM wparam, LPARAM lparam)
delay_time = get_dialog_numberf(DIALOG_slideshowtime); delay_time = get_dialog_numberf(DIALOG_slideshowtime);
upsample_cubic = BST_CHECKED == SendMessage(GetDlgItem(hdlg,DIALOG_upsample ), BM_GETCHECK,0,0); upsample_cubic = BST_CHECKED == SendMessage(GetDlgItem(hdlg,DIALOG_upsample ), BM_GETCHECK,0,0);
show_label = BST_CHECKED == SendMessage(GetDlgItem(hdlg,DIALOG_showlabel), BM_GETCHECK,0,0); show_label = BST_CHECKED == SendMessage(GetDlgItem(hdlg,DIALOG_showlabel), BM_GETCHECK,0,0);
#if USE_STBI
only_stbi = BST_CHECKED == SendMessage(GetDlgItem(hdlg,DIALOG_stbi_only), BM_GETCHECK,0,0); only_stbi = BST_CHECKED == SendMessage(GetDlgItem(hdlg,DIALOG_stbi_only), BM_GETCHECK,0,0);
#endif USE_STBI
new_border = BST_CHECKED == SendMessage(GetDlgItem(hdlg,DIALOG_showborder),BM_GETCHECK,0,0); new_border = BST_CHECKED == SendMessage(GetDlgItem(hdlg,DIALOG_showborder),BM_GETCHECK,0,0);
// if alpha_background changed, clear the cache of any images that used it // if alpha_background changed, clear the cache of any images that used it
@ -2234,10 +2280,12 @@ int WINAPI MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
KillTimer(win,0); KillTimer(win,0);
break; break;
#if ALLOW_RECOLORING
case '[': lmax = stb_clamp(lmax-1.0f/32, 0,1); clear_cache(0); advance(0); break; case '[': lmax = stb_clamp(lmax-1.0f/32, 0,1); clear_cache(0); advance(0); break;
case ']': lmax = stb_clamp(lmax+1.0f/32, 0,1); clear_cache(0); advance(0); break; case ']': lmax = stb_clamp(lmax+1.0f/32, 0,1); clear_cache(0); advance(0); break;
case '{': lmin = stb_clamp(lmin-1.0f/32, 0,1); clear_cache(0); advance(0); break; case '{': lmin = stb_clamp(lmin-1.0f/32, 0,1); clear_cache(0); advance(0); break;
case '}': lmin = stb_clamp(lmin+1.0f/32, 0,1); clear_cache(0); advance(0); break; case '}': lmin = stb_clamp(lmin+1.0f/32, 0,1); clear_cache(0); advance(0); break;
#endif
default: default:
return 1; return 1;
@ -2391,7 +2439,7 @@ int cur_is_current(void)
return !strcmp(cur_filename, source_c->filename); return !strcmp(cur_filename, source_c->filename);
} }
#ifdef USE_GDIPLUS #if USE_GDIPLUS
typedef ULONG ULONG_PTR; typedef ULONG ULONG_PTR;
static Bool GdiplusPresent; static Bool GdiplusPresent;
@ -2402,7 +2450,7 @@ static Bool LoadGdiplus(void);
//#define ICM_SUFFIX "ICM" //#define ICM_SUFFIX "ICM"
#endif #endif
#ifdef USE_FREEIMAGE #if USE_FREEIMAGE
static int FreeImagePresent; static int FreeImagePresent;
static int LoadFreeImage(void); static int LoadFreeImage(void);
#endif #endif
@ -2441,19 +2489,27 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
// we can't do this statically with the current build process // we can't do this statically with the current build process
strcat(helptext_center, VERSION); strcat(helptext_center, VERSION);
#ifdef USE_GDIPLUS #if USE_GDIPLUS
if (LoadGdiplus()) { if (LoadGdiplus()) {
strcat(helptext_center, "\nUsing GDI+"); strcat(helptext_center, "\nUsing GDI+");
open_filter = "Image Files\0*.jpg;*.jpeg;*.png;*.bmp;*.tga;*.hdr;*.gif;*.ico;*.jng;*.tiff\0"; open_filter = "Image Files\0*.jpg;*.jpeg;*.png;*.bmp;*.tga;"
#if USE_STBI
"*.hdr;"
#endif
"*.gif;*.ico;*.jng;*.tiff\0";
} }
#endif #endif
// now try to LoadFreeImage _after_ we've already loaded the prefs; // now try to LoadFreeImage _after_ we've already loaded the prefs;
// that way only_stbi can be used to suppress errors // that way only_stbi can be used to suppress errors
#ifdef USE_FREEIMAGE #if USE_FREEIMAGE
if (LoadFreeImage()) { if (LoadFreeImage()) {
strcat(helptext_center, "\nUsing FreeImage.dll: http://freeimage.sourceforge.net"); strcat(helptext_center, "\nUsing FreeImage.dll: http://freeimage.sourceforge.net");
open_filter = "Image Files\0*.jpg;*.jpeg;*.png;*.bmp;*.hdr;*.dds;*.gif;*.ico;*.jng;*.lbm;*.pcx;*.ppm;*.psd;*.tga;*.tiff\0"; open_filter = "Image Files\0*.jpg;*.jpeg;*.png;*.bmp;*.tga;"
#if USE_STBI
"*.hdr;"
#endif
"*.dds;*.gif;*.ico;*.jng;*.lbm;*.pcx;*.ppm;*.psd;*.tiff\0";
} }
#endif #endif
assert(helptext_center[sizeof(helptext_center)-1]==0); assert(helptext_center[sizeof(helptext_center)-1]==0);
@ -3308,7 +3364,7 @@ static char *imv_failure_reason(void)
return imv_failure_string; return imv_failure_string;
} }
#ifdef USE_GDIPLUS #if USE_GDIPLUS
#pragma pack(push,8) #pragma pack(push,8)
@ -3463,14 +3519,18 @@ static Bool LoadGdiplus(void)
GdipBitmapLockBits = (GdipBitmapLockBitsProc)GpFunc("GdipBitmapLockBits"); GdipBitmapLockBits = (GdipBitmapLockBitsProc)GpFunc("GdipBitmapLockBits");
GdipBitmapUnlockBits = (GdipBitmapUnlockBitsProc)GpFunc("GdipBitmapUnlockBits"); GdipBitmapUnlockBits = (GdipBitmapUnlockBitsProc)GpFunc("GdipBitmapUnlockBits");
if (!GdiplusPresent) { if (!GdiplusPresent) {
#if USE_STBI
if (!only_stbi) if (!only_stbi)
#endif
error("Invalid GdiPlus.dll; disabling GDI+ support."); error("Invalid GdiPlus.dll; disabling GDI+ support.");
} else { } else {
// no need to use GDI+ backup thread, or to call the hook methods in gpStartupOutput // no need to use GDI+ backup thread, or to call the hook methods in gpStartupOutput
GdiplusStartupInput gpStartupInput = { 1, NULL, TRUE, FALSE }; GdiplusStartupInput gpStartupInput = { 1, NULL, TRUE, FALSE };
if (GdiplusStartup(&GpToken, &gpStartupInput, &gpStartupOutput) != GpOk) { if (GdiplusStartup(&GpToken, &gpStartupInput, &gpStartupOutput) != GpOk) {
GdiplusPresent = FALSE; GdiplusPresent = FALSE;
#if USE_STBI
if (!only_stbi) if (!only_stbi)
#endif
error("Failed to initialize GdiPlus.dll; disabling GDI+ support."); error("Failed to initialize GdiPlus.dll; disabling GDI+ support.");
} }
} }
@ -3539,7 +3599,7 @@ liwgExit:
#endif #endif
#ifdef USE_FREEIMAGE #if USE_FREEIMAGE
// FreeImage types // FreeImage types
@ -3635,7 +3695,9 @@ static int LoadFreeImage(void)
FreeImage_IsTransparent = (freeimage_istransparent *)fifunc("_FreeImage_IsTransparent@4"); FreeImage_IsTransparent = (freeimage_istransparent *)fifunc("_FreeImage_IsTransparent@4");
if (!FreeImagePresent) { if (!FreeImagePresent) {
#if USE_STBI
if (!only_stbi) if (!only_stbi)
#endif
error("Invalid FreeImage.dll; disabling FreeImage support."); error("Invalid FreeImage.dll; disabling FreeImage support.");
} else } else
FreeImage_SetOutputMessage(FreeImageErrorHandler); FreeImage_SetOutputMessage(FreeImageErrorHandler);
@ -3683,6 +3745,7 @@ static uint8 *imv_decode_from_memory(uint8 *mem, int len, int *x, int *y, Bool*
// prefer STBI over everything else // prefer STBI over everything else
*loaded_as_rgb = FALSE; *loaded_as_rgb = FALSE;
#if USE_STBI
res = stbi_load_from_memory(mem, len, x, y, n, n_req); res = stbi_load_from_memory(mem, len, x, y, n, n_req);
if (res) { if (res) {
*loaded_as_rgb = TRUE; *loaded_as_rgb = TRUE;
@ -3692,10 +3755,11 @@ static uint8 *imv_decode_from_memory(uint8 *mem, int len, int *x, int *y, Bool*
if (only_stbi) if (only_stbi)
return res; return res;
#endif
// prefer GDI+ over FreeImage // prefer GDI+ over FreeImage
#ifdef USE_GDIPLUS #if USE_GDIPLUS
if (GdiplusPresent) { if (GdiplusPresent) {
res = LoadImageWithGdiplus(mem, len, x, y, n, n_req); res = LoadImageWithGdiplus(mem, len, x, y, n, n_req);
if (res) if (res)
@ -3705,7 +3769,7 @@ static uint8 *imv_decode_from_memory(uint8 *mem, int len, int *x, int *y, Bool*
// FreeImage is the final fallback // FreeImage is the final fallback
#ifdef USE_FREEIMAGE #if USE_FREEIMAGE
if (FreeImagePresent) { if (FreeImagePresent) {
FIMEMORY *fi = FreeImage_OpenMemory(mem,len); FIMEMORY *fi = FreeImage_OpenMemory(mem,len);
res = LoadImageWithFreeImage(fi, x, y, n, n_req); res = LoadImageWithFreeImage(fi, x, y, n, n_req);

View File

@ -13,6 +13,7 @@ rem # Make release directory
mkdir ..\stb_imv mkdir ..\stb_imv
copy vc6\release\stb_imv.exe ..\stb_imv\imv.exe copy vc6\release\stb_imv.exe ..\stb_imv\imv.exe
copy "vc6\light release\stb_imv_light.exe" ..\stb_imv\imv_light.exe
copy readme_binary.txt+notes.txt ..\stb_imv\readme.txt copy readme_binary.txt+notes.txt ..\stb_imv\readme.txt
rem # Make tarball directory rem # Make tarball directory

View File

@ -1 +1 @@
set VERSION="0.95" set VERSION="0.96"