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