Current News
Archived News
Search News
Discussion Forum


Old Forum
Install Programs More Downloads...
Troubleshooting
Source Code
Format Specs.
Misc. Information
Non-SF Stuff
Links




CommitLineData
14362b19 1#include "grpapi.h"\r
ecca31ff 2#include "../LoadStorm/storm.h"\r
14362b19 3#include <malloc.h>\r
4\r
5#ifdef GRPAPI_STATIC\r
6#define DllMain GrpMain\r
7\r
8#include "grp_static.h"\r
9\r
10struct GRPLIBMODULE {\r
11 GRPLIBMODULE();\r
12 ~GRPLIBMODULE();\r
13} GrpLib;\r
14\r
15BOOL APIENTRY DllMain(HINSTANCE hInstDLL, DWORD ul_reason_for_call, LPVOID lpReserved);\r
16\r
17GRPLIBMODULE::GRPLIBMODULE()\r
18{\r
19 GrpMain(0,DLL_PROCESS_ATTACH,0);\r
20}\r
21\r
22GRPLIBMODULE::~GRPLIBMODULE()\r
23{\r
24 GrpMain(0,DLL_PROCESS_DETACH,0);\r
25}\r
26\r
27#endif\r
28\r
29typedef struct {\r
30 BYTE Left;\r
31 BYTE Top;\r
32 BYTE Width;\r
33 BYTE Height;\r
34 DWORD Offset;\r
35} FRAMEHEADER;\r
36\r
c483a082 37typedef struct {\r
38 WORD *lpRowOffsets;\r
39 WORD *lpRowSizes;\r
40 LPBYTE *lpRowData;\r
41} FRAMEDATA;\r
42\r
ecca31ff 43GETPIXELPROC MyGetPixel = GetPixel;\r
44SETPIXELPROC MySetPixel = (SETPIXELPROC)SetPixelV;\r
45\r
ff024783 46void __inline SetPix(HDC hDC, int X, int Y, COLORREF clrColor, DWORD *dwPalette, DWORD dwFlags, DWORD dwAlpha);\r
c483a082 47void EncodeFrameData(signed short *lpImageData, WORD nFrame, GRPHEADER *lpGrpHeader, FRAMEHEADER *lpFrameHeader, FRAMEDATA *lpFrameData);\r
0df81049 48BOOL VerifyRow(signed short *lpRawRow, int nWidth, LPBYTE lpEncRow, int nSize);\r
14362b19 49\r
50extern HINSTANCE hStorm;\r
51\r
52BOOL APIENTRY DllMain( HINSTANCE hInstDLL, \r
53 DWORD ul_reason_for_call, \r
54 LPVOID lpReserved\r
55 )\r
56{\r
57 switch (ul_reason_for_call)\r
58 {\r
59 case DLL_PROCESS_ATTACH:\r
60 break;\r
61 case DLL_THREAD_ATTACH:\r
62 break;\r
63 case DLL_THREAD_DETACH:\r
64 break;\r
65 case DLL_PROCESS_DETACH:\r
66 break;\r
67 }\r
68\r
69 return TRUE;\r
70}\r
71\r
72BOOL GRPAPI WINAPI LoadGrpApi()\r
73{\r
ecca31ff 74 if (!hStorm) return FALSE;\r
14362b19 75 else return TRUE;\r
76}\r
77\r
78void GRPAPI WINAPI FreeGrpApi()\r
79{\r
80}\r
81\r
ecca31ff 82BOOL GRPAPI WINAPI SetMpqDll(LPCSTR lpDllFileName)\r
83{\r
84 if (LoadStorm((char *)lpDllFileName)) return TRUE;\r
85 else return FALSE;\r
86}\r
87\r
14362b19 88BOOL GRPAPI WINAPI LoadPalette(LPCSTR lpFileName, DWORD *dwPaletteBuffer)\r
89{\r
ecca31ff 90 if (!lpFileName || !dwPaletteBuffer) return FALSE;\r
14362b19 91 HANDLE hFile;\r
ecca31ff 92 if (SFileOpenFileEx && SFileGetFileSize\r
93 && SFileSetFilePointer && SFileReadFile\r
94 && SFileCloseFile) {\r
95 if (!SFileOpenFileEx(0,lpFileName,1,&hFile)) return FALSE;\r
14362b19 96 DWORD fsz = SFileGetFileSize(hFile,0);\r
97 SFileSetFilePointer(hFile,0,0,FILE_BEGIN);\r
98 if (fsz>=1024) {\r
99 memset(dwPaletteBuffer,0,1024);\r
100 SFileReadFile(hFile,dwPaletteBuffer,1024,0,0);\r
101 }\r
102 else if (fsz==768) {\r
103 char *buffer = (char *)_alloca(768);\r
104 memset(buffer,0,768);\r
105 SFileReadFile(hFile,buffer,768,0,0);\r
106 for (DWORD i=0;i<256;i++) {\r
107 memcpy(&dwPaletteBuffer[i],buffer+i*3,3);\r
108 *(((char *)&dwPaletteBuffer[i])+3) = 0;\r
109 }\r
110 }\r
111 else {\r
112 memset(dwPaletteBuffer,0,1024);\r
113 SFileReadFile(hFile,dwPaletteBuffer,fsz,0,0);\r
114 }\r
115 SFileCloseFile(hFile);\r
116 }\r
117 else {\r
118 hFile = CreateFile(lpFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);\r
119 if (hFile==INVALID_HANDLE_VALUE) return FALSE;\r
120 DWORD fsz = GetFileSize(hFile,0),tsz;\r
121 SetFilePointer(hFile,0,0,FILE_BEGIN);\r
122 if (fsz>=1024) {\r
123 memset(dwPaletteBuffer,0,1024);\r
124 ReadFile(hFile,dwPaletteBuffer,1024,&tsz,0);\r
125 }\r
126 else if (fsz==768) {\r
127 char *buffer = (char *)_alloca(768);\r
128 memset(buffer,0,768);\r
129 ReadFile(hFile,buffer,768,&tsz,0);\r
130 for (DWORD i=0;i<256;i++) {\r
131 memcpy(&dwPaletteBuffer[i],buffer+i*3,3);\r
132 *(((char *)&dwPaletteBuffer[i])+3) = 0;\r
133 }\r
134 }\r
135 else {\r
136 memset(dwPaletteBuffer,0,1024);\r
137 ReadFile(hFile,dwPaletteBuffer,fsz,&tsz,0);\r
138 }\r
139 CloseHandle(hFile);\r
140 }\r
141 return TRUE;\r
142}\r
143\r
144HANDLE GRPAPI WINAPI LoadGrp(LPCSTR lpFileName)\r
145{\r
ecca31ff 146 if (!lpFileName) return (HANDLE)-1;\r
14362b19 147 HANDLE hFile;\r
148 char *GrpFile;\r
ecca31ff 149 if (SFileOpenFileEx && SFileGetFileSize\r
150 && SFileSetFilePointer && SFileReadFile\r
151 && SFileCloseFile) {\r
152 if (!SFileOpenFileEx(0,lpFileName,1,&hFile)) return (HANDLE)-1;\r
14362b19 153 DWORD fsz = SFileGetFileSize(hFile,0);\r
154 if (fsz<6) {\r
155 SFileCloseFile(hFile);\r
156 return (HANDLE)-1;\r
157 }\r
afcd1861 158 GrpFile = (char *)malloc(fsz);\r
ecca31ff 159 if (GrpFile) {\r
14362b19 160 SFileSetFilePointer(hFile,0,0,FILE_BEGIN);\r
161 SFileReadFile(hFile,GrpFile,fsz,0,0);\r
162 }\r
163 else GrpFile=(char *)-1;\r
164 SFileCloseFile(hFile);\r
165 }\r
166 else {\r
167 hFile = CreateFile(lpFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);\r
168 if (hFile==INVALID_HANDLE_VALUE) return (HANDLE)-1;\r
169 DWORD fsz = GetFileSize(hFile,0),tsz;\r
170 if (fsz<6) {\r
171 CloseHandle(hFile);\r
172 return (HANDLE)-1;\r
173 }\r
afcd1861 174 GrpFile = (char *)malloc(fsz);\r
ecca31ff 175 if (GrpFile) {\r
14362b19 176 SetFilePointer(hFile,0,0,FILE_BEGIN);\r
177 ReadFile(hFile,GrpFile,fsz,&tsz,0);\r
178 }\r
179 else GrpFile=(char *)-1;\r
180 CloseHandle(hFile);\r
181 }\r
182 return (HANDLE)GrpFile;\r
183}\r
184\r
185BOOL GRPAPI WINAPI DestroyGrp(HANDLE hGrp)\r
186{\r
ecca31ff 187 if (!hGrp || hGrp==INVALID_HANDLE_VALUE) return FALSE;\r
afcd1861 188 free(hGrp);\r
14362b19 189 return TRUE;\r
190}\r
191\r
192BOOL GRPAPI WINAPI DrawGrp(HANDLE hGrp, HDC hdcDest, int nXDest, int nYDest, WORD nFrame, DWORD *dwPalette, DWORD dwFlags, DWORD dwAlpha)\r
193{\r
c483a082 194 if (!hGrp || hGrp==INVALID_HANDLE_VALUE || hdcDest==0 || (!dwPalette && !(dwFlags&USE_INDEX))) return FALSE;\r
14362b19 195 GRPHEADER *GrpFile = (GRPHEADER *)hGrp;\r
196 nFrame %= GrpFile->nFrames;\r
197 FRAMEHEADER *GrpFrame = &((FRAMEHEADER *)(((char *)GrpFile)+6))[nFrame];\r
2975ca34 198 FRAMEHEADER *GrpFrames = &((FRAMEHEADER *)(((char *)GrpFile)+6))[0];\r
199 int FrameSize = 0xFFFFFF;\r
14362b19 200 DWORD Right,Bottom;\r
201 if (dwFlags&HORIZONTAL_FLIP) Right = nXDest+GrpFile->wMaxWidth-1-GrpFrame->Left;\r
202 if (dwFlags&VERTICAL_FLIP) Bottom = nYDest+GrpFile->wMaxHeight-1-GrpFrame->Top;\r
203 nXDest += GrpFrame->Left;\r
204 nYDest += GrpFrame->Top;\r
205 WORD *GrpOffsets = ((WORD *)(((char *)GrpFile)+GrpFrame->Offset));\r
2975ca34 206 BYTE *GrpRaw = (BYTE *)GrpOffsets;\r
ecca31ff 207 BYTE *RowData;\r
208 WORD x,ofs;\r
209 DWORD y;\r
210 WORD i;\r
2975ca34 211 int j;\r
212 if (nFrame + 1 < GrpFile->nFrames) {\r
213 for (i = 0; i + 1 < GrpFile->nFrames; i++) {\r
214 j = GrpFrames[i].Offset - GrpFrame->Offset;\r
215 if (j > 0 && j < FrameSize)\r
216 FrameSize = j;\r
217 }\r
218 }\r
219 if (FrameSize == 0xFFFFFF) {\r
220 for (i = 0; i + 1 < GrpFile->nFrames; i++) {\r
221 j = GrpFrames[i].Offset - GrpFrames[0].Offset;\r
222 if (j > 0 && j < FrameSize)\r
223 FrameSize = j;\r
224 }\r
225 if (FrameSize == GrpFrames[0].Width * GrpFrames[0].Height)\r
226 FrameSize = GrpFrame->Width * GrpFrame->Height;\r
227 }\r
ecca31ff 228 if (!(dwFlags&HORIZONTAL_FLIP) && !(dwFlags&VERTICAL_FLIP)) {\r
2975ca34 229 if (FrameSize != GrpFrame->Width * GrpFrame->Height) {\r
230 for (y=0;y<GrpFrame->Height;y++) {\r
231 RowData = ((BYTE *)(((char *)GrpOffsets)+GrpOffsets[y]));\r
232 x=0; ofs=0;\r
233 while (x<GrpFrame->Width) {\r
234 if (!(RowData[ofs] & 0x80)) {\r
235 if (!(RowData[ofs] & 0x40)) {\r
236 for (i=1;i<=RowData[ofs] && x<GrpFrame->Width;i++) {\r
ff024783 237 SetPix(hdcDest,nXDest+x,nYDest+y,RowData[ofs+i],dwPalette,dwFlags,dwAlpha);\r
2975ca34 238 x++;\r
239 }\r
240 ofs+=RowData[ofs]+1;\r
241 }\r
242 else {\r
243 for (i=0;i<RowData[ofs]-64 && x<GrpFrame->Width;i++) {\r
ff024783 244 SetPix(hdcDest,nXDest+x,nYDest+y,RowData[ofs+1],dwPalette,dwFlags,dwAlpha);\r
2975ca34 245 x++;\r
246 }\r
247 ofs+=2;\r
ecca31ff 248 }\r
14362b19 249 }\r
ecca31ff 250 else {\r
2975ca34 251 x+=RowData[ofs]-128;\r
252 ofs++;\r
14362b19 253 }\r
254 }\r
2975ca34 255 }\r
256 }\r
257 else {\r
258 for (y=0;y<GrpFrame->Height;y++) {\r
259 for (x=0;x<GrpFrame->Width;x++) {\r
ff024783 260 SetPix(hdcDest,nXDest+x,nYDest+y,GrpRaw[y * GrpFrame->Width + x],dwPalette,dwFlags,dwAlpha);\r
ecca31ff 261 }\r
262 }\r
263 }\r
264 }\r
265 else if (dwFlags&HORIZONTAL_FLIP && !(dwFlags&VERTICAL_FLIP)) {\r
2975ca34 266 if (FrameSize != GrpFrame->Width * GrpFrame->Height) {\r
267 for (y=0;y<GrpFrame->Height;y++) {\r
268 RowData = ((BYTE *)(((char *)GrpOffsets)+GrpOffsets[y]));\r
269 x=0; ofs=0;\r
270 while (x<GrpFrame->Width) {\r
271 if (!(RowData[ofs] & 0x80)) {\r
272 if (!(RowData[ofs] & 0x40)) {\r
273 for (i=1;i<=RowData[ofs] && x<GrpFrame->Width;i++) {\r
ff024783 274 SetPix(hdcDest,Right-x,nYDest+y,RowData[ofs+i],dwPalette,dwFlags,dwAlpha);\r
2975ca34 275 x++;\r
276 }\r
277 ofs+=RowData[ofs]+1;\r
278 }\r
279 else {\r
280 for (i=0;i<RowData[ofs]-64 && x<GrpFrame->Width;i++) {\r
ff024783 281 SetPix(hdcDest,Right-x,nYDest+y,RowData[ofs+1],dwPalette,dwFlags,dwAlpha);\r
2975ca34 282 x++;\r
283 }\r
284 ofs+=2;\r
ecca31ff 285 }\r
ecca31ff 286 }\r
287 else {\r
2975ca34 288 x+=RowData[ofs]-128;\r
289 ofs++;\r
14362b19 290 }\r
291 }\r
2975ca34 292 }\r
293 }\r
294 else {\r
295 for (y=0;y<GrpFrame->Height;y++) {\r
296 for (x=0;x<GrpFrame->Width;x++) {\r
ff024783 297 SetPix(hdcDest,Right-x,nYDest+y,GrpRaw[y * GrpFrame->Width + x],dwPalette,dwFlags,dwAlpha);\r
14362b19 298 }\r
14362b19 299 }\r
ecca31ff 300 }\r
301 }\r
302 else if (!(dwFlags&HORIZONTAL_FLIP) && dwFlags&VERTICAL_FLIP) {\r
2975ca34 303 if (FrameSize != GrpFrame->Width * GrpFrame->Height) {\r
304 for (y=0;y<GrpFrame->Height;y++) {\r
305 RowData = ((BYTE *)(((char *)GrpOffsets)+GrpOffsets[y]));\r
306 x=0; ofs=0;\r
307 while (x<GrpFrame->Width) {\r
308 if (!(RowData[ofs] & 0x80)) {\r
309 if (!(RowData[ofs] & 0x40)) {\r
310 for (i=1;i<=RowData[ofs] && x<GrpFrame->Width;i++) {\r
ff024783 311 SetPix(hdcDest,nXDest+x,Bottom-y,RowData[ofs+i],dwPalette,dwFlags,dwAlpha);\r
2975ca34 312 x++;\r
313 }\r
314 ofs+=RowData[ofs]+1;\r
315 }\r
316 else {\r
317 for (i=0;i<RowData[ofs]-64 && x<GrpFrame->Width;i++) {\r
ff024783 318 SetPix(hdcDest,nXDest+x,Bottom-y,RowData[ofs+1],dwPalette,dwFlags,dwAlpha);\r
2975ca34 319 x++;\r
320 }\r
321 ofs+=2;\r
ecca31ff 322 }\r
14362b19 323 }\r
ecca31ff 324 else {\r
2975ca34 325 x+=RowData[ofs]-128;\r
326 ofs++;\r
14362b19 327 }\r
328 }\r
2975ca34 329 }\r
330 }\r
331 else {\r
332 for (y=0;y<GrpFrame->Height;y++) {\r
333 for (x=0;x<GrpFrame->Width;x++) {\r
ff024783 334 SetPix(hdcDest,nXDest+x,Bottom-y,GrpRaw[y * GrpFrame->Width + x],dwPalette,dwFlags,dwAlpha);\r
ecca31ff 335 }\r
336 }\r
337 }\r
338 }\r
339 else {\r
2975ca34 340 if (FrameSize != GrpFrame->Width * GrpFrame->Height) {\r
341 for (y=0;y<GrpFrame->Height;y++) {\r
342 RowData = ((BYTE *)(((char *)GrpOffsets)+GrpOffsets[y]));\r
343 x=0; ofs=0;\r
344 while (x<GrpFrame->Width) {\r
345 if (!(RowData[ofs] & 0x80)) {\r
346 if (!(RowData[ofs] & 0x40)) {\r
347 for (i=1;i<=RowData[ofs] && x<GrpFrame->Width;i++) {\r
ff024783 348 SetPix(hdcDest,Right-x,Bottom-y,RowData[ofs+i],dwPalette,dwFlags,dwAlpha);\r
2975ca34 349 x++;\r
350 }\r
351 ofs+=RowData[ofs]+1;\r
352 }\r
353 else {\r
354 for (i=0;i<RowData[ofs]-64 && x<GrpFrame->Width;i++) {\r
ff024783 355 SetPix(hdcDest,Right-x,Bottom-y,RowData[ofs+1],dwPalette,dwFlags,dwAlpha);\r
2975ca34 356 x++;\r
357 }\r
358 ofs+=2;\r
ecca31ff 359 }\r
ecca31ff 360 }\r
361 else {\r
2975ca34 362 x+=RowData[ofs]-128;\r
363 ofs++;\r
14362b19 364 }\r
365 }\r
2975ca34 366 }\r
367 }\r
368 else {\r
369 for (y=0;y<GrpFrame->Height;y++) {\r
370 for (x=0;x<GrpFrame->Width;x++) {\r
ff024783 371 SetPix(hdcDest,Right-x,Bottom-y,GrpRaw[y * GrpFrame->Width + x],dwPalette,dwFlags,dwAlpha);\r
14362b19 372 }\r
14362b19 373 }\r
374 }\r
375 }\r
376 return TRUE;\r
377}\r
378\r
379BOOL GRPAPI WINAPI GetGrpInfo(HANDLE hGrp, GRPHEADER *GrpInfo)\r
380{\r
ecca31ff 381 if (!hGrp || hGrp==INVALID_HANDLE_VALUE || !GrpInfo) return FALSE;\r
14362b19 382 memcpy(GrpInfo,hGrp,6);\r
383 return TRUE;\r
384}\r
385\r
ecca31ff 386void GRPAPI WINAPI SetFunctionGetPixel(GETPIXELPROC lpGetPixelProc)\r
387{\r
afcd1861 388 if (!lpGetPixelProc)\r
389 MyGetPixel = GetPixel;\r
390 else\r
391 MyGetPixel = lpGetPixelProc;\r
ecca31ff 392}\r
393\r
394void GRPAPI WINAPI SetFunctionSetPixel(SETPIXELPROC lpSetPixelProc)\r
395{\r
afcd1861 396 if (!lpSetPixelProc)\r
397 MySetPixel = (SETPIXELPROC)SetPixelV;\r
398 else\r
399 MySetPixel = lpSetPixelProc;\r
ecca31ff 400}\r
401\r
ff024783 402void __inline SetPix(HDC hDC, int X, int Y, COLORREF clrColor, DWORD *dwPalette, DWORD dwFlags, DWORD dwAlpha)\r
14362b19 403{\r
ff024783 404 if (!(dwFlags&USE_INDEX)) {\r
405 if (dwFlags&SHADOW_COLOR) {\r
406 clrColor = (dwFlags >> 8) & 0x00FFFFFF;\r
407 }\r
408 else {\r
409 clrColor = dwPalette[clrColor];\r
410 }\r
411 if (dwFlags&ALPHA_BLEND) {\r
412 DWORD dwColor = MyGetPixel(hDC,X,Y);\r
14362b19 413\r
ff024783 414 // Old alpha\r
415 /*((BYTE *)&dwColor)[0]*=1-((float)((BYTE *)&dwAlpha)[0]/256);\r
416 ((BYTE *)&dwColor)[1]*=1-((float)((BYTE *)&dwAlpha)[1]/256);\r
417 ((BYTE *)&dwColor)[2]*=1-((float)((BYTE *)&dwAlpha)[2]/256);\r
418 ((BYTE *)&clrColor)[0]*=(float)((BYTE *)&dwAlpha)[0]/256;\r
419 ((BYTE *)&clrColor)[1]*=(float)((BYTE *)&dwAlpha)[1]/256;\r
420 ((BYTE *)&clrColor)[2]*=(float)((BYTE *)&dwAlpha)[2]/256;\r
421 ((BYTE *)&clrColor)[0]+=((BYTE *)&dwColor)[0];\r
422 ((BYTE *)&clrColor)[1]+=((BYTE *)&dwColor)[1];\r
423 ((BYTE *)&clrColor)[2]+=((BYTE *)&dwColor)[2];*/\r
14362b19 424\r
ff024783 425 /* blendedcolor =\r
426 ( ( forecolor * ( 1 - alpha ) ) >> 8 )\r
427 + ( ( backcolor * ( 256 - alpha ) ) >> 8 ) */\r
428 ((BYTE *)&clrColor)[0] =\r
429 ( ( ((BYTE *)&clrColor)[0] * ( ((BYTE *)&dwAlpha)[0] + 1 ) ) >> 8 )\r
430 + ( ( ((BYTE *)&dwColor)[0] * ( 256 - ((BYTE *)&dwAlpha)[0] ) ) >> 8 );\r
431 ((BYTE *)&clrColor)[1] =\r
432 ( ( ((BYTE *)&clrColor)[1] * ( ((BYTE *)&dwAlpha)[1] + 1 ) ) >> 8 )\r
433 + ( ( ((BYTE *)&dwColor)[1] * ( 256 - ((BYTE *)&dwAlpha)[1] ) ) >> 8 );\r
434 ((BYTE *)&clrColor)[2] =\r
435 ( ( ((BYTE *)&clrColor)[2] * ( ((BYTE *)&dwAlpha)[2] + 1 ) ) >> 8 )\r
436 + ( ( ((BYTE *)&dwColor)[2] * ( 256 - ((BYTE *)&dwAlpha)[2] ) ) >> 8 );\r
437 }\r
14362b19 438 }\r
ecca31ff 439 MySetPixel(hDC,X,Y,clrColor);\r
14362b19 440}\r
c483a082 441\r
03269fee 442HANDLE GRPAPI WINAPI CreateGrp(signed short *lpImageData, WORD nFrames, WORD wMaxWidth, WORD wMaxHeight, BOOL bNoCompress, DWORD *nGrpSize)\r
c483a082 443{\r
444 GRPHEADER GrpHeader;\r
445 FRAMEHEADER *lpFrameHeaders;\r
446 FRAMEDATA *lpFrameData;\r
447 LPBYTE lpGrpData;\r
0df81049 448 int i, j, x, y, x1, x2, y1, y2;\r
449 DWORD nLastOffset;\r
c483a082 450\r
451 if (!lpImageData || !nGrpSize) return (HANDLE)-1;\r
452\r
453 GrpHeader.nFrames = nFrames;\r
454 GrpHeader.wMaxWidth = wMaxWidth;\r
455 GrpHeader.wMaxHeight = wMaxHeight;\r
0df81049 456 lpFrameHeaders = (FRAMEHEADER *)malloc(nFrames * sizeof(FRAMEHEADER));\r
c483a082 457 lpFrameData = (FRAMEDATA *)malloc(nFrames * sizeof(FRAMEDATA));\r
458\r
0df81049 459 for (i = 0; i < nFrames; i++) {\r
460 // Search for duplicate frames\r
461 for (j = 0; j < i; j++) {\r
462 if (memcmp(&lpImageData[i * wMaxWidth * wMaxHeight],\r
463 &lpImageData[j * wMaxWidth * wMaxHeight],\r
464 wMaxWidth * wMaxHeight * sizeof(short)) == 0)\r
465 break;\r
466 }\r
467\r
468 if (j < i) {\r
469 memcpy(&lpFrameHeaders[i], &lpFrameHeaders[j], sizeof(FRAMEHEADER));\r
ec637542 470 lpFrameData[i].lpRowOffsets = 0;\r
0df81049 471 continue;\r
472 }\r
473\r
c483a082 474 if (i == 0) {\r
475 lpFrameHeaders[i].Offset = sizeof(GRPHEADER) + nFrames * sizeof(FRAMEHEADER);\r
476 }\r
477 else {\r
0df81049 478 lpFrameHeaders[i].Offset = nLastOffset;\r
c483a082 479 }\r
c483a082 480\r
481 // Scan frame to find dimensions of used part\r
482 x1 = y1 = 0x10000;\r
483 x2 = y2 = -1;\r
484 for (y = 0; y < wMaxHeight; y++) {\r
485 for (x = 0; x < wMaxWidth; x++) {\r
486 if (lpImageData[i * wMaxWidth * wMaxHeight + y * wMaxWidth + x] >= 0) {\r
487 if (x < x1) x1 = x;\r
488 if (x > x2) x2 = x;\r
489 if (y < y1) y1 = y;\r
490 if (y > y2) y2 = y;\r
491 }\r
492 }\r
493 }\r
494 lpFrameHeaders[i].Left = x1;\r
495 lpFrameHeaders[i].Top = y1;\r
496 lpFrameHeaders[i].Width = x2 - x1 + 1;\r
497 lpFrameHeaders[i].Height = y2 - y1 + 1;\r
498\r
03269fee 499 if (!bNoCompress) {\r
500 EncodeFrameData(lpImageData, i, &GrpHeader, &lpFrameHeaders[i], &lpFrameData[i]);\r
0df81049 501\r
03269fee 502 y = lpFrameHeaders[i].Height;\r
503 if (y > 0) {\r
504 y--;\r
505 nLastOffset = lpFrameHeaders[i].Offset + lpFrameData[i].lpRowOffsets[y] + lpFrameData[i].lpRowSizes[y];\r
506 }\r
507 else {\r
508 nLastOffset = lpFrameHeaders[i].Offset;\r
509 }\r
0df81049 510 }\r
511 else {\r
03269fee 512 nLastOffset = lpFrameHeaders[i].Offset + lpFrameHeaders[i].Width * lpFrameHeaders[i].Height;\r
0df81049 513 }\r
c483a082 514 }\r
515\r
0df81049 516 lpGrpData = (LPBYTE)malloc(nLastOffset);\r
c483a082 517\r
518 // Write completed GRP to buffer\r
519 memcpy(lpGrpData, &GrpHeader, sizeof(GRPHEADER));\r
520 memcpy(lpGrpData + sizeof(GRPHEADER), lpFrameHeaders, nFrames * sizeof(FRAMEHEADER));\r
521\r
522 for (i = 0; i < nFrames; i++) {\r
ec637542 523 if (lpFrameData[i].lpRowOffsets) {\r
03269fee 524 if (!bNoCompress) {\r
525 memcpy(lpGrpData + lpFrameHeaders[i].Offset, lpFrameData[i].lpRowOffsets, lpFrameHeaders[i].Height * sizeof(WORD));\r
c483a082 526\r
03269fee 527 for (y = 0; y < lpFrameHeaders[i].Height; y++) {\r
528 if (lpFrameData[i].lpRowData[y]) {\r
529 memcpy(lpGrpData + lpFrameHeaders[i].Offset + lpFrameData[i].lpRowOffsets[y], lpFrameData[i].lpRowData[y], lpFrameData[i].lpRowSizes[y]);\r
530 free(lpFrameData[i].lpRowData[y]);\r
531 }\r
ec637542 532 }\r
0df81049 533\r
03269fee 534 free(lpFrameData[i].lpRowOffsets);\r
535 free(lpFrameData[i].lpRowSizes);\r
536 free(lpFrameData[i].lpRowData);\r
537 }\r
538 else {\r
539 for (y = 0; y < lpFrameHeaders[i].Height; y++) {\r
540 for (x = 0; x < lpFrameHeaders[i].Width; x++) {\r
541 lpGrpData[lpFrameHeaders[i].Offset + y * lpFrameHeaders[i].Width + x] =\r
542 lpImageData[i * wMaxWidth * wMaxHeight + (lpFrameHeaders[i].Top + y) * wMaxWidth + lpFrameHeaders[i].Left + x];\r
543 }\r
544 }\r
545 }\r
0df81049 546 }\r
c483a082 547 }\r
548\r
c483a082 549 free(lpFrameHeaders);\r
550 free(lpFrameData);\r
551\r
0df81049 552 *nGrpSize = nLastOffset;\r
c483a082 553 return (HANDLE)lpGrpData;\r
554}\r
555\r
556void EncodeFrameData(signed short *lpImageData, WORD nFrame, GRPHEADER *lpGrpHeader, FRAMEHEADER *lpFrameHeader, FRAMEDATA *lpFrameData)\r
557{\r
ec637542 558 int x, y, i, j, nBufPos, nRepeat;\r
c483a082 559 LPBYTE lpRowBuf;\r
ec637542 560 WORD nLastOffset;\r
c483a082 561\r
562 lpFrameData->lpRowOffsets = (WORD *)malloc(lpFrameHeader->Height * sizeof(WORD));\r
563 lpFrameData->lpRowSizes = (WORD *)malloc(lpFrameHeader->Height * sizeof(WORD));\r
564 lpFrameData->lpRowData = (LPBYTE *)malloc(lpFrameHeader->Height * sizeof(LPBYTE));\r
565 lpRowBuf = (LPBYTE)malloc(lpFrameHeader->Width * 2);\r
566\r
567 for (y = 0; y < lpFrameHeader->Height; y++) {\r
568 i = nFrame * lpGrpHeader->wMaxWidth * lpGrpHeader->wMaxHeight + (lpFrameHeader->Top + y) * lpGrpHeader->wMaxWidth;\r
ec637542 569\r
570 /* Fails verification when using this. Bug in encoder or decoder? Doesn't provide much benefit.\r
03269fee 571 // Search for duplicate rows (experimental)\r
ec637542 572 for (x = 0; x < y; x++) {\r
573 j = nFrame * lpGrpHeader->wMaxWidth * lpGrpHeader->wMaxHeight + (lpFrameHeader->Top + x) * lpGrpHeader->wMaxWidth;\r
574 if (memcmp(&lpImageData[i+lpFrameHeader->Left],\r
575 &lpImageData[j+lpFrameHeader->Left],\r
576 lpGrpHeader->wMaxWidth * sizeof(short)) == 0)\r
577 break;\r
578 }\r
579\r
580 if (x < y) {\r
581 lpFrameData->lpRowOffsets[y] = lpFrameData->lpRowOffsets[x];\r
582 lpFrameData->lpRowSizes[y] = 0;\r
583 lpFrameData->lpRowData[y] = 0;\r
584\r
585#ifdef _DEBUG\r
586 if (!VerifyRow(&lpImageData[i+lpFrameHeader->Left], lpFrameHeader->Width, lpFrameData->lpRowData[x], lpFrameData->lpRowSizes[x])) {\r
587 nBufPos = nBufPos;\r
588 }\r
589#endif\r
590\r
591 continue;\r
592 }\r
593 */\r
594\r
c483a082 595 nBufPos = 0;\r
0df81049 596 if (lpFrameHeader->Width > 0) {\r
597 for (x = lpFrameHeader->Left; x < lpFrameHeader->Left + lpFrameHeader->Width; x++) {\r
598 if (x < lpFrameHeader->Left + lpFrameHeader->Width - 1) {\r
599 if (lpImageData[i+x] < 0) {\r
600 lpRowBuf[nBufPos] = 0x80;\r
601 for (; lpImageData[i+x] < 0 && x < lpFrameHeader->Left + lpFrameHeader->Width && lpRowBuf[nBufPos] < 0xFF; x++) {\r
602 lpRowBuf[nBufPos]++;\r
603 }\r
604 x--;\r
605 nBufPos++;\r
606 continue;\r
c483a082 607 }\r
0df81049 608\r
609 // Count repeating pixels, nRepeat = number of pixels - 1, ignore if there are less than 4 duplicates\r
58a8b78c 610 for (nRepeat = 0; lpImageData[i+x+nRepeat] == lpImageData[i+x+nRepeat+1] && x+nRepeat < lpFrameHeader->Left + lpFrameHeader->Width - 1 && nRepeat < 0x3E; nRepeat++) {}\r
0df81049 611\r
612 if (nRepeat > 2) {\r
613 lpRowBuf[nBufPos] = 0x41 + nRepeat;\r
614 lpRowBuf[nBufPos+1] = (BYTE)lpImageData[i+x];\r
615 x += nRepeat;\r
616 nBufPos += 2;\r
617 }\r
618 else {\r
619 lpRowBuf[nBufPos] = 0;\r
620 for (; lpImageData[i+x] >= 0 && x < lpFrameHeader->Left + lpFrameHeader->Width && lpRowBuf[nBufPos] < 0x3F; x++) {\r
621 // Count repeating pixels, ignore if there are less than 4 duplicates\r
622 for (nRepeat = 0; lpImageData[i+x+nRepeat] == lpImageData[i+x+nRepeat+1] && x+nRepeat < lpFrameHeader->Left + lpFrameHeader->Width - 1 && nRepeat < 3; nRepeat++) {}\r
623 if (nRepeat > 2) break;\r
624\r
625 lpRowBuf[nBufPos]++;\r
626 lpRowBuf[nBufPos+lpRowBuf[nBufPos]] = (BYTE)lpImageData[i+x];\r
627 }\r
628 if (lpImageData[i+x] >= 0 && x == lpFrameHeader->Left + lpFrameHeader->Width - 1 && lpRowBuf[nBufPos] < 0x3F) {\r
629 lpRowBuf[nBufPos]++;\r
630 lpRowBuf[nBufPos+lpRowBuf[nBufPos]] = (BYTE)lpImageData[i+x];\r
631 }\r
632 x--;\r
633 nBufPos += 1 + lpRowBuf[nBufPos];\r
c483a082 634 }\r
c483a082 635 }\r
636 else {\r
0df81049 637 if (lpImageData[i+x] < 0) {\r
638 lpRowBuf[nBufPos] = 0x81;\r
639 nBufPos++;\r
640 }\r
641 else {\r
642 lpRowBuf[nBufPos] = 1;\r
643 lpRowBuf[nBufPos+1] = (BYTE)lpImageData[i+x];\r
644 nBufPos += 2;\r
c483a082 645 }\r
c483a082 646 }\r
647 }\r
648 }\r
0df81049 649\r
650#ifdef _DEBUG\r
651 if (!VerifyRow(&lpImageData[i+lpFrameHeader->Left], lpFrameHeader->Width, lpRowBuf, nBufPos)) {\r
652 nBufPos = nBufPos;\r
c483a082 653 }\r
0df81049 654#endif\r
c483a082 655\r
656 if (y == 0) {\r
657 lpFrameData->lpRowOffsets[y] = lpFrameHeader->Height * sizeof(WORD);\r
658 }\r
659 else {\r
ec637542 660 lpFrameData->lpRowOffsets[y] = nLastOffset;\r
c483a082 661 }\r
662\r
ec637542 663 nLastOffset = lpFrameData->lpRowOffsets[y] + nBufPos;\r
664\r
c483a082 665 lpFrameData->lpRowSizes[y] = nBufPos;\r
666 lpFrameData->lpRowData[y] = (LPBYTE)malloc(nBufPos);\r
667 memcpy(lpFrameData->lpRowData[y], lpRowBuf, nBufPos);\r
668 }\r
669\r
670 free(lpRowBuf);\r
671}\r
0df81049 672\r
673#ifdef _DEBUG\r
674BOOL VerifyRow(signed short *lpRawRow, int nWidth, LPBYTE lpEncRow, int nSize)\r
675{\r
676 int i,x=0,ofs=0;\r
677 while (x < nWidth && ofs < nSize) {\r
678 if (!(lpEncRow[ofs] & 0x80)) {\r
679 if (!(lpEncRow[ofs] & 0x40)) {\r
680 for (i=1;i<=lpEncRow[ofs] && x<nWidth;i++) {\r
681 if (lpEncRow[ofs+i] != (BYTE)lpRawRow[x]) return FALSE;\r
682 x++;\r
683 }\r
684 ofs+=lpEncRow[ofs]+1;\r
685 }\r
686 else {\r
687 for (i=0;i<lpEncRow[ofs]-64 && x<nWidth;i++) {\r
688 if (lpEncRow[ofs+1] != (BYTE)lpRawRow[x]) return FALSE;\r
689 x++;\r
690 }\r
691 ofs+=2;\r
692 }\r
693 }\r
694 else {\r
695 for (i=0;i<lpEncRow[ofs]-128 && x<nWidth;i++) {\r
696 if (lpRawRow[x] >= 0) return FALSE;\r
697 }\r
698 x+=lpEncRow[ofs]-128;\r
699 ofs++;\r
700 }\r
701 }\r
702\r
703 if (x != nWidth || ofs != nSize) return FALSE;\r
704\r
705 return TRUE;\r
706}\r
707#endif\r