menubuilder: Use png file format for icons with 24 & 32-bit color.
Vitaliy Margolen
wine-patch at kievinfo.com
Mon Jan 23 17:06:49 CST 2006
ChangeLog:
menubuilder: Use png file format for icons with 24 & 32-bit color.
Add BMP file handling.
This time with processing of the AND mask. For that I'm using top left corner
for the background color.
configure | 82 +++++++++++
configure.ac | 10 +
include/config.h.in | 3
programs/winemenubuilder/Makefile.in | 2
programs/winemenubuilder/winemenubuilder.c | 204 +++++++++++++++++++++++-----
5 files changed, 260 insertions(+), 41 deletions(-)
-------------- next part --------------
d12de0bc85cce7df66aafd8af21e3c152fb7a93e
diff --git a/configure b/configure
index 4de3c19..7217067 100755
--- a/configure
+++ b/configure
@@ -311,7 +311,7 @@ ac_includes_default="\
# include <unistd.h>
#endif"
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS DLLDEFS build build_cpu build_vendor build_os host host_cpu host_vendor host_os WIN16_FILES WIN16_INSTALL SET_MAKE CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CXX CXXFLAGS ac_ct_CXX CPPBIN ac_ct_CPPBIN TOOLSDIR CPP X_CFLAGS X_PRE_LIBS X_LIBS X_EXTRA_LIBS LEX LEXLIB LEX_OUTPUT_ROOT XLEX BISON AS ac_ct_AS LD ac_ct_LD AR ac_ct_AR RANLIB ac_ct_RANLIB STRIP ac_ct_STRIP WINDRES ac_ct_WINDRES LN_S LN EGREP LDCONFIG INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LINT LINTFLAGS FONTFORGE PKG_CONFIG PRELINK LIBPTHREAD XLIB XFILES OPENGLFILES GLU32FILES OPENGL_LIBS GLUT_LIBS GLUT32FILES NASLIBS XML2LIBS XML2INCL XSLTLIBS XSLTINCL CURSESLIBS sane_devel SANELIBS SANEINCL ICULIBS LCMSLIBS LDAPLIBS FREETYPELIBS FREETYPEINCL ft_devel ft_devel2 FONTSSUBDIRS ARTSCCONFIG ARTSLIBS ARTSINCL ESDCONFIG ESDLIBS ESDINCL ALSALIBS AUDIOIOLIBS EXTRACFLAGS BUILTINFLAG DLLEXT DLLFLAGS DLLIBS LDSHARED LDDLLFLAGS LIBEXT IMPLIBEXT DLLTOOL ac_ct_DLLTOOL DLLWRAP ac_ct_DLLWRAP LDEXECFLAGS COREFOUNDATIONLIB IOKITLIB LDLIBWINEFLAGS CROSSTEST CROSSCC CROSSWINDRES LDPATH CRTLIBS SOCKETLIBS WINE_BINARIES MAIN_BINARY LDD LIBOBJS LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS DLLDEFS build build_cpu build_vendor build_os host host_cpu host_vendor host_os WIN16_FILES WIN16_INSTALL SET_MAKE CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CXX CXXFLAGS ac_ct_CXX CPPBIN ac_ct_CPPBIN TOOLSDIR CPP X_CFLAGS X_PRE_LIBS X_LIBS X_EXTRA_LIBS LEX LEXLIB LEX_OUTPUT_ROOT XLEX BISON AS ac_ct_AS LD ac_ct_LD AR ac_ct_AR RANLIB ac_ct_RANLIB STRIP ac_ct_STRIP WINDRES ac_ct_WINDRES LN_S LN EGREP LDCONFIG INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LINT LINTFLAGS FONTFORGE PKG_CONFIG PRELINK LIBPTHREAD XLIB XFILES OPENGLFILES GLU32FILES OPENGL_LIBS GLUT_LIBS GLUT32FILES NASLIBS XML2LIBS XML2INCL XSLTLIBS XSLTINCL CURSESLIBS sane_devel SANELIBS SANEINCL ICULIBS LCMSLIBS PNGLIBS LDAPLIBS FREETYPELIBS FREETYPEINCL ft_devel ft_devel2 FONTSSUBDIRS ARTSCCONFIG ARTSLIBS ARTSINCL ESDCONFIG ESDLIBS ESDINCL ALSALIBS AUDIOIOLIBS EXTRACFLAGS BUILTINFLAG DLLEXT DLLFLAGS DLLIBS LDSHARED LDDLLFLAGS LIBEXT IMPLIBEXT DLLTOOL ac_ct_DLLTOOL DLLWRAP ac_ct_DLLWRAP LDEXECFLAGS COREFOUNDATIONLIB IOKITLIB LDLIBWINEFLAGS CROSSTEST CROSSCC CROSSWINDRES LDPATH CRTLIBS SOCKETLIBS WINE_BINARIES MAIN_BINARY LDD LIBOBJS LTLIBOBJS'
ac_subst_files='MAKE_RULES MAKE_DLL_RULES MAKE_IMPLIB_RULES MAKE_TEST_RULES MAKE_LIB_RULES MAKE_PROG_RULES'
# Initialize some variables set by options.
@@ -7091,6 +7091,7 @@ for ac_header in \
poll.h \
process.h \
pthread.h \
+ png.h \
pwd.h \
regex.h \
sched.h \
@@ -9613,6 +9614,84 @@ fi
fi
+PNGLIBS=""
+
+if test "$ac_cv_header_png_h" = "yes"
+then
+ echo "$as_me:$LINENO: checking for png_set_IHDR in -lpng" >&5
+echo $ECHO_N "checking for png_set_IHDR in -lpng... $ECHO_C" >&6
+if test "${ac_cv_lib_png_png_set_IHDR+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpng $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char png_set_IHDR ();
+int
+main ()
+{
+png_set_IHDR ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_png_png_set_IHDR=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_png_png_set_IHDR=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_png_png_set_IHDR" >&5
+echo "${ECHO_T}$ac_cv_lib_png_png_set_IHDR" >&6
+if test $ac_cv_lib_png_png_set_IHDR = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_PNG 1
+_ACEOF
+
+ PNGLIBS="-lpng"
+fi
+
+fi
+
LDAPLIBS=""
if test "$ac_cv_header_ldap_h" = "yes" -a "$ac_cv_header_lber_h" = "yes"
@@ -19689,6 +19768,7 @@ s, at SANELIBS@,$SANELIBS,;t t
s, at SANEINCL@,$SANEINCL,;t t
s, at ICULIBS@,$ICULIBS,;t t
s, at LCMSLIBS@,$LCMSLIBS,;t t
+s, at PNGLIBS@,$PNGLIBS,;t t
s, at LDAPLIBS@,$LDAPLIBS,;t t
s, at FREETYPELIBS@,$FREETYPELIBS,;t t
s, at FREETYPEINCL@,$FREETYPEINCL,;t t
diff --git a/configure.ac b/configure.ac
index b458d7d..c1b78b3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -224,6 +224,7 @@ AC_CHECK_HEADERS(\
poll.h \
process.h \
pthread.h \
+ png.h \
pwd.h \
regex.h \
sched.h \
@@ -542,6 +543,15 @@ then
LCMSLIBS="-llcms"])
fi
+dnl **** Check for libpng ***
+AC_SUBST(PNGLIBS,"")
+if test "$ac_cv_header_png_h" = "yes"
+then
+ AC_CHECK_LIB(png, png_set_IHDR,
+ [AC_DEFINE(HAVE_PNG, 1, [Define if you have the libpng development environment])
+ PNGLIBS="-lpng"])
+fi
+
dnl **** Check for OpenLDAP ***
AC_SUBST(LDAPLIBS,"")
if test "$ac_cv_header_ldap_h" = "yes" -a "$ac_cv_header_lber_h" = "yes"
diff --git a/include/config.h.in b/include/config.h.in
index 51ecdc5..95c7149 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -458,6 +458,9 @@
/* Define to 1 if the system has the type `pid_t'. */
#undef HAVE_PID_T
+/* Define to 1 if you have the <png.h> header file. */
+#undef HAVE_PNG_H
+
/* Define to 1 if you have the <poll.h> header file. */
#undef HAVE_POLL_H
diff --git a/programs/winemenubuilder/Makefile.in b/programs/winemenubuilder/Makefile.in
index 48ac38d..adb79a1 100644
--- a/programs/winemenubuilder/Makefile.in
+++ b/programs/winemenubuilder/Makefile.in
@@ -5,7 +5,7 @@ VPATH = @srcdir@
MODULE = winemenubuilder.exe
APPMODE = -mwindows
IMPORTS = shell32 ole32 user32 advapi32 kernel32
-EXTRALIBS = -luuid
+EXTRALIBS = -luuid @PNGLIBS@
C_SRCS = \
winemenubuilder.c
diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c
index 08c0760..2875571 100644
--- a/programs/winemenubuilder/winemenubuilder.c
+++ b/programs/winemenubuilder/winemenubuilder.c
@@ -62,6 +62,9 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+#ifdef HAVE_PNG_H
+#include <png.h>
+#endif
#include <errno.h>
#include <stdarg.h>
@@ -143,22 +146,131 @@ typedef struct
* FIXME: should not use stdio
*/
-static BOOL SaveIconResAsXPM(const BITMAPINFO *pIcon, const char *szXPMFileName, LPCWSTR commentW)
+#define MASK(x,y) (!(pAND)?0:(pAND[(x) / 8 + (nHeight - (y) - 1) * nANDWidthBytes] & (1 << (7 - (x) % 8))))
+
+#ifdef HAVE_PNG_H
+static BOOL SaveIconResAsPNG(const BITMAPINFO *pIcon, char *szPNGFileName, LPCWSTR commentW)
+{
+ FILE *fPNGFile;
+ png_structp png_ptr;
+ png_infop info_ptr;
+ int nXORWidthBytes, nANDWidthBytes, color_type = 0, i, j;
+ BYTE *pXOR, *row;
+ const BYTE *pAND = NULL;
+ RGBQUAD bgColor = {0};
+ int nWidth = pIcon->bmiHeader.biWidth;
+ int nHeight = pIcon->bmiHeader.biHeight;
+ int nBpp = pIcon->bmiHeader.biBitCount;
+
+ memcpy(szPNGFileName + strlen(szPNGFileName) - 3, "png", 3);
+ if (!(fPNGFile = fopen(szPNGFileName, "w")))
+ {
+ WINE_ERR("unable to open '%s' for writing: %s\n", szPNGFileName, strerror(errno));
+ return FALSE;
+ }
+
+ nXORWidthBytes = 4 * ((nWidth * nBpp + 31) / 32);
+ nANDWidthBytes = 4 * ((nWidth + 31 ) / 32);
+ pXOR = (BYTE*) pIcon + sizeof(BITMAPINFOHEADER) + pIcon->bmiHeader.biClrUsed * sizeof(RGBQUAD);
+ if (nHeight > nWidth)
+ {
+ nHeight /= 2;
+ pAND = pXOR + nHeight * nXORWidthBytes;
+ }
+
+ switch (nBpp)
+ {
+ case 32:
+ color_type |= PNG_COLOR_MASK_ALPHA;
+ /* fall through */
+ case 24:
+ color_type |= PNG_COLOR_MASK_COLOR;
+ break;
+ default:
+ return FALSE;
+ }
+
+ /* image and mask are upside down reversed */
+ row = pXOR + (nHeight - 1) * nXORWidthBytes;
+ /* top left corner */
+ bgColor.rgbRed = row[0];
+ bgColor.rgbGreen = row[1];
+ bgColor.rgbBlue = row[2];
+ for (i = 0; i < nHeight; i++, row -= nXORWidthBytes)
+ {
+ for (j = 0; j < nWidth; j++, row += nBpp >> 3)
+ {
+ if (MASK(j, i))
+ {
+ RGBQUAD *pixel = (RGBQUAD *)row;
+ pixel->rgbBlue = bgColor.rgbBlue;
+ pixel->rgbGreen = bgColor.rgbGreen;
+ pixel->rgbRed = bgColor.rgbRed;
+ if (nBpp == 32)
+ pixel->rgbReserved = bgColor.rgbReserved;
+ }
+ }
+ }
+
+ if (!(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) ||
+ !(info_ptr = png_create_info_struct(png_ptr)))
+ goto error;
+
+ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ /* All future errors jump here */
+ WINE_ERR("png error\n");
+ goto error;
+ }
+
+ png_init_io(png_ptr, fPNGFile);
+ png_set_IHDR(png_ptr, info_ptr, nWidth, nHeight, 8,
+ color_type,
+ PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_DEFAULT,
+ PNG_FILTER_TYPE_DEFAULT);
+
+ png_write_info(png_ptr, info_ptr);
+ png_set_bgr(png_ptr);
+ for (i = nHeight - 1; i >= 0 ; i--)
+ png_write_row(png_ptr, (png_bytep)pXOR + nXORWidthBytes * i);
+ png_write_end(png_ptr, info_ptr);
+
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+ if (png_ptr) png_destroy_write_struct(&png_ptr, NULL);
+ fclose(fPNGFile);
+ return TRUE;
+
+ error:
+ if (png_ptr) png_destroy_write_struct(&png_ptr, NULL);
+ fclose(fPNGFile);
+ unlink(szPNGFileName);
+ return FALSE;
+}
+#endif
+
+static BOOL SaveIconResAsXPM(const BITMAPINFO *pIcon, char *szXPMFileName, LPCWSTR commentW)
{
FILE *fXPMFile;
- int nHeight;
+ int nWidth = pIcon->bmiHeader.biWidth;
+ int nHeight = pIcon->bmiHeader.biHeight;
+ int nBpp = pIcon->bmiHeader.biBitCount;
int nXORWidthBytes;
int nANDWidthBytes;
BOOL b8BitColors;
int nColors;
const BYTE *pXOR;
- const BYTE *pAND;
+ const BYTE *pAND = NULL;
BOOL aColorUsed[256] = {0};
int nColorsUsed = 0;
int i,j;
char *comment;
- if (!((pIcon->bmiHeader.biBitCount == 4) || (pIcon->bmiHeader.biBitCount == 8)))
+#ifdef HAVE_PNG_H
+ if (nBpp >= 24) return SaveIconResAsPNG(pIcon, szXPMFileName, commentW);
+#endif
+
+ if (nBpp != 4 && nBpp != 8)
{
WINE_FIXME("Unsupported color depth %d-bit\n", pIcon->bmiHeader.biBitCount);
return FALSE;
@@ -174,22 +286,21 @@ static BOOL SaveIconResAsXPM(const BITMA
comment = HeapAlloc(GetProcessHeap(), 0, i);
WideCharToMultiByte(CP_UNIXCP, 0, commentW, -1, comment, i, NULL, NULL);
- nHeight = pIcon->bmiHeader.biHeight / 2;
- nXORWidthBytes = 4 * ((pIcon->bmiHeader.biWidth * pIcon->bmiHeader.biBitCount / 32)
- + ((pIcon->bmiHeader.biWidth * pIcon->bmiHeader.biBitCount % 32) > 0));
- nANDWidthBytes = 4 * ((pIcon->bmiHeader.biWidth / 32)
- + ((pIcon->bmiHeader.biWidth % 32) > 0));
+ nXORWidthBytes = 4 * ((nWidth * nBpp + 31) / 32);
+ nANDWidthBytes = 4 * ((nWidth + 31) / 32);
b8BitColors = pIcon->bmiHeader.biBitCount == 8;
- nColors = pIcon->bmiHeader.biClrUsed ? pIcon->bmiHeader.biClrUsed
- : 1 << pIcon->bmiHeader.biBitCount;
+ nColors = pIcon->bmiHeader.biClrUsed ? pIcon->bmiHeader.biClrUsed : 1 << nBpp;
pXOR = (const BYTE*) pIcon + sizeof (BITMAPINFOHEADER) + (nColors * sizeof (RGBQUAD));
- pAND = pXOR + nHeight * nXORWidthBytes;
+ if (nHeight > nWidth)
+ {
+ nHeight /= 2; /* we have a mask */
+ pAND = pXOR + nHeight * nXORWidthBytes;
+ }
-#define MASK(x,y) (pAND[(x) / 8 + (nHeight - (y) - 1) * nANDWidthBytes] & (1 << (7 - (x) % 8)))
#define COLOR(x,y) (b8BitColors ? pXOR[(x) + (nHeight - (y) - 1) * nXORWidthBytes] : (x) % 2 ? pXOR[(x) / 2 + (nHeight - (y) - 1) * nXORWidthBytes] & 0xF : (pXOR[(x) / 2 + (nHeight - (y) - 1) * nXORWidthBytes] & 0xF0) >> 4)
for (i = 0; i < nHeight; i++) {
- for (j = 0; j < pIcon->bmiHeader.biWidth; j++) {
+ for (j = 0; j < nWidth; j++) {
if (!aColorUsed[COLOR(j,i)] && !MASK(j,i))
{
aColorUsed[COLOR(j,i)] = TRUE;
@@ -201,7 +312,7 @@ static BOOL SaveIconResAsXPM(const BITMA
if (fprintf(fXPMFile, "/* XPM */\n/* %s */\nstatic char *icon[] = {\n", comment) <= 0)
goto error;
if (fprintf(fXPMFile, "\"%d %d %d %d\",\n",
- (int) pIcon->bmiHeader.biWidth, nHeight, nColorsUsed + 1, 2) <=0)
+ (int) nWidth, nHeight, nColorsUsed + 1, 2) <=0)
goto error;
for (i = 0; i < nColors; i++) {
@@ -217,7 +328,7 @@ static BOOL SaveIconResAsXPM(const BITMA
{
if (fprintf(fXPMFile, ",\n\"") <= 0)
goto error;
- for (j = 0; j < pIcon->bmiHeader.biWidth; j++)
+ for (j = 0; j < nWidth; j++)
{
if MASK(j,i)
{
@@ -261,7 +372,7 @@ static BOOL CALLBACK EnumResNameProc(HMO
return TRUE;
}
-static BOOL extract_icon32(LPCWSTR szFileName, int nIndex, const char *szXPMFileName)
+static BOOL extract_icon32(LPCWSTR szFileName, int nIndex, char *szXPMFileName)
{
HMODULE hModule;
HRSRC hResInfo;
@@ -350,7 +461,7 @@ static BOOL extract_icon32(LPCWSTR szFil
return ret;
}
-static BOOL ExtractFromEXEDLL(LPCWSTR szFileName, int nIndex, const char *szXPMFileName)
+static BOOL ExtractFromEXEDLL(LPCWSTR szFileName, int nIndex, char *szXPMFileName)
{
if (!extract_icon32(szFileName, nIndex, szXPMFileName) /*&&
!extract_icon16(szFileName, szXPMFileName)*/)
@@ -358,14 +469,14 @@ static BOOL ExtractFromEXEDLL(LPCWSTR sz
return TRUE;
}
-static int ExtractFromICO(LPCWSTR szFileName, const char *szXPMFileName)
+static int ExtractFromICO(LPCWSTR szFileName, char *szXPMFileName)
{
FILE *fICOFile;
ICONDIR iconDir;
- ICONDIRENTRY *pIconDirEntry;
+ ICONDIRENTRY *pIconDirEntry = NULL;
int nMax = 0;
int nIndex = 0;
- void *pIcon;
+ BITMAPINFO *pIcon;
int i;
char *filename;
@@ -377,29 +488,44 @@ static int ExtractFromICO(LPCWSTR szFile
}
if (fread(&iconDir, sizeof (ICONDIR), 1, fICOFile) != 1 ||
- (iconDir.idReserved != 0) || (iconDir.idType != 1))
+ ((iconDir.idReserved != 0 || iconDir.idType != 1) &&
+ iconDir.idReserved != 0x4d42) )
{
- WINE_ERR("Invalid ico file format\n");
+ WINE_ERR("Invalid ico file format (%x)\n", iconDir.idType);
goto error2;
}
- if ((pIconDirEntry = HeapAlloc(GetProcessHeap(), 0, iconDir.idCount * sizeof (ICONDIRENTRY))) == NULL)
- goto error2;
- if (fread(pIconDirEntry, sizeof (ICONDIRENTRY), iconDir.idCount, fICOFile) != iconDir.idCount)
- goto error3;
+ /* It's a BMP */
+ if (iconDir.idReserved == 0x4d42)
+ {
+ BITMAPFILEHEADER *bfHeader = (BITMAPFILEHEADER *)&iconDir;
- for (i = 0; i < iconDir.idCount; i++)
- if ((pIconDirEntry[i].bHeight * pIconDirEntry[i].bWidth) > nMax)
- {
- nIndex = i;
- nMax = pIconDirEntry[i].bHeight * pIconDirEntry[i].bWidth;
- }
- if ((pIcon = HeapAlloc(GetProcessHeap(), 0, pIconDirEntry[nIndex].dwBytesInRes)) == NULL)
- goto error3;
- if (fseek(fICOFile, pIconDirEntry[nIndex].dwImageOffset, SEEK_SET))
- goto error4;
- if (fread(pIcon, pIconDirEntry[nIndex].dwBytesInRes, 1, fICOFile) != 1)
- goto error4;
+ if ((pIcon = HeapAlloc(GetProcessHeap(), 0, bfHeader->bfSize)) == NULL)
+ goto error3;
+ if (fseek(fICOFile, sizeof(BITMAPFILEHEADER), SEEK_SET) ||
+ fread(pIcon, bfHeader->bfSize - sizeof(BITMAPFILEHEADER), 1, fICOFile) != 1)
+ goto error4;
+ }
+ else
+ {
+ if ((pIconDirEntry = HeapAlloc(GetProcessHeap(), 0, iconDir.idCount * sizeof (ICONDIRENTRY))) == NULL)
+ goto error2;
+ if (fread(pIconDirEntry, sizeof (ICONDIRENTRY), iconDir.idCount, fICOFile) != iconDir.idCount)
+ goto error3;
+
+ for (i = 0; i < iconDir.idCount; i++)
+ if ((pIconDirEntry[i].bHeight * pIconDirEntry[i].bWidth) > nMax)
+ {
+ nIndex = i;
+ nMax = pIconDirEntry[i].bHeight * pIconDirEntry[i].bWidth;
+ }
+ if ((pIcon = HeapAlloc(GetProcessHeap(), 0, pIconDirEntry[nIndex].dwBytesInRes)) == NULL)
+ goto error3;
+ if (fseek(fICOFile, pIconDirEntry[nIndex].dwImageOffset, SEEK_SET))
+ goto error4;
+ if (fread(pIcon, pIconDirEntry[nIndex].dwBytesInRes, 1, fICOFile) != 1)
+ goto error4;
+ }
if(!SaveIconResAsXPM(pIcon, szXPMFileName, szFileName))
goto error4;
More information about the wine-patches
mailing list