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
442HANDLE GRPAPI WINAPI CreateGrp(signed short *lpImageData, WORD nFrames, WORD wMaxWidth, WORD wMaxHeight, DWORD *nGrpSize)\r
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
470 continue;\r
471 }\r
472\r
c483a082 473 if (i == 0) {\r
474 lpFrameHeaders[i].Offset = sizeof(GRPHEADER) + nFrames * sizeof(FRAMEHEADER);\r
475 }\r
476 else {\r
0df81049 477 lpFrameHeaders[i].Offset = nLastOffset;\r
c483a082 478 }\r
c483a082 479\r
480 // Scan frame to find dimensions of used part\r
481 x1 = y1 = 0x10000;\r
482 x2 = y2 = -1;\r
483 for (y = 0; y < wMaxHeight; y++) {\r
484 for (x = 0; x < wMaxWidth; x++) {\r
485 if (lpImageData[i * wMaxWidth * wMaxHeight + y * wMaxWidth + x] >= 0) {\r
486 if (x < x1) x1 = x;\r
487 if (x > x2) x2 = x;\r
488 if (y < y1) y1 = y;\r
489 if (y > y2) y2 = y;\r
490 }\r
491 }\r
492 }\r
493 lpFrameHeaders[i].Left = x1;\r
494 lpFrameHeaders[i].Top = y1;\r
495 lpFrameHeaders[i].Width = x2 - x1 + 1;\r
496 lpFrameHeaders[i].Height = y2 - y1 + 1;\r
497\r
498 EncodeFrameData(lpImageData, i, &GrpHeader, &lpFrameHeaders[i], &lpFrameData[i]);\r
0df81049 499\r
500 y = lpFrameHeaders[i].Height;\r
501 if (y > 0) {\r
502 y--;\r
503 nLastOffset = lpFrameHeaders[i].Offset + lpFrameData[i].lpRowOffsets[y] + lpFrameData[i].lpRowSizes[y];\r
504 }\r
505 else {\r
506 nLastOffset = lpFrameHeaders[i].Offset;\r
507 }\r
c483a082 508 }\r
509\r
0df81049 510 lpGrpData = (LPBYTE)malloc(nLastOffset);\r
c483a082 511\r
512 // Write completed GRP to buffer\r
513 memcpy(lpGrpData, &GrpHeader, sizeof(GRPHEADER));\r
514 memcpy(lpGrpData + sizeof(GRPHEADER), lpFrameHeaders, nFrames * sizeof(FRAMEHEADER));\r
515\r
516 for (i = 0; i < nFrames; i++) {\r
0df81049 517 if (lpFrameHeaders[i].Offset) {\r
518 memcpy(lpGrpData + lpFrameHeaders[i].Offset, lpFrameData[i].lpRowOffsets, lpFrameHeaders[i].Height * sizeof(WORD));\r
c483a082 519\r
0df81049 520 for (y = 0; y < lpFrameHeaders[i].Height; y++) {\r
521 memcpy(lpGrpData + lpFrameHeaders[i].Offset + lpFrameData[i].lpRowOffsets[y], lpFrameData[i].lpRowData[y], lpFrameData[i].lpRowSizes[y]);\r
522 free(lpFrameData[i].lpRowData[y]);\r
523 }\r
524\r
525 free(lpFrameData[i].lpRowOffsets);\r
526 free(lpFrameData[i].lpRowSizes);\r
527 free(lpFrameData[i].lpRowData);\r
c483a082 528\r
0df81049 529 for (j = i + 1; j < nFrames; j++) {\r
530 if (lpFrameHeaders[i].Offset == lpFrameHeaders[j].Offset)\r
531 lpFrameHeaders[j].Offset = 0;\r
532 }\r
533 }\r
c483a082 534 }\r
535\r
c483a082 536 free(lpFrameHeaders);\r
537 free(lpFrameData);\r
538\r
0df81049 539 *nGrpSize = nLastOffset;\r
c483a082 540 return (HANDLE)lpGrpData;\r
541}\r
542\r
543void EncodeFrameData(signed short *lpImageData, WORD nFrame, GRPHEADER *lpGrpHeader, FRAMEHEADER *lpFrameHeader, FRAMEDATA *lpFrameData)\r
544{\r
0df81049 545 int x, y, i, nBufPos, nRepeat;\r
c483a082 546 LPBYTE lpRowBuf;\r
547\r
548 lpFrameData->lpRowOffsets = (WORD *)malloc(lpFrameHeader->Height * sizeof(WORD));\r
549 lpFrameData->lpRowSizes = (WORD *)malloc(lpFrameHeader->Height * sizeof(WORD));\r
550 lpFrameData->lpRowData = (LPBYTE *)malloc(lpFrameHeader->Height * sizeof(LPBYTE));\r
551 lpRowBuf = (LPBYTE)malloc(lpFrameHeader->Width * 2);\r
552\r
553 for (y = 0; y < lpFrameHeader->Height; y++) {\r
554 i = nFrame * lpGrpHeader->wMaxWidth * lpGrpHeader->wMaxHeight + (lpFrameHeader->Top + y) * lpGrpHeader->wMaxWidth;\r
555 nBufPos = 0;\r
0df81049 556 if (lpFrameHeader->Width > 0) {\r
557 for (x = lpFrameHeader->Left; x < lpFrameHeader->Left + lpFrameHeader->Width; x++) {\r
558 if (x < lpFrameHeader->Left + lpFrameHeader->Width - 1) {\r
559 if (lpImageData[i+x] < 0) {\r
560 lpRowBuf[nBufPos] = 0x80;\r
561 for (; lpImageData[i+x] < 0 && x < lpFrameHeader->Left + lpFrameHeader->Width && lpRowBuf[nBufPos] < 0xFF; x++) {\r
562 lpRowBuf[nBufPos]++;\r
563 }\r
564 x--;\r
565 nBufPos++;\r
566 continue;\r
c483a082 567 }\r
0df81049 568\r
569 // Count repeating pixels, nRepeat = number of pixels - 1, ignore if there are less than 4 duplicates\r
58a8b78c 570 for (nRepeat = 0; lpImageData[i+x+nRepeat] == lpImageData[i+x+nRepeat+1] && x+nRepeat < lpFrameHeader->Left + lpFrameHeader->Width - 1 && nRepeat < 0x3E; nRepeat++) {}\r
0df81049 571\r
572 if (nRepeat > 2) {\r
573 lpRowBuf[nBufPos] = 0x41 + nRepeat;\r
574 lpRowBuf[nBufPos+1] = (BYTE)lpImageData[i+x];\r
575 x += nRepeat;\r
576 nBufPos += 2;\r
577 }\r
578 else {\r
579 lpRowBuf[nBufPos] = 0;\r
580 for (; lpImageData[i+x] >= 0 && x < lpFrameHeader->Left + lpFrameHeader->Width && lpRowBuf[nBufPos] < 0x3F; x++) {\r
581 // Count repeating pixels, ignore if there are less than 4 duplicates\r
582 for (nRepeat = 0; lpImageData[i+x+nRepeat] == lpImageData[i+x+nRepeat+1] && x+nRepeat < lpFrameHeader->Left + lpFrameHeader->Width - 1 && nRepeat < 3; nRepeat++) {}\r
583 if (nRepeat > 2) break;\r
584\r
585 lpRowBuf[nBufPos]++;\r
586 lpRowBuf[nBufPos+lpRowBuf[nBufPos]] = (BYTE)lpImageData[i+x];\r
587 }\r
588 if (lpImageData[i+x] >= 0 && x == lpFrameHeader->Left + lpFrameHeader->Width - 1 && lpRowBuf[nBufPos] < 0x3F) {\r
589 lpRowBuf[nBufPos]++;\r
590 lpRowBuf[nBufPos+lpRowBuf[nBufPos]] = (BYTE)lpImageData[i+x];\r
591 }\r
592 x--;\r
593 nBufPos += 1 + lpRowBuf[nBufPos];\r
c483a082 594 }\r
c483a082 595 }\r
596 else {\r
0df81049 597 if (lpImageData[i+x] < 0) {\r
598 lpRowBuf[nBufPos] = 0x81;\r
599 nBufPos++;\r
600 }\r
601 else {\r
602 lpRowBuf[nBufPos] = 1;\r
603 lpRowBuf[nBufPos+1] = (BYTE)lpImageData[i+x];\r
604 nBufPos += 2;\r
c483a082 605 }\r
c483a082 606 }\r
607 }\r
608 }\r
0df81049 609\r
610#ifdef _DEBUG\r
611 if (!VerifyRow(&lpImageData[i+lpFrameHeader->Left], lpFrameHeader->Width, lpRowBuf, nBufPos)) {\r
612 nBufPos = nBufPos;\r
c483a082 613 }\r
0df81049 614#endif\r
c483a082 615\r
616 if (y == 0) {\r
617 lpFrameData->lpRowOffsets[y] = lpFrameHeader->Height * sizeof(WORD);\r
618 }\r
619 else {\r
620 lpFrameData->lpRowOffsets[y] = lpFrameData->lpRowOffsets[y-1] + lpFrameData->lpRowSizes[y-1];\r
621 }\r
622\r
623 lpFrameData->lpRowSizes[y] = nBufPos;\r
624 lpFrameData->lpRowData[y] = (LPBYTE)malloc(nBufPos);\r
625 memcpy(lpFrameData->lpRowData[y], lpRowBuf, nBufPos);\r
626 }\r
627\r
628 free(lpRowBuf);\r
629}\r
0df81049 630\r
631#ifdef _DEBUG\r
632BOOL VerifyRow(signed short *lpRawRow, int nWidth, LPBYTE lpEncRow, int nSize)\r
633{\r
634 int i,x=0,ofs=0;\r
635 while (x < nWidth && ofs < nSize) {\r
636 if (!(lpEncRow[ofs] & 0x80)) {\r
637 if (!(lpEncRow[ofs] & 0x40)) {\r
638 for (i=1;i<=lpEncRow[ofs] && x<nWidth;i++) {\r
639 if (lpEncRow[ofs+i] != (BYTE)lpRawRow[x]) return FALSE;\r
640 x++;\r
641 }\r
642 ofs+=lpEncRow[ofs]+1;\r
643 }\r
644 else {\r
645 for (i=0;i<lpEncRow[ofs]-64 && x<nWidth;i++) {\r
646 if (lpEncRow[ofs+1] != (BYTE)lpRawRow[x]) return FALSE;\r
647 x++;\r
648 }\r
649 ofs+=2;\r
650 }\r
651 }\r
652 else {\r
653 for (i=0;i<lpEncRow[ofs]-128 && x<nWidth;i++) {\r
654 if (lpRawRow[x] >= 0) return FALSE;\r
655 }\r
656 x+=lpEncRow[ofs]-128;\r
657 ofs++;\r
658 }\r
659 }\r
660\r
661 if (x != nWidth || ofs != nSize) return FALSE;\r
662\r
663 return TRUE;\r
664}\r
665#endif\r