1 //-----------------------------------------------------------------------------
2 //
3 // ImageLib Sources
4 // Copyright (C) 2000-2009 by Denton Woods
5 // Last modified: 03/07/2009
6 //
7 // Filename: src-IL/src/il_mng.c
8 //
9 // Description: Multiple Network Graphics (.mng) functions
10 //
11 //-----------------------------------------------------------------------------
12
13 #include "il_internal.h"
14 #ifndef IL_NO_MNG
15 #define MNG_SUPPORT_READ
16 #define MNG_SUPPORT_WRITE
17 #define MNG_SUPPORT_DISPLAY
18
19 #ifdef _WIN32
20 //#define MNG_USE_SO
21 #endif
22
23 #if defined(_WIN32) && defined(IL_USE_PRAGMA_LIBS)
24 #if defined(_MSC_VER) || defined(__BORLANDC__)
25 #ifndef _DEBUG
26 #pragma comment(lib, "libmng.lib")
27 #pragma comment(lib, "lcms.lib")
28 #pragma comment(lib, "libjpeg.lib")
29 #pragma comment(lib, "zlib.lib")
30 #else
31 #pragma comment(lib, "libmng-d.lib")
32 #pragma comment(lib, "lcms-d.lib")
33 #pragma comment(lib, "libjpeg-d.lib")
34 #pragma comment(lib, "zlib-d.lib")
35 #endif
36 #endif
37 #endif
38
39
40 #if defined(_MSC_VER)
41 #pragma warning(push)
42 #pragma warning(disable : 4142) // Redefinition in jmorecfg.h
43 #endif
44
45 #include <libmng.h>
46
47 #if defined(_MSC_VER)
48 #pragma warning(pop)
49 #endif
50
51
52 //---------------------------------------------------------------------------------------------
53 // memory allocation; data must be zeroed
54 //---------------------------------------------------------------------------------------------
mymngalloc(mng_size_t size)55 mng_ptr MNG_DECL mymngalloc(mng_size_t size)
56 {
57 return (mng_ptr)icalloc(1, size);
58 }
59
60
61 //---------------------------------------------------------------------------------------------
62 // memory deallocation
63 //---------------------------------------------------------------------------------------------
mymngfree(mng_ptr p,mng_size_t size)64 void MNG_DECL mymngfree(mng_ptr p, mng_size_t size)
65 {
66 ifree(p);
67 }
68
69
70 //---------------------------------------------------------------------------------------------
71 // Stream open:
72 //---------------------------------------------------------------------------------------------
mymngopenstream(mng_handle mng)73 mng_bool MNG_DECL mymngopenstream(mng_handle mng)
74 {
75 return MNG_TRUE;
76 }
77
78
79 //---------------------------------------------------------------------------------------------
80 // Stream open for Writing:
81 //---------------------------------------------------------------------------------------------
mymngopenstreamwrite(mng_handle mng)82 mng_bool MNG_DECL mymngopenstreamwrite(mng_handle mng)
83 {
84 return MNG_TRUE;
85 }
86
87
88 //---------------------------------------------------------------------------------------------
89 // Stream close:
90 //---------------------------------------------------------------------------------------------
mymngclosestream(mng_handle mng)91 mng_bool MNG_DECL mymngclosestream(mng_handle mng)
92 {
93 return MNG_TRUE; // We close the file ourself, mng_cleanup doesnt seem to do it...
94 }
95
96
97 //---------------------------------------------------------------------------------------------
98 // feed data to the decoder
99 //---------------------------------------------------------------------------------------------
mymngreadstream(mng_handle mng,mng_ptr buffer,mng_size_t size,mng_uint32 * bytesread)100 mng_bool MNG_DECL mymngreadstream(mng_handle mng, mng_ptr buffer, mng_size_t size, mng_uint32 *bytesread)
101 {
102 // read the requested amount of data from the file
103 *bytesread = iread(buffer, 1, (ILuint)size);
104
105 return MNG_TRUE;
106 }
107
108
109 //---------------------------------------------------------------------------------------------
110 // callback for writing data
111 //---------------------------------------------------------------------------------------------
mymngwritedata(mng_handle mng,mng_ptr buffer,mng_size_t size,mng_uint32 * byteswritten)112 mng_bool MNG_DECL mymngwritedata(mng_handle mng, mng_ptr buffer, mng_size_t size, mng_uint32 *byteswritten)
113 {
114 *byteswritten = iwrite(buffer, 1, (ILuint)size);
115
116 if (*byteswritten < size) {
117 ilSetError(IL_FILE_WRITE_ERROR);
118 return MNG_FALSE;
119 }
120
121 return MNG_TRUE;
122 }
123
124
125 //---------------------------------------------------------------------------------------------
126 // the header's been read. set up the display stuff
127 //---------------------------------------------------------------------------------------------
mymngprocessheader(mng_handle mng,mng_uint32 width,mng_uint32 height)128 mng_bool MNG_DECL mymngprocessheader(mng_handle mng, mng_uint32 width, mng_uint32 height)
129 {
130 ILuint AlphaDepth;
131
132 AlphaDepth = mng_get_alphadepth(mng);
133
134 if (AlphaDepth == 0) {
135 ilTexImage(width, height, 1, 3, IL_BGR, IL_UNSIGNED_BYTE, NULL);
136 iCurImage->Origin = IL_ORIGIN_LOWER_LEFT;
137 mng_set_canvasstyle(mng, MNG_CANVAS_BGR8);
138 }
139 else { // Use alpha channel
140 ilTexImage(width, height, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL);
141 iCurImage->Origin = IL_ORIGIN_LOWER_LEFT;
142 mng_set_canvasstyle(mng, MNG_CANVAS_BGRA8);
143 }
144
145 iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
146
147 return MNG_TRUE;
148 }
149
150
151 //---------------------------------------------------------------------------------------------
152 // return a row pointer for the decoder to fill
153 //---------------------------------------------------------------------------------------------
mymnggetcanvasline(mng_handle mng,mng_uint32 line)154 mng_ptr MNG_DECL mymnggetcanvasline(mng_handle mng, mng_uint32 line)
155 {
156 return (mng_ptr)(iCurImage->Data + iCurImage->Bps * line);
157 }
158
159
160 //---------------------------------------------------------------------------------------------
161 // timer
162 //---------------------------------------------------------------------------------------------
mymnggetticks(mng_handle mng)163 mng_uint32 MNG_DECL mymnggetticks(mng_handle mng)
164 {
165 return 0;
166 }
167
168
169 //---------------------------------------------------------------------------------------------
170 // Refresh:
171 //---------------------------------------------------------------------------------------------
mymngrefresh(mng_handle mng,mng_uint32 x,mng_uint32 y,mng_uint32 w,mng_uint32 h)172 mng_bool MNG_DECL mymngrefresh(mng_handle mng, mng_uint32 x, mng_uint32 y, mng_uint32 w, mng_uint32 h)
173 {
174 return MNG_TRUE;
175 }
176
177
178 //---------------------------------------------------------------------------------------------
179 // interframe delay callback
180 //---------------------------------------------------------------------------------------------
mymngsettimer(mng_handle mng,mng_uint32 msecs)181 mng_bool MNG_DECL mymngsettimer(mng_handle mng, mng_uint32 msecs)
182 {
183 return MNG_TRUE;
184 }
185
186
187
188 // Make this do something different soon!
189
190 //---------------------------------------------------------------------------------------------
191 // Error Callback;
192 //---------------------------------------------------------------------------------------------
mymngerror(mng_handle mng,mng_int32 code,mng_int8 severity,mng_chunkid chunktype,mng_uint32 chunkseq,mng_int32 extra1,mng_int32 extra2,mng_pchar text)193 mng_bool MNG_DECL mymngerror(
194 mng_handle mng, mng_int32 code, mng_int8 severity,
195 mng_chunkid chunktype, mng_uint32 chunkseq,
196 mng_int32 extra1, mng_int32 extra2, mng_pchar text
197 )
198 {
199 // error occured;
200 return MNG_FALSE;
201 }
202
203
204 ILboolean iLoadMngInternal(void);
205
206 // Reads a file
ilLoadMng(ILconst_string FileName)207 ILboolean ilLoadMng(ILconst_string FileName)
208 {
209 ILHANDLE MngFile;
210 ILboolean bMng = IL_FALSE;
211
212 MngFile = iopenr(FileName);
213 if (MngFile == NULL) {
214 ilSetError(IL_COULD_NOT_OPEN_FILE);
215 return bMng;
216 }
217
218 bMng = ilLoadMngF(MngFile);
219 icloser(MngFile);
220
221 return bMng;
222 }
223
224
225 // Reads an already-opened file
ilLoadMngF(ILHANDLE File)226 ILboolean ilLoadMngF(ILHANDLE File)
227 {
228 ILuint FirstPos;
229 ILboolean bRet;
230
231 iSetInputFile(File);
232 FirstPos = itell();
233 bRet = iLoadMngInternal();
234 iseek(FirstPos, IL_SEEK_SET);
235
236 return bRet;
237 }
238
239
240 // Reads from a memory "lump"
ilLoadMngL(const void * Lump,ILuint Size)241 ILboolean ilLoadMngL(const void *Lump, ILuint Size)
242 {
243 iSetInputLump(Lump, Size);
244 return iLoadMngInternal();
245 }
246
247
iLoadMngInternal()248 ILboolean iLoadMngInternal()
249 {
250 mng_handle mng;
251
252 if (iCurImage == NULL) {
253 ilSetError(IL_ILLEGAL_OPERATION);
254 return IL_FALSE;
255 }
256
257 mng = mng_initialize(MNG_NULL, mymngalloc, mymngfree, MNG_NULL);
258 if (mng == MNG_NULL) {
259 ilSetError(IL_LIB_MNG_ERROR);
260 return IL_FALSE;
261 }
262
263 // If .mng background is available, use it.
264 mng_set_usebkgd(mng, MNG_TRUE);
265
266 // Set the callbacks.
267 mng_setcb_errorproc(mng, mymngerror);
268 mng_setcb_openstream(mng, mymngopenstream);
269 mng_setcb_closestream(mng, mymngclosestream);
270 mng_setcb_readdata(mng, (mng_readdata)mymngreadstream);
271 mng_setcb_gettickcount(mng, mymnggetticks);
272 mng_setcb_settimer(mng, mymngsettimer);
273 mng_setcb_processheader(mng, mymngprocessheader);
274 mng_setcb_getcanvasline(mng, mymnggetcanvasline);
275 mng_setcb_refresh(mng, mymngrefresh);
276
277 mng_read(mng);
278 mng_display(mng);
279
280 return ilFixImage();
281 }
282
283
284 ILboolean iSaveMngInternal(void);
285
286 //! Writes a Mng file
ilSaveMng(const ILstring FileName)287 ILboolean ilSaveMng(const ILstring FileName)
288 {
289 ILHANDLE MngFile;
290 ILuint MngSize;
291
292 if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) {
293 if (iFileExists(FileName)) {
294 ilSetError(IL_FILE_ALREADY_EXISTS);
295 return IL_FALSE;
296 }
297 }
298
299 MngFile = iopenw(FileName);
300 if (MngFile == NULL) {
301 ilSetError(IL_COULD_NOT_OPEN_FILE);
302 return IL_FALSE;
303 }
304
305 MngSize = ilSaveMngF(MngFile);
306 iclosew(MngFile);
307
308 if (MngSize == 0)
309 return IL_FALSE;
310 return IL_TRUE;
311 }
312
313
314 //! Writes a Mng to an already-opened file
ilSaveMngF(ILHANDLE File)315 ILuint ilSaveMngF(ILHANDLE File)
316 {
317 ILuint Pos = itellw();
318 iSetOutputFile(File);
319 if (iSaveMngInternal() == IL_FALSE)
320 return 0; // Error occurred
321 return itellw() - Pos; // Return the number of bytes written.
322 }
323
324
325 //! Writes a Mng to a memory "lump"
ilSaveMngL(void * Lump,ILuint Size)326 ILuint ilSaveMngL(void *Lump, ILuint Size)
327 {
328 ILuint Pos;
329 iSetOutputLump(Lump, Size);
330 Pos = itellw();
331 if (iSaveMngInternal() == IL_FALSE)
332 return 0; // Error occurred
333 return itellw() - Pos; // Return the number of bytes written.
334 }
335
336
337 // Internal function used to save the Mng.
iSaveMngInternal()338 ILboolean iSaveMngInternal()
339 {
340 //mng_handle mng;
341
342 // Not working yet, so just error out.
343 ilSetError(IL_INVALID_EXTENSION);
344 return IL_FALSE;
345
346 //if (iCurImage == NULL) {
347 // ilSetError(IL_ILLEGAL_OPERATION);
348 // return IL_FALSE;
349 //}
350
351 //mng = mng_initialize(MNG_NULL, mymngalloc, mymngfree, MNG_NULL);
352 //if (mng == MNG_NULL) {
353 // ilSetError(IL_LIB_MNG_ERROR);
354 // return IL_FALSE;
355 //}
356
357 //mng_setcb_openstream(mng, mymngopenstreamwrite);
358 //mng_setcb_closestream(mng, mymngclosestream);
359 //mng_setcb_writedata(mng, mymngwritedata);
360
361 //// Write File:
362 // mng_create(mng);
363
364 //// Check return value.
365 //mng_putchunk_mhdr(mng, iCurImage->Width, iCurImage->Height, 1000, 3, 1, 3, 0x0047);
366 //mng_putchunk_basi(mng, iCurImage->Width, iCurImage->Height, 8, MNG_COLORTYPE_RGB, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 1);
367 //mng_putchunk_iend(mng);
368 //mng_putimgdata_ihdr(mng, iCurImage->Width, iCurImage->Height, MNG_COLORTYPE_RGB, 8, 0, 0, 0, 0, mymnggetcanvasline);
369
370 //// Now write file:
371 //mng_write(mng);
372
373 //mng_cleanup(&mng);
374
375 //return IL_TRUE;
376 }
377
378 #endif//IL_NO_MNG
379