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) | if(!ret) | ||||
| ret = pipi_load_sdl(name); | ret = pipi_load_sdl(name); | ||||
| #endif | #endif | ||||
| #if USE_GDIPLUS | |||||
| if(!ret) | |||||
| ret = pipi_load_gdiplus(name); | |||||
| #endif | |||||
| #if USE_GDI | #if USE_GDI | ||||
| if(!ret) | if(!ret) | ||||
| ret = pipi_load_gdi(name); | ret = pipi_load_gdi(name); | ||||
| @@ -94,14 +98,14 @@ int pipi_save(pipi_image_t *img, const char *name) | |||||
| if(ret < 0) | if(ret < 0) | ||||
| ret = pipi_save_sdl(img, name); | ret = pipi_save_sdl(img, name); | ||||
| #endif | #endif | ||||
| #if USE_GDI | |||||
| if(ret < 0) | |||||
| ret = pipi_save_gdi(img, name); | |||||
| #endif | |||||
| #if USE_GDIPLUS | #if USE_GDIPLUS | ||||
| if(ret < 0) | if(ret < 0) | ||||
| ret = pipi_save_gdiplus(img, name); | ret = pipi_save_gdiplus(img, name); | ||||
| #endif | #endif | ||||
| #if USE_GDI | |||||
| if(ret < 0) | |||||
| ret = pipi_save_gdi(img, name); | |||||
| #endif | |||||
| #if USE_COCOA | #if USE_COCOA | ||||
| if(ret < 0) | if(ret < 0) | ||||
| ret = pipi_save_coreimage(img, name); | ret = pipi_save_coreimage(img, name); | ||||
| @@ -23,117 +23,131 @@ | |||||
| #include <string.h> | #include <string.h> | ||||
| #include <windows.h> | #include <windows.h> | ||||
| #include <gdiplus.h> | |||||
| #include "pipi.h" | #include "pipi.h" | ||||
| #include "pipi_internals.h" | #include "pipi_internals.h" | ||||
| extern "C" pipi_image_t *pipi_load_gdiplus(const char *name) | 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; | 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; | 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; | 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->codec_priv = NULL; | ||||
| img->wrap = 0; | img->wrap = 0; | ||||
| img->u8 = 1; | img->u8 = 1; | ||||
| ReleaseDC(0, hdc); | |||||
| DeleteObject(hbmap); | |||||
| return img; | return img; | ||||
| } | } | ||||
| extern "C" int pipi_save_gdiplus(pipi_image_t *img, const char *name) | 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; | 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; | return 0; | ||||
| } | } | ||||
| @@ -1,7 +1,7 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||||
| <VisualStudioProject | <VisualStudioProject | ||||
| ProjectType="Visual C++" | ProjectType="Visual C++" | ||||
| Version="8.00" | |||||
| Version="8,00" | |||||
| Name="libpipi" | Name="libpipi" | ||||
| ProjectGUID="{48A34C3A-1E36-49B7-92C4-E982FDCB90C0}" | ProjectGUID="{48A34C3A-1E36-49B7-92C4-E982FDCB90C0}" | ||||
| RootNamespace="libpipi" | RootNamespace="libpipi" | ||||
| @@ -60,6 +60,7 @@ | |||||
| /> | /> | ||||
| <Tool | <Tool | ||||
| Name="VCLinkerTool" | Name="VCLinkerTool" | ||||
| AdditionalDependencies="gdiplus.lib" | |||||
| OutputFile="$(OutDir)\$(ProjectName)-0.dll" | OutputFile="$(OutDir)\$(ProjectName)-0.dll" | ||||
| LinkIncremental="2" | LinkIncremental="2" | ||||
| GenerateDebugInformation="true" | GenerateDebugInformation="true" | ||||
| @@ -133,6 +134,7 @@ | |||||
| /> | /> | ||||
| <Tool | <Tool | ||||
| Name="VCLinkerTool" | Name="VCLinkerTool" | ||||
| AdditionalDependencies="gdiplus.lib" | |||||
| OutputFile="$(OutDir)\$(ProjectName)-0.dll" | OutputFile="$(OutDir)\$(ProjectName)-0.dll" | ||||
| LinkIncremental="2" | LinkIncremental="2" | ||||
| GenerateDebugInformation="true" | GenerateDebugInformation="true" | ||||
| @@ -215,26 +217,10 @@ | |||||
| RelativePath=".\accessors.c" | RelativePath=".\accessors.c" | ||||
| > | > | ||||
| </File> | </File> | ||||
| <File | |||||
| RelativePath=".\filter\autocontrast.c" | |||||
| > | |||||
| </File> | |||||
| <File | |||||
| RelativePath=".\paint\bezier.c" | |||||
| > | |||||
| </File> | |||||
| <File | |||||
| RelativePath=".\filter\blur.c" | |||||
| > | |||||
| </File> | |||||
| <File | <File | ||||
| RelativePath=".\codec.c" | RelativePath=".\codec.c" | ||||
| > | > | ||||
| </File> | </File> | ||||
| <File | |||||
| RelativePath=".\filter\color.c" | |||||
| > | |||||
| </File> | |||||
| <File | <File | ||||
| RelativePath=".\colorstring.c" | RelativePath=".\colorstring.c" | ||||
| > | > | ||||
| @@ -243,82 +229,14 @@ | |||||
| RelativePath=".\context.c" | RelativePath=".\context.c" | ||||
| > | > | ||||
| </File> | </File> | ||||
| <File | |||||
| RelativePath=".\filter\convolution.c" | |||||
| > | |||||
| </File> | |||||
| <File | |||||
| RelativePath=".\dither\dbs.c" | |||||
| > | |||||
| </File> | |||||
| <File | |||||
| RelativePath=".\filter\dilate.c" | |||||
| > | |||||
| </File> | |||||
| <File | <File | ||||
| RelativePath=".\dither.c" | RelativePath=".\dither.c" | ||||
| > | > | ||||
| </File> | </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 | <File | ||||
| RelativePath=".\measure.c" | RelativePath=".\measure.c" | ||||
| > | > | ||||
| </File> | </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 | <File | ||||
| RelativePath=".\pipi.c" | RelativePath=".\pipi.c" | ||||
| > | > | ||||
| @@ -327,10 +245,6 @@ | |||||
| RelativePath=".\pixels.c" | RelativePath=".\pixels.c" | ||||
| > | > | ||||
| </File> | </File> | ||||
| <File | |||||
| RelativePath=".\dither\random.c" | |||||
| > | |||||
| </File> | |||||
| <File | <File | ||||
| RelativePath=".\quantize\reduce.c" | RelativePath=".\quantize\reduce.c" | ||||
| > | > | ||||
| @@ -339,30 +253,146 @@ | |||||
| RelativePath=".\resize.c" | RelativePath=".\resize.c" | ||||
| > | > | ||||
| </File> | </File> | ||||
| <File | |||||
| RelativePath=".\combine\rgb.c" | |||||
| > | |||||
| </File> | |||||
| <File | |||||
| RelativePath=".\render\screen.c" | |||||
| > | |||||
| </File> | |||||
| <File | <File | ||||
| RelativePath=".\stock.c" | RelativePath=".\stock.c" | ||||
| > | > | ||||
| </File> | </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> | </Filter> | ||||
| </Files> | </Files> | ||||
| <Globals> | <Globals> | ||||