source: libpipi/trunk/pipi/codec/gdiplus.cpp @ 3070

Last change on this file since 3070 was 3070, checked in by Sam Hocevar, 12 years ago

Full GDI+ load and save support.

  • Property svn:executable set to *
File size: 3.8 KB
Line 
1/*
2 *  libpipi       Pathetic image processing interface library
3 *  Copyright (c) 2004-2008 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id$
7 *
8 *  This library is free software. It comes without any warranty, to
9 *  the extent permitted by applicable law. You can redistribute it
10 *  and/or modify it under the terms of the Do What The Fuck You Want
11 *  To Public License, Version 2, as published by Sam Hocevar. See
12 *  http://sam.zoy.org/wtfpl/COPYING for more details.
13 */
14
15/*
16 * gdi.c: Windows GDI I/O functions (BMP only)
17 */
18
19#include "config.h"
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24
25#include <windows.h>
26#include <gdiplus.h>
27
28#include "pipi.h"
29#include "pipi_internals.h"
30
31extern "C" pipi_image_t *pipi_load_gdiplus(const char *name)
32{
33    size_t len;
34    if(mbstowcs_s(&len, NULL, 0, name, _TRUNCATE) != 0)
35        return NULL;
36    wchar_t *wname = new wchar_t[len];
37    if(mbstowcs_s(NULL, wname, len, name, _TRUNCATE) != 0)
38    {
39        delete[] wname;
40        return NULL;
41    }
42
43    ULONG_PTR token;
44    Gdiplus::GdiplusStartupInput input;
45    Gdiplus::GdiplusStartup(&token, &input, NULL);
46
47    Gdiplus::Bitmap *b = Gdiplus::Bitmap::FromFile(wname, 0);
48    if(!b)
49    {
50        delete[] wname;
51        return NULL;
52    }
53    delete[] wname;
54
55    Gdiplus::BitmapData bdata;
56    Gdiplus::Rect rect(0, 0, b->GetWidth(), b->GetHeight());
57
58    if(b->LockBits(&rect, Gdiplus::ImageLockModeRead,
59                   PixelFormat32bppARGB, &bdata) != Gdiplus::Ok)
60    {
61        delete b;
62        return NULL;
63    }
64
65    pipi_image_t *img = pipi_new(b->GetWidth(), b->GetHeight());
66    pipi_pixels_t *p = pipi_getpixels(img, PIPI_PIXELS_RGBA_C);
67    memcpy(p->pixels, bdata.Scan0, bdata.Width * bdata.Height * 4);
68
69    b->UnlockBits(&bdata);
70    delete b;
71
72    img->codec_priv = NULL;
73
74    img->wrap = 0;
75    img->u8 = 1;
76
77    return img;
78}
79
80extern "C" int pipi_save_gdiplus(pipi_image_t *img, const char *name)
81{
82    wchar_t const *fmt;
83    if(strstr(name, ".gif"))
84        fmt = L"image/gif";
85    else if(strstr(name, ".jpeg") || strstr(name, ".jpeg"))
86        fmt = L"image/jpeg";
87    else if(strstr(name, ".png"))
88        fmt = L"image/png";
89    else if(strstr(name, ".tiff"))
90        fmt = L"image/tiff";
91
92    unsigned int num = 0, size = 0;
93    Gdiplus::GetImageEncodersSize(&num, &size);
94    if(size == 0)
95        return -1;
96    Gdiplus::ImageCodecInfo *codecs
97        = (Gdiplus::ImageCodecInfo *)(malloc(size));
98    if(!codecs)
99        return -1;
100    Gdiplus::GetImageEncoders(num, size, codecs);
101    CLSID clsid;
102    for(unsigned int i = 0; i < num; i++)
103    {
104        if(wcscmp(codecs[i].MimeType, fmt) == 0)
105        {
106            clsid = codecs[i].Clsid;
107            break;
108        }
109    }
110
111    size_t len;
112    if(mbstowcs_s(&len, NULL, 0, name, _TRUNCATE) != 0)
113        return NULL;
114    wchar_t *wname = new wchar_t[len];
115    if(mbstowcs_s(NULL, wname, len, name, _TRUNCATE) != 0)
116    {
117        delete[] wname;
118        return -1;
119    }
120
121    ULONG_PTR token;
122    Gdiplus::GdiplusStartupInput input;
123    Gdiplus::GdiplusStartup(&token, &input, NULL);
124
125    Gdiplus::Bitmap *b = new Gdiplus::Bitmap(img->w, img->h,
126                                             PixelFormat32bppARGB);
127
128    Gdiplus::BitmapData bdata;
129    Gdiplus::Rect rect(0, 0, img->w, img->h);
130
131    if(b->LockBits(&rect, Gdiplus::ImageLockModeWrite,
132                   PixelFormat32bppARGB, &bdata) != Gdiplus::Ok)
133    {
134        delete b;
135        return -1;
136    }
137
138    pipi_pixels_t *p = pipi_getpixels(img, PIPI_PIXELS_RGBA_C);
139    memcpy(bdata.Scan0, p->pixels, bdata.Width * bdata.Height * 4);
140
141    b->UnlockBits(&bdata);
142
143    if(b->Save(wname, &clsid, NULL) != Gdiplus::Ok)
144    {
145        delete[] wname;
146        delete b;
147        return -1;
148    }
149    delete[] wname;
150    delete b;
151
152    return 0;
153}
154
155/*
156 * XXX: The following functions are local.
157 */
158
Note: See TracBrowser for help on using the repository browser.