Working with the RAW File Filter

The RAW File Filter can be used to load and save raw uncompressed data. The raw data can have

image\sqrblit.gif any offset in the file

image\sqrblit.gif any bits per pixel

image\sqrblit.gif any width/height

image\sqrblit.gif each line padded to 4 bytes

image\sqrblit.gif any view perspective

image\sqrblit.gif BGR or RGB color order

Loading a file with the RAW filter

Parameters for loading raw uncompressed data are set through the LOADINFOCALLBACK. To do this you must call L_SetLoadInfoCallback() with your defined LOADINFOCALLBACK function. To get the user data previously set using L_SetLoadInfoCallback, use L_GetLoadInfoCallbackData. When calling the file load functions (L_LoadFile, L_LoadBitmap, etc) , it is also necessary to pass a FILEINFO structure with the Format field set to FILE_RAW and the Flags field set to FILEINFO_FORMATVALID. This triggers your LOADINFOCALLBACK function.

Inside the LOADINFOCALLBACK, set the Format field to FILE_RAW. Valid values must be set for the following LOADINFO fields: Width, Height, BitsPerPixel, Offset (byte location in file where raw data begins). If each line of RAW data is padded so that the number of bytes is a multiple of 4 (as is the case with raw Windows BMP data), include LOADINFO_PAD4 in the Flags field. Include an orientation flag in the Flags field to load with the proper orientation. For example, raw Windows BMP data is stored with a BOTTOM_LEFT orientation. If the orientation is unknown, include the TOP_LEFT flag. If the raw data is 8 bits per pixel or less, then the image is palettized and a palette must be generated. If this is the case, include the LOADINFO_PALETTE flag, and fill in the first (2BitsPerPixel) entries of the rgbQuad field.

If the color order is ORDER_RGB then include this flag. If the ORDER_RGB flag is not included, the data will be loaded as ORDER_BGR.

Saving a file with the RAW filter

To save raw uncompressed data, an image must already be loaded into a BITMAPHANDLE. When saving raw uncompressed data, the raw data will be correspond to the width, height, bits per pixel, and color order, and view perspective of the image when it was loaded. For example, suppose a Window BMP file that is 300x400 24-bit color is loaded. If this file is saved as raw uncompressed data, the raw data is 24-bit, ORDER_BGR, with a view perspective BOTTOM_LEFT (the first bytes in the file correspond to the bottom-left of the image). The total size of the raw data file will be 300x400x3 = 360,000 bytes.

You can affect the way the raw data is saved by setting certain parameters in the SAVEFILEOPTION structure. A pointer to a SAVEFILEOPTION structure is an argument to all the file save API functions (L_SaveFile, L_SaveBitmap, etc).

The bits in each byte can be reversed by including the ESO_REVERSEBITS flag in SAVEFILEOPTION.Flags. Each line of raw data can be padded so that the length is a multiple of four bytes by including the ESO_PAD4 flag in SAVEFILEOPTION.Flags. The raw data can be saved at any offset in the file by using the L_SaveFileOffset.

LEAD also supports saving Raw LZW data using the FILE_RAW_LZW file format constant when saving the data. Please note that when this option is used, the view perspective is ignored. The main purpose of this option is to provide support for saving LZW images that are embedded in other file formats such as PDF.

When using L_SaveFile to save RAW data that is 8 bits per pixel or less, it is necessary to pass the OPTIMIZED_PALETTE flag to disable any dithering prior to the save. Note that no palette information is saved in the RAW file. Consequently, after loading RAW data, it is necessary to supply a palette.(see Loading a file with the RAW filter above)

The following examples demonstrate how to load and save raw uncompressed data.

//This example saves a LEAD BITMAPHANDLE as RAW data starting at offset uOffset.
//The data is padded so that each line of bytes is evenly divided by 4.
//The bits in each byte are reversed before saving.
//The bits per pixel of the raw data is the same as the bits per pixel of pBitmap.
//If pBitmap is a palettized image, the palette is not saved--only the raw data.
//The OPTIMIZED_PALETTE flag is used to disable dithering on images with 8 bits or pixel or less.
//Note that when saving a file as RAW data, the view perspective is ignored.
L_INT SaveRawData(L_TCHAR *pszFileName, pBITMAPHANDLE pBitmap, L_UINT32 uOffset)
{
   SAVEFILEOPTION SaveFileOption;
   L_INT nRet;
   
   memset(&SaveFileOption, 0, sizeof(SAVEFILEOPTION));
   SaveFileOption.uStructSize = sizeof(SAVEFILEOPTION);
   SaveFileOption.Flags = ESO_PAD4 | ESO_REVERSEBITS;
   
   if (uOffset == 0)
   {
      nRet = L_SaveFile(pszFileName, pBitmap, FILE_RAW, 0, 0, SAVEFILE_OPTIMIZEDPALETTE, NULL, NULL, &SaveFileOption);
   }
   else 
   {
      HFILE hFile; 
      L_UINT32 SizeWritten;
      
      #ifdef UNICODE

hFile = _wcreat(pszFileName, 0);

#else

hFile = _lcreat(pszFileName, 0);

#endif

      nRet  = L_SaveFileOffset(hFile, uOffset, &SizeWritten, pBitmap, FILE_RAW, 0, 0, SAVEFILE_OPTIMIZEDPALETTE, NULL, NULL, &SaveFileOption);
      _lclose(hFile);
   }
   return nRet;
}

//This example loads RAW data into a LEAD BITMAPHANDLE.
//Raw data parameters are set in the MyLoadInfoCallBack, which gets called
//when the file format is FILE_RAW, or any unrecognized file format.
//The MyLoadInfoCallBack obtains information through a user-defined structure.
//In this example it is RAWLOADDATA
//
//typedef struct tagRAWLOADDATA
//{
//   L_INT nWidth;               //width of image
//   L_INT nHeight;              //height of image
//   L_INT nBitsPerPixel;        //bits per pixel of image--if palettized, a gray palette is generated
//   L_INT nViewPerspective;     //view perspective of raw data (TOP_LEFT, BOTTOM_LEFT, etc)   
//   L_INT nOrder;               //ORDER_RGB or ORDER_BGR
//   L_INT nOffset;              //offset into file where raw data begins
//   L_INT bPadding;             //TRUE if each line of data is padded to four bytes
//   L_INT bReverseBits          //TRUE if the bits of each byte are reversed 
//} RAWLOADDATA,  *LPRAWLOADDATA;

L_INT L_EXPORT EXT_CALLBACK MyLoadInfoCallBack( L_INT fd, pLOADINFO pInfo, L_VOID  *pUserData )
{
   LPRAWLOADDATA pRawData = (LPRAWLOADDATA)pUserData;
   
   UNREFERENCED_PARAMETER(fd);
   
   pInfo->Format        = FILE_RAW;
   pInfo->Width         = pRawData->nWidth;          
   pInfo->Height        = pRawData->nHeight;             
   pInfo->BitsPerPixel  = pRawData->nBitsPerPixel;       
   pInfo->XResolution   = 150;        
   pInfo->YResolution   = 150;        
   pInfo->Offset        = pRawData->nOffset;
   
   pInfo->Flags = 0;
   
   if (pRawData->bPadding)
      pInfo->Flags |= LOADINFO_PAD4;
   
   if (pRawData->nOrder == ORDER_RGB)
      pInfo->Flags |= LOADINFO_ORDERRGB;

   if (pRawData->bReverseBits)
      pInfo->Flags |= LOADINFO_LSB;

   switch(pRawData->nViewPerspective)
   {
   case TOP_LEFT:
      pInfo->Flags |= LOADINFO_TOPLEFT;
      break;
      
   case BOTTOM_LEFT:
      pInfo->Flags |= LOADINFO_REVERSE;
      break;
      
   case TOP_RIGHT://BOTTOM_LEFT180
      pInfo->Flags |= LOADINFO_BOTTOMLEFT180;
      break;
      
   case BOTTOM_RIGHT: //TOP_LEFT180    
      pInfo->Flags |= LOADINFO_TOPLEFT180;
      break;
      
   case RIGHT_TOP:  //TOP_LEFT90  
      pInfo->Flags |= LOADINFO_TOPLEFT90;
      break;
      
   case LEFT_BOTTOM: //TOP_LEFT270  
      pInfo->Flags |= LOADINFO_TOPLEFT270;
      break;
      
   case LEFT_TOP: //BOTTOM_LEFT90
      pInfo->Flags |= LOADINFO_BOTTOMLEFT90;
      break;
      
   case RIGHT_BOTTOM: //BOTTOM_LEFT270        
         pInfo->Flags |= LOADINFO_BOTTOMLEFT270;
         break;
   }
   
   //if image is palettized create a grayscale palette
   if ( pInfo->BitsPerPixel <= 8)
   {     
      L_INT nColors, i;
      nColors = 1 <<  pInfo->BitsPerPixel;
      pInfo->Flags |= LOADINFO_PALETTE;
      
      for (i=0; i<nColors; i++)
      {
         pInfo->rgbQuad[i].rgbBlue  = (i * 256) / nColors;
         pInfo->rgbQuad[i].rgbGreen = (i * 256) / nColors;
         pInfo->rgbQuad[i].rgbRed   = (i * 256) / nColors;
         pInfo->rgbQuad[i].rgbReserved = 0;
      }
   }
   
   return SUCCESS;
}

L_INT LoadRawData(L_TCHAR *pszFile, pBITMAPHANDLE pBitmap, LPRAWLOADDATA pRawLoadData)
{
   LOADINFOCALLBACK OldCallback;
   L_INT   nRet;
   FILEINFO FileInfo;
   
   memset(&FileInfo, 0, sizeof(FILEINFO));
   FileInfo.Format = FILE_RAW;
   FileInfo.Flags = FILEINFO_FORMATVALID;
   
   OldCallback = L_SetLoadInfoCallback(MyLoadInfoCallBack, (L_VOID *)pRawLoadData);   
   
   nRet = L_LoadFile(
      pszFile, 
      pBitmap, sizeof(BITMAPHANDLE), 
      0, 
      ORDER_BGR, 
      LOADFILE_ALLOCATE | LOADFILE_STORE, 
      NULL, 
      NULL, 
      NULL,
      &FileInfo);
   
   L_SetLoadInfoCallback(OldCallback, NULL);
   return nRet;
}

 

NOTE: This format does not support LEAD's redirected IO feature, therefore it cannot be used with L_RedirectIO, L_LoadBitmapMemory, L_LoadMemory, L_SaveBitmapMemory, or L_FeedLoad.