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

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

libpipi: the GDI+ codec defaults to BMP when the file extension is unknown.

  • 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
27#include <Gdiplus.h>
28
29extern "C" {
30#include "pipi.h"
31#include "pipi_internals.h"
32}
33
34extern "C" pipi_image_t *pipi_load_gdiplus(const char *name)
35{
36    size_t len;
37    len = mbstowcs(NULL, name, 0);
38    wchar_t *wname = new wchar_t[len + 1];
39    if(mbstowcs(wname, name, len + 1) == (size_t)-1)
40    {
41        delete[] wname;
42        return NULL;
43    }
44
45    ULONG_PTR token;
46    Gdiplus::GdiplusStartupInput input;
47    Gdiplus::GdiplusStartup(&token, &input, NULL);
48
49    Gdiplus::Bitmap *b = Gdiplus::Bitmap::FromFile(wname, 0);
50    if(!b)
51    {
52        delete[] wname;
53        return NULL;
54    }
55    delete[] wname;
56
57    Gdiplus::BitmapData bdata;
58    Gdiplus::Rect rect(0, 0, b->GetWidth(), b->GetHeight());
59
60    if(b->LockBits(&rect, Gdiplus::ImageLockModeRead,
61                   PixelFormat32bppARGB, &bdata) != Gdiplus::Ok)
62    {
63        delete b;
64        return NULL;
65    }
66
67    pipi_image_t *img = pipi_new(b->GetWidth(), b->GetHeight());
68    pipi_pixels_t *p = pipi_getpixels(img, PIPI_PIXELS_RGBA_C);
69    memcpy(p->pixels, bdata.Scan0, bdata.Width * bdata.Height * 4);
70
71    b->UnlockBits(&bdata);
72    delete b;
73
74    img->codec_priv = NULL;
75
76    img->wrap = 0;
77    img->u8 = 1;
78
79    return img;
80}
81
82extern "C" int pipi_save_gdiplus(pipi_image_t *img, const char *name)
83{
84    wchar_t const *fmt;
85    if(strstr(name, ".gif"))
86        fmt = L"image/gif";
87    else if(strstr(name, ".jpeg") || strstr(name, ".jpeg"))
88        fmt = L"image/jpeg";
89    else if(strstr(name, ".png"))
90        fmt = L"image/png";
91    else if(strstr(name, ".tiff"))
92        fmt = L"image/tiff";
93    else /* if(strstr(name, ".bmp")) */
94        fmt = L"image/bmp";
95
96    unsigned int num = 0, size = 0;
97    Gdiplus::GetImageEncodersSize(&num, &size);
98    if(size == 0)
99        return -1;
100    Gdiplus::ImageCodecInfo *codecs
101        = (Gdiplus::ImageCodecInfo *)(malloc(size));
102    if(!codecs)
103        return -1;
104    Gdiplus::GetImageEncoders(num, size, codecs);
105    CLSID clsid;
106    for(unsigned int i = 0; i < num; i++)
107    {
108        if(wcscmp(codecs[i].MimeType, fmt) == 0)
109        {
110            clsid = codecs[i].Clsid;
111            break;
112        }
113    }
114
115    size_t len;
116    len = mbstowcs(NULL, name, 0);
117    wchar_t *wname = new wchar_t[len + 1];
118    if(mbstowcs(wname, name, len + 1) == (size_t)-1)
119    {
120        delete[] wname;
121        return -1;
122    }
123
124    ULONG_PTR token;
125    Gdiplus::GdiplusStartupInput input;
126    Gdiplus::GdiplusStartup(&token, &input, NULL);
127
128    Gdiplus::Bitmap *b = new Gdiplus::Bitmap(img->w, img->h,
129                                             PixelFormat32bppARGB);
130
131    Gdiplus::BitmapData bdata;
132    Gdiplus::Rect rect(0, 0, img->w, img->h);
133
134    if(b->LockBits(&rect, (unsigned int)Gdiplus::ImageLockModeWrite,
135                   PixelFormat32bppARGB, &bdata) != Gdiplus::Ok)
136    {
137        delete b;
138        return -1;
139    }
140
141    pipi_pixels_t *p = pipi_getpixels(img, PIPI_PIXELS_RGBA_C);
142    memcpy(bdata.Scan0, p->pixels, bdata.Width * bdata.Height * 4);
143
144    b->UnlockBits(&bdata);
145
146    if(b->Save(wname, &clsid, NULL) != Gdiplus::Ok)
147    {
148        delete[] wname;
149        delete b;
150        return -1;
151    }
152    delete[] wname;
153    delete b;
154
155    return 0;
156}
157
158/*
159 * XXX: The following functions are local.
160 */
161
Note: See TracBrowser for help on using the repository browser.