git-svn-id: file:///srv/caca.zoy.org/var/lib/svn/libpipi/trunk@3070 92316355-f0b4-4df1-b90c-862c8a59935fremotes/tiles
@@ -50,6 +50,10 @@ pipi_image_t *pipi_load(char const *name) | |||
if(!ret) | |||
ret = pipi_load_sdl(name); | |||
#endif | |||
#if USE_GDIPLUS | |||
if(!ret) | |||
ret = pipi_load_gdiplus(name); | |||
#endif | |||
#if USE_GDI | |||
if(!ret) | |||
ret = pipi_load_gdi(name); | |||
@@ -94,14 +98,14 @@ int pipi_save(pipi_image_t *img, const char *name) | |||
if(ret < 0) | |||
ret = pipi_save_sdl(img, name); | |||
#endif | |||
#if USE_GDI | |||
if(ret < 0) | |||
ret = pipi_save_gdi(img, name); | |||
#endif | |||
#if USE_GDIPLUS | |||
if(ret < 0) | |||
ret = pipi_save_gdiplus(img, name); | |||
#endif | |||
#if USE_GDI | |||
if(ret < 0) | |||
ret = pipi_save_gdi(img, name); | |||
#endif | |||
#if USE_COCOA | |||
if(ret < 0) | |||
ret = pipi_save_coreimage(img, name); | |||
@@ -23,117 +23,131 @@ | |||
#include <string.h> | |||
#include <windows.h> | |||
#include <gdiplus.h> | |||
#include "pipi.h" | |||
#include "pipi_internals.h" | |||
extern "C" pipi_image_t *pipi_load_gdiplus(const char *name) | |||
{ | |||
BITMAPINFO binfo; | |||
pipi_image_t *img; | |||
pipi_pixels_t *p; | |||
uint8_t *data; | |||
HBITMAP hbmap; | |||
HDC hdc; | |||
hbmap = (HBITMAP)LoadImage(NULL, name, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); | |||
if(!hbmap) | |||
size_t len; | |||
if(mbstowcs_s(&len, NULL, 0, name, _TRUNCATE) != 0) | |||
return NULL; | |||
wchar_t *wname = new wchar_t[len]; | |||
if(mbstowcs_s(NULL, wname, len, name, _TRUNCATE) != 0) | |||
{ | |||
delete[] wname; | |||
return NULL; | |||
} | |||
hdc = CreateCompatibleDC(NULL); | |||
SelectObject(hdc, hbmap); | |||
ULONG_PTR token; | |||
Gdiplus::GdiplusStartupInput input; | |||
Gdiplus::GdiplusStartup(&token, &input, NULL); | |||
memset(&binfo, 0, sizeof(binfo)); | |||
binfo.bmiHeader.biSize = sizeof(binfo.bmiHeader); | |||
if(!GetDIBits(hdc, hbmap, 0, 0, 0, &binfo, DIB_RGB_COLORS)) | |||
Gdiplus::Bitmap *b = Gdiplus::Bitmap::FromFile(wname, 0); | |||
if(!b) | |||
{ | |||
ReleaseDC(0, hdc); | |||
DeleteObject(hbmap); | |||
delete[] wname; | |||
return NULL; | |||
} | |||
delete[] wname; | |||
img = pipi_new(binfo.bmiHeader.biWidth, binfo.bmiHeader.biHeight); | |||
p = pipi_getpixels(img, PIPI_PIXELS_RGBA_C); | |||
data = (uint8_t *)p->pixels; | |||
Gdiplus::BitmapData bdata; | |||
Gdiplus::Rect rect(0, 0, b->GetWidth(), b->GetHeight()); | |||
binfo.bmiHeader.biBitCount = 32; | |||
binfo.bmiHeader.biCompression = BI_RGB; | |||
binfo.bmiHeader.biHeight = - abs(binfo.bmiHeader.biHeight); | |||
if(!GetDIBits(hdc, hbmap, 0, abs(binfo.bmiHeader.biHeight), data, | |||
&binfo, DIB_RGB_COLORS)) | |||
if(b->LockBits(&rect, Gdiplus::ImageLockModeRead, | |||
PixelFormat32bppARGB, &bdata) != Gdiplus::Ok) | |||
{ | |||
ReleaseDC(0, hdc); | |||
DeleteObject(hbmap); | |||
delete b; | |||
return NULL; | |||
} | |||
/* FIXME: do we need to swap bytes? Apparently Vista doesn't need it, | |||
* but we'd need a more thorough test. */ | |||
pipi_image_t *img = pipi_new(b->GetWidth(), b->GetHeight()); | |||
pipi_pixels_t *p = pipi_getpixels(img, PIPI_PIXELS_RGBA_C); | |||
memcpy(p->pixels, bdata.Scan0, bdata.Width * bdata.Height * 4); | |||
b->UnlockBits(&bdata); | |||
delete b; | |||
img->codec_priv = NULL; | |||
img->wrap = 0; | |||
img->u8 = 1; | |||
ReleaseDC(0, hdc); | |||
DeleteObject(hbmap); | |||
return img; | |||
} | |||
extern "C" int pipi_save_gdiplus(pipi_image_t *img, const char *name) | |||
{ | |||
BITMAPINFOHEADER binfo; | |||
BITMAPFILEHEADER bfheader; | |||
uint8_t dummy[4] = { 0 }; | |||
HANDLE hfile; | |||
pipi_pixels_t *p; | |||
DWORD ret = 0; | |||
uint8_t *data; | |||
int x, y, padding; | |||
p = pipi_getpixels(img, PIPI_PIXELS_RGBA_C); | |||
data = (uint8_t *)p->pixels; | |||
padding = ((img->w * 3) + 3) / 4 * 4 - img->w * 3; | |||
memset(&binfo, 0, sizeof(binfo)); | |||
binfo.biSize = sizeof(binfo); | |||
binfo.biWidth = img->w; | |||
binfo.biHeight = img->h; | |||
binfo.biPlanes = 1; | |||
binfo.biBitCount = 24; | |||
binfo.biCompression = BI_RGB; | |||
binfo.biSizeImage = (img->w * 3 + padding) * img->h; | |||
memset(&bfheader, 0, sizeof(bfheader)); | |||
bfheader.bfType = 0x4D42; | |||
bfheader.bfOffBits = sizeof(bfheader) + sizeof(binfo); | |||
bfheader.bfSize = bfheader.bfOffBits + binfo.biSizeImage; | |||
/* We don’t even create the bitmap object, since we know exactly | |||
* what kind of file we are saving. But later, when we support | |||
* different depths and BMP options, we'll need to care about it. */ | |||
hfile = CreateFile(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, | |||
FILE_ATTRIBUTE_ARCHIVE, NULL); | |||
if(!hfile) | |||
wchar_t const *fmt; | |||
if(strstr(name, ".gif")) | |||
fmt = L"image/gif"; | |||
else if(strstr(name, ".jpeg") || strstr(name, ".jpeg")) | |||
fmt = L"image/jpeg"; | |||
else if(strstr(name, ".png")) | |||
fmt = L"image/png"; | |||
else if(strstr(name, ".tiff")) | |||
fmt = L"image/tiff"; | |||
unsigned int num = 0, size = 0; | |||
Gdiplus::GetImageEncodersSize(&num, &size); | |||
if(size == 0) | |||
return -1; | |||
Gdiplus::ImageCodecInfo *codecs | |||
= (Gdiplus::ImageCodecInfo *)(malloc(size)); | |||
if(!codecs) | |||
return -1; | |||
WriteFile(hfile, &bfheader, sizeof(bfheader), &ret, NULL); | |||
WriteFile(hfile, &binfo, sizeof(binfo), &ret, NULL); | |||
for(y = 0; y < img->h; y++) | |||
Gdiplus::GetImageEncoders(num, size, codecs); | |||
CLSID clsid; | |||
for(unsigned int i = 0; i < num; i++) | |||
{ | |||
for(x = 0; x < img->w; x++) | |||
if(wcscmp(codecs[i].MimeType, fmt) == 0) | |||
{ | |||
uint8_t tmp[3]; | |||
tmp[0] = data[4 * (img->w * (img->h - 1 - y) + x) + 0]; | |||
tmp[1] = data[4 * (img->w * (img->h - 1 - y) + x) + 1]; | |||
tmp[2] = data[4 * (img->w * (img->h - 1 - y) + x) + 2]; | |||
WriteFile(hfile, tmp, 3, &ret, NULL); | |||
clsid = codecs[i].Clsid; | |||
break; | |||
} | |||
if(padding) | |||
WriteFile(hfile, dummy, padding, &ret, NULL); | |||
} | |||
CloseHandle(hfile); | |||
size_t len; | |||
if(mbstowcs_s(&len, NULL, 0, name, _TRUNCATE) != 0) | |||
return NULL; | |||
wchar_t *wname = new wchar_t[len]; | |||
if(mbstowcs_s(NULL, wname, len, name, _TRUNCATE) != 0) | |||
{ | |||
delete[] wname; | |||
return -1; | |||
} | |||
ULONG_PTR token; | |||
Gdiplus::GdiplusStartupInput input; | |||
Gdiplus::GdiplusStartup(&token, &input, NULL); | |||
Gdiplus::Bitmap *b = new Gdiplus::Bitmap(img->w, img->h, | |||
PixelFormat32bppARGB); | |||
Gdiplus::BitmapData bdata; | |||
Gdiplus::Rect rect(0, 0, img->w, img->h); | |||
if(b->LockBits(&rect, Gdiplus::ImageLockModeWrite, | |||
PixelFormat32bppARGB, &bdata) != Gdiplus::Ok) | |||
{ | |||
delete b; | |||
return -1; | |||
} | |||
pipi_pixels_t *p = pipi_getpixels(img, PIPI_PIXELS_RGBA_C); | |||
memcpy(bdata.Scan0, p->pixels, bdata.Width * bdata.Height * 4); | |||
b->UnlockBits(&bdata); | |||
if(b->Save(wname, &clsid, NULL) != Gdiplus::Ok) | |||
{ | |||
delete[] wname; | |||
delete b; | |||
return -1; | |||
} | |||
delete[] wname; | |||
delete b; | |||
return 0; | |||
} | |||
@@ -1,7 +1,7 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<VisualStudioProject | |||
ProjectType="Visual C++" | |||
Version="8.00" | |||
Version="8,00" | |||
Name="libpipi" | |||
ProjectGUID="{48A34C3A-1E36-49B7-92C4-E982FDCB90C0}" | |||
RootNamespace="libpipi" | |||
@@ -60,6 +60,7 @@ | |||
/> | |||
<Tool | |||
Name="VCLinkerTool" | |||
AdditionalDependencies="gdiplus.lib" | |||
OutputFile="$(OutDir)\$(ProjectName)-0.dll" | |||
LinkIncremental="2" | |||
GenerateDebugInformation="true" | |||
@@ -133,6 +134,7 @@ | |||
/> | |||
<Tool | |||
Name="VCLinkerTool" | |||
AdditionalDependencies="gdiplus.lib" | |||
OutputFile="$(OutDir)\$(ProjectName)-0.dll" | |||
LinkIncremental="2" | |||
GenerateDebugInformation="true" | |||
@@ -215,26 +217,10 @@ | |||
RelativePath=".\accessors.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\filter\autocontrast.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\paint\bezier.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\filter\blur.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\codec.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\filter\color.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\colorstring.c" | |||
> | |||
@@ -243,82 +229,14 @@ | |||
RelativePath=".\context.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\filter\convolution.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\dither\dbs.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\filter\dilate.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\dither.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\dither\ediff.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\paint\floodfill.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\codec\gdi.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\codec\gdiplus.cpp" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\histogram\histogram.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\paint\line.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\combine\mean.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\measure.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\filter\median.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\combine\minmax.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\combine\mulscreen.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\render\noise.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\dither\ordered.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\codec\oric.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\dither\ostromoukhov.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\pipi.c" | |||
> | |||
@@ -327,10 +245,6 @@ | |||
RelativePath=".\pixels.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\dither\random.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\quantize\reduce.c" | |||
> | |||
@@ -339,30 +253,146 @@ | |||
RelativePath=".\resize.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\combine\rgb.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\render\screen.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\stock.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\combine\subadd.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\paint\tile.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\filter\transform.c" | |||
> | |||
</File> | |||
<Filter | |||
Name="codec" | |||
> | |||
<File | |||
RelativePath=".\codec\gdi.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\codec\gdiplus.cpp" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\codec\oric.c" | |||
> | |||
</File> | |||
</Filter> | |||
<Filter | |||
Name="combine" | |||
> | |||
<File | |||
RelativePath=".\combine\mean.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\combine\minmax.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\combine\mulscreen.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\combine\rgb.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\combine\subadd.c" | |||
> | |||
</File> | |||
</Filter> | |||
<Filter | |||
Name="dither" | |||
> | |||
<File | |||
RelativePath=".\dither\dbs.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\dither\ediff.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\dither\ordered.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\dither\ostromoukhov.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\dither\random.c" | |||
> | |||
</File> | |||
</Filter> | |||
<Filter | |||
Name="filter" | |||
> | |||
<File | |||
RelativePath=".\filter\autocontrast.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\filter\blur.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\filter\color.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\filter\convolution.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\filter\dilate.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\filter\median.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\filter\transform.c" | |||
> | |||
</File> | |||
</Filter> | |||
<Filter | |||
Name="histogram" | |||
> | |||
<File | |||
RelativePath=".\histogram\histogram.c" | |||
> | |||
</File> | |||
</Filter> | |||
<Filter | |||
Name="paint" | |||
> | |||
<File | |||
RelativePath=".\paint\bezier.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\paint\floodfill.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\paint\line.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\paint\tile.c" | |||
> | |||
</File> | |||
</Filter> | |||
<Filter | |||
Name="render" | |||
> | |||
<File | |||
RelativePath=".\render\noise.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath=".\render\screen.c" | |||
> | |||
</File> | |||
</Filter> | |||
</Filter> | |||
</Files> | |||
<Globals> | |||