/***************************************************************************** * * LoadBMP * * Uses GS/OS native I/O routines to read in a windows BMP file. We only * support 4-bit, uncompressed images * *****************************************************************************/ #include #include #include "bmp.h" Handle LoadBMP( char *filename, LocInfo *locInfo, Word *colorTable ) { FileInfoRec fiRec; /* GetFileInfo record */ RefNumRecGS clRec; /* CloseGS record */ OpenRecGS opRec; /* OpenGS record */ IORecGS rdRec; /* ReadGS record */ SetPositionRecGS spRec; /* SetMarkGS record */ GSString255 fileStr; BMPHeader bmpHeader; BMPInfo bmpInfo; RGBTuple bmpColor; Pointer imagePtr; Handle imageHndl = NULL; /* handle to the memory it's in */ LongWord buffsize; int i; /* Convert the filename to a p-string */ fileStr.length = strlen( filename ); strcpy( fileStr.text, filename ); /* Only open binary files (Filetype $06) */ fiRec.pCount = 4; fiRec.pathname = &fileStr; GetFileInfoGS(&fiRec); /* If we cannot get the file information, fail */ if (toolerror()) return NULL; /* Verify the filetype and auxtype match */ if ( fiRec.fileType != 0x06 ) return NULL; /* We've verified it is a binary file, open the file */ opRec.pCount = 12; opRec.pathname = &fileStr; opRec.requestAccess = 1; opRec.resourceNumber = 0; opRec.optionList = NULL; OpenGS(&opRec); if (toolerror()) return NULL; /* Fill in part of other records with data from the open record */ clRec.pCount = 1; clRec.refNum = opRec.refNum; /* These parameters remain the same in the inner loop */ spRec.pCount = 3; spRec.refNum = opRec.refNum; spRec.base = startPlus; spRec.displacement = 0; rdRec.pCount = 4; rdRec.refNum = opRec.refNum; /* Read in the BMP header */ rdRec.dataBuffer = (Pointer) &bmpHeader; rdRec.requestCount = 14; ReadGS(&rdRec); if (toolerror() != 0) goto fail; /* Signature 'BM' */ if ( bmpHeader.type != 0x4D42 ) goto fail; /* Read the BMP Info record */ rdRec.dataBuffer = (Pointer) &bmpInfo; rdRec.requestCount = 40; ReadGS(&rdRec); if (toolerror() != 0) goto fail; /** * We only support 4 bits per pixel, 1 graphics plane and image sizes * less than 64K */ if ( bmpInfo.planes != 1 || bmpInfo.compression != BMP_NO_COMPRESS || bmpInfo.bits != 4 || bmpInfo.imagesize >= 0x010000 ) goto fail; /* Everything is fine. */ if ( colorTable != NULL ) { for ( i = 0; i < bmpInfo.ncolors; i++ ) { /* Read in the color */ rdRec.dataBuffer = (Pointer) &bmpColor; rdRec.requestCount = 4; ReadGS(&rdRec); colorTable[i] = (bmpColor.b >> 4) | (bmpColor.g & 0xF0) | ((bmpColor.r & 0xF0) << 4); } } /* Fill in the locInfo record and allocate the memory, round width to */ /* the nearest multiple of eight byte */ locInfo->portSCB = 0x00; locInfo->width = ((bmpInfo.width + 15) / 2) & 0xFFF8; locInfo->boundsRect.v1 = 0; locInfo->boundsRect.h1 = 0; locInfo->boundsRect.v2 = bmpInfo.height; locInfo->boundsRect.h2 = bmpInfo.width; buffsize = bmpInfo.height * locInfo->width; /* Allocate the memory */ imageHndl = NewHandle( buffsize, userid(), 0x8014, NULL ); if ( toolerror() ) goto fail; /* Finish filling in the locInfo record */ imagePtr = *imageHndl; locInfo->ptrToPixImage = imagePtr; /* Move the the data */ spRec.base = startPlus; spRec.displacement = bmpHeader.offset; SetMarkGS( &spRec ); /* Read in the data. It is stored bottom-up, left-to-right */ imagePtr += (bmpInfo.height - 1) * locInfo->width; for (i = 0; i < bmpInfo.height; i++) { rdRec.dataBuffer = (Pointer) imagePtr; rdRec.requestCount = bmpInfo.width / 2; ReadGS(&rdRec); if ( toolerror() ) break; imagePtr -= locInfo->width; } fail: CloseGS(&clRec); /* close the file */ return imageHndl; }