1 |
///////////////////////////////////////////////////////////////////////////// |
2 |
// Name: src/common/imagxpm.cpp |
3 |
// Purpose: wxXPMHandler |
4 |
// Author: Vaclav Slavik, Robert Roebling |
5 |
// RCS-ID: $Id: imagxpm.cpp 53477 2008-05-07 07:28:57Z JS $ |
6 |
// Copyright: (c) 2001 Vaclav Slavik |
7 |
// Licence: wxWindows licence |
8 |
///////////////////////////////////////////////////////////////////////////// |
9 |
|
10 |
/* |
11 |
|
12 |
This file is partially based on source code of ImageMagick by John Cristy. Its |
13 |
license is as follows: |
14 |
|
15 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
16 |
% % |
17 |
% % |
18 |
% % |
19 |
% X X PPPP M M % |
20 |
% X X P P MM MM % |
21 |
% X PPPP M M M % |
22 |
% X X P M M % |
23 |
% X X P M M % |
24 |
% % |
25 |
% % |
26 |
% Read/Write ImageMagick Image Format. % |
27 |
% % |
28 |
% % |
29 |
% Software Design % |
30 |
% John Cristy % |
31 |
% July 1992 % |
32 |
% % |
33 |
% % |
34 |
% Copyright (C) 2001 ImageMagick Studio, a non-profit organization dedicated % |
35 |
% to making software imaging solutions freely available. % |
36 |
% % |
37 |
% Permission is hereby granted, free of charge, to any person obtaining a % |
38 |
% copy of this software and associated documentation files ("ImageMagick"), % |
39 |
% to deal in ImageMagick without restriction, including without limitation % |
40 |
% the rights to use, copy, modify, merge, publish, distribute, sublicense, % |
41 |
% and/or sell copies of ImageMagick, and to permit persons to whom the % |
42 |
% ImageMagick is furnished to do so, subject to the following conditions: % |
43 |
% % |
44 |
% The above copyright notice and this permission notice shall be included in % |
45 |
% all copies or substantial portions of ImageMagick. % |
46 |
% % |
47 |
% The software is provided "as is", without warranty of any kind, express or % |
48 |
% implied, including but not limited to the warranties of merchantability, % |
49 |
% fitness for a particular purpose and noninfringement. In no event shall % |
50 |
% ImageMagick Studio be liable for any claim, damages or other liability, % |
51 |
% whether in an action of contract, tort or otherwise, arising from, out of % |
52 |
% or in connection with ImageMagick or the use or other dealings in % |
53 |
% ImageMagick. % |
54 |
% % |
55 |
% Except as contained in this notice, the name of the ImageMagick Studio % |
56 |
% shall not be used in advertising or otherwise to promote the sale, use or % |
57 |
% other dealings in ImageMagick without prior written authorization from the % |
58 |
% ImageMagick Studio. % |
59 |
% % |
60 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
61 |
% |
62 |
% |
63 |
*/ |
64 |
|
65 |
// For compilers that support precompilation, includes "wx.h". |
66 |
#include "wx/wxprec.h" |
67 |
|
68 |
#ifdef __BORLANDC__ |
69 |
#pragma hdrstop |
70 |
#endif |
71 |
|
72 |
#if wxUSE_XPM |
73 |
|
74 |
#ifndef WX_PRECOMP |
75 |
#include "wx/log.h" |
76 |
#include "wx/intl.h" |
77 |
#include "wx/utils.h" |
78 |
#endif |
79 |
|
80 |
#include "wx/imagxpm.h" |
81 |
#include "wx/wfstream.h" |
82 |
#include "wx/xpmdecod.h" |
83 |
|
84 |
IMPLEMENT_DYNAMIC_CLASS(wxXPMHandler,wxImageHandler) |
85 |
|
86 |
//----------------------------------------------------------------------------- |
87 |
// wxXPMHandler |
88 |
//----------------------------------------------------------------------------- |
89 |
|
90 |
#if wxUSE_STREAMS |
91 |
|
92 |
bool wxXPMHandler::LoadFile(wxImage *image, |
93 |
wxInputStream& stream, |
94 |
bool WXUNUSED(verbose), int WXUNUSED(index)) |
95 |
{ |
96 |
wxXPMDecoder decoder; |
97 |
|
98 |
wxImage img = decoder.ReadFile(stream); |
99 |
if ( !img.Ok() ) |
100 |
return false; |
101 |
*image = img; |
102 |
return true; |
103 |
} |
104 |
|
105 |
bool wxXPMHandler::SaveFile(wxImage * image, |
106 |
wxOutputStream& stream, bool WXUNUSED(verbose)) |
107 |
{ |
108 |
// 1. count colours: |
109 |
#define MaxCixels 92 |
110 |
static const char Cixel[MaxCixels+1] = |
111 |
" .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjk" |
112 |
"lzxcvbnmMNBVCZASDFGHJKLPIUYTREWQ!~^/()_`'][{}|"; |
113 |
int i, j, k; |
114 |
|
115 |
wxImageHistogram histogram; |
116 |
int cols = int(image->ComputeHistogram(histogram)); |
117 |
|
118 |
int chars_per_pixel = 1; |
119 |
for ( k = MaxCixels; cols > k; k *= MaxCixels) |
120 |
chars_per_pixel++; |
121 |
|
122 |
// 2. write the header: |
123 |
wxString sName; |
124 |
if ( image->HasOption(wxIMAGE_OPTION_FILENAME) ) |
125 |
{ |
126 |
wxSplitPath(image->GetOption(wxIMAGE_OPTION_FILENAME), |
127 |
NULL, &sName, NULL); |
128 |
sName << wxT("_xpm"); |
129 |
} |
130 |
|
131 |
if ( !sName.empty() ) |
132 |
sName = wxString(wxT("/* XPM */\nstatic const char *")) + sName; |
133 |
else |
134 |
sName = wxT("/* XPM */\nstatic const char *xpm_data"); |
135 |
stream.Write( (const char*) sName.ToAscii(), sName.Len() ); |
136 |
|
137 |
char tmpbuf[200]; |
138 |
// VS: 200b is safe upper bound for anything produced by sprintf below |
139 |
// (<101 bytes the string, neither %i can expand into more than 10 chars) |
140 |
sprintf(tmpbuf, |
141 |
"[] = {\n" |
142 |
"/* columns rows colors chars-per-pixel */\n" |
143 |
"\"%i %i %i %i\",\n", |
144 |
image->GetWidth(), image->GetHeight(), cols, chars_per_pixel); |
145 |
stream.Write(tmpbuf, strlen(tmpbuf)); |
146 |
|
147 |
// 3. create color symbols table: |
148 |
char *symbols_data = new char[cols * (chars_per_pixel+1)]; |
149 |
char **symbols = new char*[cols]; |
150 |
|
151 |
// 2a. find mask colour: |
152 |
unsigned long mask_key = 0x1000000 /*invalid RGB value*/; |
153 |
if (image->HasMask()) |
154 |
mask_key = (image->GetMaskRed() << 16) | |
155 |
(image->GetMaskGreen() << 8) | image->GetMaskBlue(); |
156 |
|
157 |
// 2b. generate colour table: |
158 |
for (wxImageHistogram::iterator entry = histogram.begin(); |
159 |
entry != histogram.end(); ++entry ) |
160 |
{ |
161 |
unsigned long index = entry->second.index; |
162 |
symbols[index] = symbols_data + index * (chars_per_pixel+1); |
163 |
char *sym = symbols[index]; |
164 |
|
165 |
for (j = 0; j < chars_per_pixel; j++) |
166 |
{ |
167 |
sym[j] = Cixel[index % MaxCixels]; |
168 |
index /= MaxCixels; |
169 |
} |
170 |
sym[j] = '\0'; |
171 |
|
172 |
unsigned long key = entry->first; |
173 |
|
174 |
if (key == 0) |
175 |
sprintf( tmpbuf, "\"%s c Black\",\n", sym); |
176 |
else if (key == mask_key) |
177 |
sprintf( tmpbuf, "\"%s c None\",\n", sym); |
178 |
else |
179 |
{ |
180 |
wxByte r = wxByte(key >> 16); |
181 |
wxByte g = wxByte(key >> 8); |
182 |
wxByte b = wxByte(key); |
183 |
sprintf(tmpbuf, "\"%s c #%02X%02X%02X\",\n", sym, r, g, b); |
184 |
} |
185 |
stream.Write( tmpbuf, strlen(tmpbuf) ); |
186 |
} |
187 |
|
188 |
stream.Write("/* pixels */\n", 13); |
189 |
|
190 |
unsigned char *data = image->GetData(); |
191 |
for (j = 0; j < image->GetHeight(); j++) |
192 |
{ |
193 |
char tmp_c; |
194 |
tmp_c = '\"'; stream.Write(&tmp_c, 1); |
195 |
for (i = 0; i < image->GetWidth(); i++, data += 3) |
196 |
{ |
197 |
unsigned long key = (data[0] << 16) | (data[1] << 8) | (data[2]); |
198 |
stream.Write(symbols[histogram[key].index], chars_per_pixel); |
199 |
} |
200 |
tmp_c = '\"'; stream.Write(&tmp_c, 1); |
201 |
if ( j + 1 < image->GetHeight() ) |
202 |
{ |
203 |
tmp_c = ','; stream.Write(&tmp_c, 1); |
204 |
} |
205 |
tmp_c = '\n'; stream.Write(&tmp_c, 1); |
206 |
} |
207 |
stream.Write("};\n", 3 ); |
208 |
|
209 |
// Clean up: |
210 |
delete[] symbols; |
211 |
delete[] symbols_data; |
212 |
|
213 |
return true; |
214 |
} |
215 |
|
216 |
bool wxXPMHandler::DoCanRead(wxInputStream& stream) |
217 |
{ |
218 |
wxXPMDecoder decoder; |
219 |
return decoder.CanRead(stream); |
220 |
} |
221 |
|
222 |
#endif // wxUSE_STREAMS |
223 |
|
224 |
#endif // wxUSE_XPM |