WEBP Windows Solution for Visual Studio 2008

143 views
Skip to first unread message

palisade

unread,
Oct 3, 2010, 7:24:33 PM10/3/10
to WebP Discussion
I've come up with a webp Visual Studio 2008 (I used express but it
should work with any version) solution that compiles webp.exe for
Windows.

I was able to convert a jpeg to webp with it successfully.

The solution is entirely self-encapsulated and includes everything
needed to compile, no need to go download additional libraries or
source.

Hope this helps someone out there.

RapidShare Link:
http://rapidshare.com/files/422961110/webp.zip

Cheers,
Nelson Rush

Pierre Joye

unread,
Oct 3, 2010, 7:57:58 PM10/3/10
to webp-d...@webmproject.org
hi Nelson,

It seems that the file has been deleted.

I've sent something about windows and ANSI C fixes earlier today, see
the thread "ansi C, windows fixes.". It contains a Makefile and a
patch against current development tree (which is different from what
you can see in the initial release).

Cheers,

> --
> You received this message because you are subscribed to the Google Groups "WebP Discussion" group.
> To post to this group, send email to webp-d...@webmproject.org.
> To unsubscribe from this group, send email to webp-discuss...@webmproject.org.
> For more options, visit this group at http://groups.google.com/a/webmproject.org/group/webp-discuss/?hl=en.
>
>

--
Pierre

@pierrejoye | http://blog.thepimp.net | http://www.libgd.org

palisade

unread,
Oct 3, 2010, 10:45:15 PM10/3/10
to WebP Discussion
Sorry about that:

http://www.mediafire.com/?3xo35mhauqthdg9

I've noticed the BMP conversion code doesn't quite work correctly in
lept. I noticed this because I'm writing a WebpToMemoryBmp function
that makes use of the included BMP streaming code in order to write a
native Windows WEBP picture viewer.

I'm making fixes to it on my side, those fixes aren't included in this
zip. All of the other image formats convert correctly from what I can
tell.

-
Nelson Rush

palisade

unread,
Oct 3, 2010, 10:47:54 PM10/3/10
to WebP Discussion
It is worth noting that one of the advantages to my solution is that
I've pruned all of the unnecessary parts of code away.

Nelson

palisade

unread,
Oct 3, 2010, 10:51:16 PM10/3/10
to WebP Discussion
NOTE: You can safely remove the LINK to libs\leptonlib-static-mtdll-
debug.lib in the project, it isn't necessary. The select code needed
from lepton is directly integrated into the project now.

palisade

unread,
Oct 3, 2010, 11:04:57 PM10/3/10
to WebP Discussion
http://i457.photobucket.com/albums/qq292/landwaster/webpissue1.jpg

There's a screenshot of the issue I'm encountering.

The image was originally a shade of blue, and I figured out it was a
endian swapping mistake. The other problem I noticed that I haven't
nailed down yet is that the image is slightly shifted/wrapping from
left-to-right.

Any ideas? Here's the code:

struct MBUFFER { void *dst; DWORD offset; };

size_t mwrite(void *src, size_t size, size_t count, MBUFFER *mp)
{
size_t length = size * count;
memmove((unsigned char*)mp->dst + mp->offset, src, length);
mp->offset += length;
return count;
}

unsigned char *pixWriteMemoryBmp(size_t &size, PIX *pix)
{
MBUFFER *mp = (MBUFFER*)malloc(sizeof(MBUFFER));
unsigned int offbytes, filebytes, fileimagebytes;
int width, height, depth, d, xres, yres;
unsigned short bfType, bfSize, bfFill1, bfReserved1, bfReserved2;
unsigned short bfOffBits, bfFill2, biPlanes, biBitCount;
unsigned short sval;
unsigned int biSize, biWidth, biHeight, biCompression,
biSizeImage;
unsigned int biXPelsPerMeter, biYPelsPerMeter, biClrUsed,
biClrImportant;
int pixWpl, pixBpl, extrabytes, writeerror;
int fileBpl, fileWpl;
int i, j, k;
int heapcm; // extra copy of cta on the heap ? 1 : 0
unsigned char *data;
unsigned char pel[4];
unsigned int *line, *pword;
PIXCMAP *cmap;
unsigned char *cta; // address of the bmp color table array
int cmaplen; // number of bytes in the bmp colormap
int ncolors, val, stepsize;
RGBA_QUAD *pquad;

if (!pix) {
fprintf(stderr, "%s: pix not defined\n", __FUNCTION__);
if (mp) free(mp);
return NULL;
}

width = pix->w;
height = pix->h;
d = pix->d;

if (d == 2) {
fprintf(stderr, "%s: writing 2 bpp bmp memory; nobody else can
read\n", __FUNCTION__);
}

depth = d;
if (d == 32)
depth = 24;

xres = (int)(39.37 * (float)pix->xres + 0.5); // to ppm
yres = (int)(39.37 * (float)pix->yres + 0.5); // to ppm

pixWpl = pix->wpl;
pixBpl = 4 * pixWpl;

fileWpl = (width * depth + 31) / 32;
fileBpl = 4 * fileWpl;

fileimagebytes = height * fileBpl;

heapcm = 0;
if (d == 32) { // 24 bpp rgb; no colormap
ncolors = 0;
cmaplen = 0;
}
else if ((cmap = pixGetColormap(pix))) { // existing colormap
ncolors = pixcmapGetCount(cmap);
cmaplen = ncolors * sizeof(RGBA_QUAD);
cta = (unsigned char *)cmap->array;
}
else { // no existing colormap; make a binary or gray one
if (d == 1) {
cmaplen = sizeof(bwmap);
ncolors = 2;
cta = (unsigned char *)bwmap;
}
else { // d != 32; output grayscale version
ncolors = 1 << depth;
cmaplen = ncolors * sizeof(RGBA_QUAD);

heapcm = 1;
if ((cta = (unsigned char *)calloc(cmaplen, 1)) == NULL) {
fprintf(stderr, "%s: colormap alloc fail\n",
__FUNCTION__);
if (mp) free(mp);
return NULL;
}

stepsize = 255 / (ncolors - 1);
for (i = 0, val = 0, pquad = (RGBA_QUAD *)cta;
i < ncolors;
i++, val += stepsize, pquad++) {
pquad->blue = pquad->green = pquad->red = val;
}
}
}

#if DEBUG
{unsigned char *pcmptr;
pcmptr = (unsigned char *)pixGetColormap(pix)->array;
fprintf(stderr, "Pix colormap[0] = %c%c%c%d\n",
pcmptr[0], pcmptr[1], pcmptr[2], pcmptr[3]);
fprintf(stderr, "Pix colormap[1] = %c%c%c%d\n",
pcmptr[4], pcmptr[5], pcmptr[6], pcmptr[7]);
}
#endif // DEBUG

// Convert to little-endian and write the file header data
bfType = convertOnBigEnd16(BMP_ID);
offbytes = BMP_FHBYTES + BMP_IHBYTES + cmaplen;

filebytes = offbytes + fileimagebytes;
sval = filebytes & 0x0000ffff;

bfSize = convertOnBigEnd16(sval);
sval = (filebytes >> 16) & 0x0000ffff;

bfFill1 = convertOnBigEnd16(sval);
bfReserved1 = 0;
bfReserved2 = 0;

sval = offbytes & 0x0000ffff;
bfOffBits = convertOnBigEnd16(sval);

sval = (offbytes >> 16) & 0x0000ffff;
bfFill2 = convertOnBigEnd16(sval);

size = filebytes;

unsigned char *mem = NULL;
if ((mem = (unsigned char *)calloc(filebytes, 1)) == NULL) {
fprintf(stderr, "%s: bmp alloc fail\n", __FUNCTION__);
if (mp) free(mp);
return NULL;
}

mp->dst = mem;
mp->offset = 0;

mwrite(&bfType, 1, 2, mp);
mwrite(&bfSize, 1, 2, mp);
mwrite(&bfFill1, 1, 2, mp);
mwrite(&bfReserved1, 1, 2, mp);
mwrite(&bfReserved1, 1, 2, mp);
mwrite(&bfOffBits, 1, 2, mp);
mwrite(&bfFill2, 1, 2, mp);

// Convert to little-endian and write the info header data
biSize = convertOnBigEnd32(BMP_IHBYTES);
biWidth = convertOnBigEnd32(width);
biHeight = convertOnBigEnd32(height);
biPlanes = convertOnBigEnd16(1);
biBitCount = convertOnBigEnd16(depth);
biCompression = 0;

biSizeImage = convertOnBigEnd32(fileimagebytes);
biXPelsPerMeter = convertOnBigEnd32(xres);
biYPelsPerMeter = convertOnBigEnd32(yres);
biClrUsed = convertOnBigEnd32(ncolors);
biClrImportant = convertOnBigEnd32(ncolors);

mwrite(&biSize, 1, 4, mp);
mwrite(&biWidth, 1, 4, mp);
mwrite(&biHeight, 1, 4, mp);
mwrite(&biPlanes, 1, 2, mp);
mwrite(&biBitCount, 1, 2, mp);
mwrite(&biCompression, 1, 4, mp);
mwrite(&biSizeImage, 1, 4, mp);
mwrite(&biXPelsPerMeter, 1, 4, mp);
mwrite(&biYPelsPerMeter, 1, 4, mp);
mwrite(&biClrUsed, 1, 4, mp);
mwrite(&biClrImportant, 1, 4, mp);

// Write the colormap data
if (ncolors > 0) {
if (mwrite(cta, 1, cmaplen, mp) != cmaplen) {
if (heapcm) free(cta);
if (mp && mp->dst) free(mp->dst);
fprintf(stderr, "%s: colormap write fail\n",
__FUNCTION__);
if (mp) free(mp);
return NULL;
}
if (heapcm) free(cta);
}

// When you write a binary image with a colormap
// that sets BLACK to 0, you must invert the data
if (depth == 1 && cmap && ((unsigned char *)(cmap->array))[0] ==
0x0) {
pixInvert(pix, pix);
}

pixEndianByteSwap(pix);

writeerror = 0;
if (depth != 24) { // typ 1 or 8 bpp
data = (unsigned char *)pixGetData(pix) + pixBpl * (height -
1);
for (i = 0; i < height; i++) {
if (mwrite(data, 1, fileBpl, mp) != fileBpl)
writeerror = 1;
data -= pixBpl;
}
}
else {
/* 32 bpp pix; 24 bpp file
* See the comments in pixReadStreamBMP() to
* understand the logic behind the pixel ordering below.
* Note that we have again done an endian swap on
* little endian machines before arriving here, so that
* the bytes are ordered on both platforms as:
Red Green Blue --
|-----------|------------|-----------|-----------|
*/
extrabytes = fileBpl - 3 * width;
line = pixGetData(pix) + pixWpl * (height - 1);

for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
pword = line + j;

pel[1] = *((unsigned char *)pword + COLOR_RED);
pel[0] = *((unsigned char *)pword + COLOR_GREEN);
pel[2] = *((unsigned char *)pword + COLOR_BLUE);

if (mwrite(&pel, 1, 3, mp) != 3)
writeerror = 1;
}

if (extrabytes) {
for (k = 0; k < extrabytes; k++)
mwrite(&pel, 1, 1, mp);
}

line -= pixWpl;
}
}

// Restore to original state
pixEndianByteSwap(pix);

if (depth == 1 && cmap && ((unsigned char *)(cmap->array))[0] ==
0x0)
pixInvert(pix, pix);

if (writeerror) {
if (mp && mp->dst) free(mp->dst);
fprintf(stderr, "%s: image write fail\n", __FUNCTION__);
if (mp) free(mp);
return NULL;
}

unsigned char *buf = (unsigned char *)mp->dst;
if (mp) free(mp);

return buf;
}

unsigned char *WebpToMemoryBmp(size_t &size, PIX *pix)
{
if (!pix) {
fprintf(stderr, "%s: pix not defined\n", __FUNCTION__);
return NULL;
}

unsigned char *buf = NULL;
if ((buf = pixWriteMemoryBmp(size, pix)) == NULL) {
fprintf(stderr, "%s: pix not written to mem\n", __FUNCTION__);
return NULL;
}

return buf;
}

int main()
{
struct Pix *pixs;

puts("begin");
pixs = pixReadWebP("beep.webp");

if (pixs == NULL) {
fprintf(stderr, "Failed to read image\n");
return 1;
} else {
puts("read webp");
}

size_t size = 0;
unsigned char *buf = NULL;

if ((buf = WebpToMemoryBmp(size, pixs)) == NULL) {
fprintf(stderr, "Failed to copy image to memory bmp\n");
} else {
puts("converted to memory bmp");
}

pixDestroy(&pixs);
puts("freed");

FILE *fp = fopen("c:\\test.bmp", "wb");
fwrite(buf, size, 1, fp);
fclose(fp);

if (buf) free(buf);

return 0;
}

MaxSt

unread,
Oct 4, 2010, 5:52:46 AM10/4/10
to WebP Discussion
Thanks a lot, palisade.

I have some suggestions:

1. Please make sure Release target compiles as well.
2. output_dir option doesn't work, because isdir() always returns 0.

Thanks.
Reply all
Reply to author
Forward
0 new messages