/* $Log: S:\oiwh\filing\fiogif.c_v $ * * Rev 1.8 05 Feb 1996 14:38:24 RWR * Eliminate static links to OIDIS400 and OIADM400 for NT builds * * Rev 1.7 07 Nov 1995 14:51:08 RWR * Get rid of internal lmemset() function - use memset() runtime * (this is all moot, since we aren't supporting GIF this week anyway) * * Rev 1.6 12 Jul 1995 16:57:26 RWR * Switch from \include\oiutil.h to (private) \filing\fileutil.h * * Rev 1.5 12 Jul 1995 10:24:28 RWR * Change display.h header (#include) to engdisp.h * * Rev 1.4 23 Jun 1995 10:39:50 RWR * Change "wiisfio2.h" include file to "filing.h" * * Rev 1.3 09 May 1995 13:21:26 RWR * #include file modifications to match changes to oiadm.h/admin.h/privapis.h * * Rev 1.2 24 Apr 1995 15:42:38 JCW * Removed the oiuidll.h. * Rename wiissubs.h to oiutil.h. * * Rev 1.1 14 Apr 1995 20:48:30 JAR * massaged to get compilation under windows 95 * * Rev 1.0 06 Apr 1995 13:55:26 JAR * Initial entry */ //************************************************************************ // // fiogif.c // //************************************************************************ #include "abridge.h" #include #include #include #include #include "wic.h" #include "filing.h" #include "fileutil.h" #include "oierror.h" #include "engdisp.h" #define pixels2bytes(n) ((n+7)/8) #define RGB_SIZE 3 typedef struct _giffileinfo { unsigned int width; unsigned int depth; unsigned int bits; int flags; int background; int status; int codesize; int linewidth; } GIFFILEINFO; typedef struct { long gif_strip_size ; long gif_start_byte ; long gif_left_in_file; long gif_left_in_buf ; char far *lpGifSrcStart; unsigned char far *src; // 9504.13 jar no huge Hugo! //unsigned char huge *dst; unsigned char *dst; HWND hGifWindow; } GIF_DATA, FAR *LP_GIF_DATA; // 9504.13 jar no huge Hugo! //int ExpandGif(unsigned char far *, unsigned char huge *, // GIFFILEINFO far *, LP_FIO_DATA, LP_GIF_DATA); int ExpandGif(unsigned char far *, unsigned char *, GIFFILEINFO far *, LP_FIO_DATA, LP_GIF_DATA); //************************************************************************ // // ReadGIF // //************************************************************************ WORD ReadGif(HWND hWnd, lp_INFO lpGFSInfo, LP_FIO_DATA pdata, LPSTR lpDest, LPSTR lpSrc, LPINT read_from_line, LPINT this_many_lines) { char first = 0; int errcode = 0; int status = 0; int lines = 0; long bytestoget; long size; // 9504.13 jar no huge Hugo! //char huge *tempptr; char *tempptr; GIFFILEINFO gifinfo; GIF_DATA GifData; HANDLE hTempDest; // 9504.13 jar no huge Hugo! //char huge *lpTempDest; char *lpTempDest; // 9504.13 jar just memset baby //_fmemset((char FAR *) &gifinfo, 0, sizeof(gifinfo)); memset((char FAR *) &gifinfo, 0, sizeof(gifinfo)); gifinfo.width = (unsigned int) lpGFSInfo->horiz_size; gifinfo.depth = (unsigned int) lpGFSInfo->vert_size; gifinfo.bits = lpGFSInfo->_file.fmt.gif.bpp; gifinfo.flags = lpGFSInfo->_file.fmt.gif.Flags; gifinfo.codesize = ((unsigned char)lpGFSInfo->_file.fmt.gif.CodeSize); gifinfo.status = 0; if(gifinfo.bits == 1) gifinfo.linewidth = pixels2bytes(gifinfo.width); else if(gifinfo.bits > 1 && gifinfo.bits <= 4) gifinfo.linewidth = pixels2bytes(gifinfo.width) << 2; else if(gifinfo.bits > 4 && gifinfo.bits <= 8) gifinfo.linewidth = gifinfo.width; else gifinfo.linewidth = gifinfo.width * RGB_SIZE; //if (gifinfo.linewidth & 0x0003) // gifinfo.linewidth = (gifinfo.linewidth | 3) + 1; size = (long) gifinfo.linewidth * (long) (gifinfo.depth + 1); if (*read_from_line == 0) first = 1; while (lines != *this_many_lines) { if (first) { GifData.gif_strip_size = (unsigned long) pdata->CmpBuffersize; GifData.gif_start_byte = 0; GifData.gif_left_in_file = 0; GifData.gif_left_in_buf = 0; GifData.hGifWindow = hWnd; GifData.lpGifSrcStart = lpSrc; if ((GifData.gif_left_in_buf = wgfsread(hWnd, (int) pdata->filedes, (char far *) lpSrc, (long) pdata->start_byte, GifData.gif_strip_size, &GifData.gif_left_in_file, (unsigned short)pdata->pgnum, &errcode)) <= 0) { return errcode; } else { GifData.gif_start_byte += GifData.gif_left_in_buf; GifData.gif_strip_size = min(GifData.gif_strip_size, GifData.gif_left_in_file); } if ( (hTempDest = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, size)) == NULL) { return(FIO_GLOBAL_ALLOC_FAILED); } // 9504.13 jar no huge Hugo! //if( (lpTempDest = (char huge *) GlobalLock(hTempDest)) == NULL) if( (lpTempDest = (char *) GlobalLock(hTempDest)) == NULL) { GlobalFree(hTempDest); return(FIO_GLOBAL_LOCK_FAILED); } status = ExpandGif(lpSrc, lpTempDest, &gifinfo, pdata, (LP_GIF_DATA)&GifData); pdata->bytes_left = GifData.gif_left_in_file; if (FioSetProp(hWnd, "GIF_DATA", hTempDest) == 0) { GlobalUnlock(hTempDest); GlobalFree(hTempDest); return(FIO_PROPERTY_LIST_ERROR); } } else { hTempDest = FioGetProp(hWnd, "GIF_DATA"); if (hTempDest == 0) { return(FIO_PROPERTY_LIST_ERROR); } // 9504.13 jar no huge Hugo! //if( (lpTempDest = (char huge *) GlobalLock(hTempDest)) == NULL) if( (lpTempDest = (char *) GlobalLock(hTempDest)) == NULL) { GlobalFree(hTempDest); return(FIO_GLOBAL_LOCK_FAILED); } } if (gifinfo.status) { GlobalUnlock(hTempDest); GlobalFree(hTempDest); break; } else { bytestoget = (long) ((long) *this_many_lines * (long) gifinfo.linewidth); tempptr = (lpTempDest + (long) ((long) *read_from_line * (long) gifinfo.linewidth)); while (bytestoget--) { *lpDest++ = *tempptr++; } lines = *this_many_lines; *read_from_line += *this_many_lines; } } if (*read_from_line == (int) lpGFSInfo->vert_size) { GlobalUnlock(hTempDest); GlobalFree(hTempDest); FioRemoveProp(hWnd, "GIF_DATA"); } if (gifinfo.status) { GlobalUnlock(hTempDest); GlobalFree(hTempDest); FioRemoveProp(hWnd, "GIF_DATA"); // 9504.05 jar - make sure we can return WORD here! return((WORD) FIO_READ_ERROR); } else return (0); } /* error codes */ #define BAD_FILE 1 #define BAD_ALLOC 2 #define CANCEL_FUNCTION 3 #define NO_CODE -1 int masktable[8] = {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01}; //************************************************************************ // // gifgetc // //************************************************************************ int gifgetc (LP_FIO_DATA pdata, LP_GIF_DATA lpGifData) { int temp; int errcode = 0; if (lpGifData->gif_left_in_buf <= 0) { if (lpGifData->gif_left_in_file <= 0) return((int) -1); lpGifData->src = lpGifData->lpGifSrcStart; if ((lpGifData->gif_left_in_buf = wgfsread(lpGifData->hGifWindow, (int) pdata->filedes, (char far *) lpGifData->src, (long) lpGifData->gif_start_byte, lpGifData->gif_strip_size, &lpGifData->gif_left_in_file, 1, &errcode)) <= 0) { return((int) -1); } else { lpGifData->gif_start_byte += lpGifData->gif_left_in_buf; lpGifData->gif_strip_size = min(lpGifData->gif_strip_size, lpGifData->gif_left_in_file); } } temp = *lpGifData->src; ++lpGifData->src; --lpGifData->gif_left_in_buf; return(temp); } //************************************************************************ // // gifread // //************************************************************************ int gifread (char far *dest, int count, LP_FIO_DATA pdata, LP_GIF_DATA lpGifData) { int i; int totalcount; int errcode = 0; char far *dptr; char far *sptr; dptr = dest; sptr = lpGifData->src; totalcount = count; if ((long) count > lpGifData->gif_left_in_buf) { if (lpGifData->gif_left_in_file <= 0) return(0); for (i = 0; (long) i < lpGifData->gif_left_in_buf; ++i) { *dptr = *sptr; ++dptr; ++sptr; } count -= ((unsigned int) lpGifData->gif_left_in_buf); sptr = lpGifData->src= lpGifData->lpGifSrcStart; if ((lpGifData->gif_left_in_buf = wgfsread(lpGifData->hGifWindow, (int) pdata->filedes, (char far *) lpGifData->src, (long) lpGifData->gif_start_byte, lpGifData->gif_strip_size, &lpGifData->gif_left_in_file, 1, &errcode)) <= 0) { return(0); } else { lpGifData->gif_start_byte += lpGifData->gif_left_in_buf; lpGifData->gif_strip_size = min(lpGifData->gif_strip_size, lpGifData->gif_left_in_file); } } for (i = 0; i < count; ++i) { *dptr = *sptr; ++dptr; ++sptr; } lpGifData->src += count; lpGifData->gif_left_in_buf -= count; return (totalcount); } //************************************************************************ // // putline // //************************************************************************ // 9504.13 jar no huge Hugo! //int putline(char far *p, char huge * pl, unsigned int n, unsigned int lwidth) int putline(char far *p, char * pl, unsigned int n, unsigned int lwidth) { // 9504.13 jar no huge Hugo! //char huge *pr; char *pr; unsigned int i; if(pl != NULL) { pr=pl+(long)lwidth*(long)(n); for(i=0;icodesize; lpGifData->src = srcbuffer; lpGifData->dst = dstbuffer; linesdone = 0; p = q = (char *) b; bitsleft = 8; if (bits < 2 || bits > 8) { fi->status = BAD_FILE; return(linesdone); } bits2 = 1 << bits; nextcode = bits2 + 2; codesize2 = 1 << (codesize = bits + 1); oldcode=oldtoken=NO_CODE; /* allocate space for the stacks */ if((stacks=GlobalAlloc(GMEM_FIXED,16384))==NULL) { fi->status = BAD_ALLOC; return(linesdone); } if((firstcodestack=GlobalLock(stacks))==NULL) { GlobalFree(stacks); fi->status = BAD_ALLOC; return(linesdone); } lastcodestack=firstcodestack+4096; codestack=(int far *)(lastcodestack+4096); if((linebuffer = GlobalAllocPtr(GMEM_MOVEABLE, max(fi->width, (unsigned) fi->linewidth))) == NULL) { GlobalUnlock(stacks); GlobalFree(stacks); fi->status = BAD_ALLOC; return(linesdone); } if((extrabuffer = GlobalAllocPtr(GMEM_MOVEABLE, max(fi->width, (unsigned) fi->linewidth))) == NULL) { GlobalFreePtr((char FAR *) linebuffer); GlobalUnlock(stacks); GlobalFree(stacks); fi->status = BAD_ALLOC; return(linesdone); } /* loop until something breaks */ while (1) { if(bitsleft==8) { if(++p >= q && (((blocksize = gifgetc(pdata, lpGifData)) < 1) || (q=(p=b)+gifread(b, blocksize, pdata, lpGifData))< (b+blocksize))) { fi->status = BAD_FILE; goto error; } bitsleft = 0; } thiscode = *p; if ((currentcode=(codesize+bitsleft)) <= 8) { *p >>= (char)codesize; bitsleft = currentcode; } else { if(++p >= q && (((blocksize = gifgetc(pdata, lpGifData)) < 1) || (q=(p=b)+gifread(b, blocksize, pdata, lpGifData))< (b+blocksize))) { fi->status = BAD_FILE; goto error; } thiscode |= *p << (8 - bitsleft); if (currentcode <= 16) *p >>= (bitsleft=currentcode-8); else { if(++p >= q && (((blocksize = gifgetc(pdata, lpGifData)) < 1) || (q=(p=b)+gifread(b, blocksize, pdata, lpGifData))< (b+blocksize))) { fi->status = BAD_FILE; goto error; } thiscode |= *p << (16 - bitsleft); *p >>= (bitsleft = currentcode - 16); } } thiscode &= wordmasktable[codesize]; currentcode = thiscode; if(thiscode == (bits2+1)) break; /* found EOI */ if(thiscode > nextcode) { fi->status = BAD_FILE; goto error; } if(thiscode == bits2) { nextcode = bits2 + 2; codesize2 = 1 << (codesize = (bits + 1)); oldtoken = oldcode = NO_CODE; continue; } u = firstcodestack; if(thiscode==nextcode) { if(oldcode==NO_CODE) { fi->status = BAD_FILE; goto error; } *u++ = oldtoken; thiscode = oldcode; } while (thiscode >= bits2) { *u++ = lastcodestack[thiscode]; thiscode = codestack[thiscode]; } oldtoken = thiscode; do { linebuffer[byte++]=thiscode; if(byte >= (int) fi->width) { if(fi->bits==1) { memset(extrabuffer, 0xff, fi->linewidth); for(i = 0; i < (int) fi->width; ++i) { if(linebuffer[i]) extrabuffer[i>>3] |= masktable[i & 0x0007]; else extrabuffer[i>>3] &= ~masktable[i & 0x0007]; } if(putline(extrabuffer, lpGifData->dst, line, fi->linewidth)) { fi->status = CANCEL_FUNCTION; goto error; } ++linesdone; } else if(fi->bits > 1 && fi->bits <=4) { memset(extrabuffer, fi->background, fi->linewidth); for(i = j = 0; i < (int) fi->width;) { extrabuffer[j] = ((linebuffer[i++] & 0x0f) << 4); if(i < (int) fi->width) extrabuffer[j] |= linebuffer[i++] & 0x0f; ++j; } if(putline(extrabuffer, lpGifData->dst, line, fi->linewidth)) { fi->status = CANCEL_FUNCTION; goto error; } ++linesdone; } else { if(putline(linebuffer, lpGifData->dst, line, fi->linewidth)) { fi->status = CANCEL_FUNCTION; goto error; } ++linesdone; } byte=0; /* check for interlaced image */ if(fi->flags & 0x40) { line+=inctable[pass]; if(line >= (int) fi->depth) line=startable[++pass]; } else ++line; } if (u <= firstcodestack) break; thiscode = *--u; } while(1); if(nextcode < 4096 && oldcode != NO_CODE) { codestack[nextcode] = oldcode; lastcodestack[nextcode] = oldtoken; if (++nextcode >= codesize2 && codesize < 12) codesize2 = 1 << ++codesize; } oldcode = currentcode; } error: GlobalFreePtr(extrabuffer); GlobalFreePtr(linebuffer); GlobalUnlock(stacks); GlobalFree(stacks); return(linesdone); }