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