~ubuntu-branches/ubuntu/raring/simutrans/raring-proposed

« back to all changes in this revision

Viewing changes to simsys_w32_png.cc

  • Committer: Package Import Robot
  • Author(s): Ansgar Burchardt
  • Date: 2011-11-03 19:59:02 UTC
  • mfrom: (1.2.7)
  • Revision ID: package-import@ubuntu.com-20111103195902-uopgwf488mfctb75
Tags: 111.0-1
* New upstream release.
* debian/rules: Update get-orig-source target for new upstream release.
* Use xz compression for source and binary packages.
* Use override_* targets to simplify debian/rules.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "macros.h"
 
2
#include "simmem.h"
 
3
#include "simsys_w32_png.h"
 
4
 
 
5
#include <stdio.h>
 
6
 
 
7
#ifndef _WIN32
 
8
#error "Only Windows has GDI+!"
 
9
#endif
 
10
 
 
11
// windows Bibliotheken DirectDraw 5.x
 
12
// windows.h defines min and max macros which we don't want
 
13
#define NOMINMAX 1
 
14
#include <windows.h>
 
15
 
 
16
// structures, since we use the C-interface
 
17
struct ImageCodecInfo
 
18
{
 
19
        CLSID Clsid;
 
20
        GUID  FormatID;
 
21
        const WCHAR* CodecName;
 
22
        const WCHAR* DllName;
 
23
        const WCHAR* FormatDescription;
 
24
        const WCHAR* FilenameExtension;
 
25
        const WCHAR* MimeType;
 
26
        DWORD Flags;
 
27
        DWORD Version;
 
28
        DWORD SigCount;
 
29
        DWORD SigSize;
 
30
        const BYTE* SigPattern;
 
31
        const BYTE* SigMask;
 
32
};
 
33
 
 
34
#define    PixelFormatIndexed      0x00010000 // Indexes into a palette
 
35
#define    PixelFormatGDI          0x00020000 // Is a GDI-supported format
 
36
#define    PixelFormat8bppIndexed     (3 | ( 8 << 8) | PixelFormatIndexed | PixelFormatGDI)
 
37
#define    PixelFormat16bppRGB555     (5 | (16 << 8) | PixelFormatGDI)
 
38
#define    PixelFormat16bppRGB565     (6 | (16 << 8) | PixelFormatGDI)
 
39
#define    PixelFormat24bppRGB        (8 | (24 << 8) | PixelFormatGDI)
 
40
 
 
41
struct EncoderParameters;
 
42
 
 
43
struct GdiplusStartupInput
 
44
{
 
45
    UINT32 GdiplusVersion;             // Must be 1
 
46
    void *DebugEventCallback; // Ignored on free builds
 
47
    BOOL SuppressBackgroundThread;     // FALSE unless you're prepared to call
 
48
                                       // the hook/unhook functions properly
 
49
    BOOL SuppressExternalCodecs;       // FALSE unless you want GDI+ only to use
 
50
                                       // its internal image codecs.
 
51
};
 
52
 
 
53
// and the functions from the library
 
54
static int (WINAPI* GdiplusStartup)(ULONG_PTR* token, GdiplusStartupInput* size, void*);
 
55
static int (WINAPI* GdiplusShutdown)(ULONG_PTR token);
 
56
static int (WINAPI* GdipGetImageEncodersSize)(UINT* numEncoders, UINT* size);
 
57
static int (WINAPI* GdipGetImageEncoders)(UINT numEncoders, UINT size, ImageCodecInfo* encoders);
 
58
static int (WINAPI* GdipCreateBitmapFromScan0)(INT width, INT height, INT stride, INT PixelFormat, BYTE* scan0, ULONG** bitmap);
 
59
static int (WINAPI* GdipDeleteCachedBitmap)(ULONG* image);
 
60
static int (WINAPI* GdipSaveImageToFile)(ULONG* image, WCHAR const* filename, CLSID const* clsidEncoder, EncoderParameters const* encoderParams);
 
61
 
 
62
 
 
63
// Die GetEncoderClsid() Funktion wurde einfach aus der MSDN/PSDK Doku kopiert.
 
64
// Zu finden mit dem Suchstring "Retrieving the Class Identifier for an Encoder"
 
65
// Sucht zu z.B. 'image/jpeg' den passenden Encoder und liefert dessen CLSID...
 
66
static int GetEncoderClsid(wchar_t const* const format, CLSID* const pClsid)
 
67
{
 
68
        UINT  num = 0;          // number of image encoders
 
69
        UINT  size = 0;         // size of the image encoder array in bytes
 
70
        UINT j;
 
71
        ImageCodecInfo* pImageCodecInfo = NULL;
 
72
 
 
73
        GdipGetImageEncodersSize(&num, &size);
 
74
 
 
75
        if(size == 0) return -1;  // Failure
 
76
 
 
77
        pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
 
78
        if(pImageCodecInfo == NULL) return -1;  // Failure
 
79
 
 
80
        GdipGetImageEncoders(num, size, pImageCodecInfo);
 
81
 
 
82
        for(  j = 0; j < num; ++j  ) {
 
83
                if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 ) {
 
84
                        *pClsid = pImageCodecInfo[j].Clsid;
 
85
                        free(pImageCodecInfo);
 
86
                        return j;  // Success
 
87
                }
 
88
        }
 
89
 
 
90
        free(pImageCodecInfo);
 
91
        return -1;  // Failure
 
92
}
 
93
 
 
94
 
 
95
template<typename T> static void GetProcAddress(T& dst, HMODULE const module, char const* const procname)
 
96
{
 
97
        dst = reinterpret_cast<T>(GetProcAddress(module, procname));
 
98
}
 
99
 
 
100
 
 
101
/* this works only, if gdiplus.dll is there.
 
102
 * It should be there on
 
103
 * Windows XP and newer
 
104
 * On Win98 and up, if .NET is installed
 
105
 */
 
106
int dr_screenshot_png(const char *filename,  int w, int h, int maxwidth, unsigned short *data, int bitdepth )
 
107
{
 
108
        // first we try as PNG
 
109
        CLSID encoderClsid;
 
110
        int ok=FALSE;
 
111
        ULONG *myImage = NULL;
 
112
        GdiplusStartupInput gdiplusStartupInput;
 
113
        ULONG_PTR gdiplusToken;
 
114
 
 
115
        HMODULE hGDIplus = LoadLibraryA( "gdiplus.dll" );
 
116
        if(hGDIplus==NULL) {
 
117
                return FALSE;
 
118
        }
 
119
 
 
120
        // retrieve names ...
 
121
        GetProcAddress(GdiplusStartup,            hGDIplus, "GdiplusStartup");
 
122
        GetProcAddress(GdiplusShutdown,           hGDIplus, "GdiplusShutdown");
 
123
        GetProcAddress(GdipGetImageEncodersSize,  hGDIplus, "GdipGetImageEncodersSize");
 
124
        GetProcAddress(GdipGetImageEncoders,      hGDIplus, "GdipGetImageEncoders");
 
125
        GetProcAddress(GdipCreateBitmapFromScan0, hGDIplus, "GdipCreateBitmapFromScan0");
 
126
        GetProcAddress(GdipDeleteCachedBitmap,    hGDIplus, "GdipDeleteCachedBitmap");
 
127
        GetProcAddress(GdipSaveImageToFile,       hGDIplus, "GdipSaveImageToFile");
 
128
 
 
129
        /* Win2k can do without init, WinXP not ... */
 
130
        gdiplusStartupInput.GdiplusVersion = 1;
 
131
        gdiplusStartupInput.DebugEventCallback = NULL;
 
132
        gdiplusStartupInput.SuppressBackgroundThread = FALSE;
 
133
        gdiplusStartupInput.SuppressExternalCodecs = FALSE;
 
134
        GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
 
135
 
 
136
        if(  bitdepth==8  ) {
 
137
                GdipCreateBitmapFromScan0(w, h, maxwidth, PixelFormat8bppIndexed , (BYTE*)data, &myImage);
 
138
        }
 
139
        else {
 
140
                GdipCreateBitmapFromScan0(w, h, maxwidth * 2, bitdepth == 16 ? PixelFormat16bppRGB565 : PixelFormat16bppRGB555, (BYTE*)data, &myImage);
 
141
        }
 
142
        if(  myImage==NULL  &&  bitdepth>8  ) {
 
143
                /* we may have XP or newer => have to convert them to 32 first to save them ... Grrrr */
 
144
                BYTE* const newdata = MALLOCN(BYTE, w * h * 4);
 
145
                BYTE *dest = newdata;
 
146
                unsigned short *src = data;
 
147
                int ww = maxwidth;
 
148
                int x, y;
 
149
 
 
150
                for(  y=0;  y<h;  y++  ) {
 
151
                        for(  x=0;  x<w;  x++  ) {
 
152
                                unsigned short color = src[x];
 
153
                                *dest++ = (color & 0xF800)>>8;
 
154
                                *dest++ = (color & 0x07E0)>>3;
 
155
                                *dest++ = (color & 0x001F)<<5;
 
156
                                *dest++ = 0xFF;
 
157
                        }
 
158
                        src += ww;
 
159
                }
 
160
                GdipCreateBitmapFromScan0(w, h, w * 4, PixelFormat24bppRGB, newdata, &myImage);
 
161
                free( newdata );
 
162
        }
 
163
 
 
164
        // Passenden Encoder f�r jpegs suchen:
 
165
        // Genausogut kann man auch image/png benutzen um png's zu speichern ;D
 
166
        // ...oder image/gif um gif's zu speichern, ...
 
167
        if(myImage!=NULL  &&  GetEncoderClsid(L"image/png", &encoderClsid)!=-1) {
 
168
                char cfilename[1024];
 
169
                sprintf(cfilename, "%.*s.png", (int)(strlen(filename) - 4), filename);
 
170
 
 
171
                WCHAR wfilename[1024];
 
172
                MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, cfilename, -1, wfilename, lengthof(wfilename));
 
173
 
 
174
                if (GdipSaveImageToFile(myImage, wfilename, &encoderClsid, 0) == 0) {
 
175
                        ok = TRUE;
 
176
                }
 
177
                else {
 
178
                        //printf( filename, "Save() for png failed!\n");
 
179
                }
 
180
        }
 
181
        else {
 
182
                //printf( filename, "No encoder for 'image/jpeg' found!\n");
 
183
        }
 
184
 
 
185
        // GDI+ freigeben:
 
186
        GdipDeleteCachedBitmap(myImage);
 
187
        GdiplusShutdown(gdiplusToken);
 
188
        FreeLibrary( hGDIplus );
 
189
 
 
190
        return ok;
 
191
}