Skip to content
Snippets Groups Projects
Select Git revision
  • master default protected
  • fix_Makefile.mingw#2
  • update_Makefile.mingw
  • fix_Makefile.mingw
  • fix_API_for_C_apps
  • fix_procinfo_mac
  • boinccmd_gpu_mode_always_until_sigterm
  • fgrp_osx_hotfix
  • fix_boinc_master@f8250782
  • eah_wrapper_improvements
  • diagnostics_win-hotfix
  • diagnostics_win-hotfix-old
  • current_fgrp_apps
  • testing_gw_apps
  • gw_app_darwin_15
  • current_brp_apps
  • current_brp_apps_android10
  • current_gfx_apps
  • current_server
  • current_gw_apps
  • previous_fgrp_apps
  • previous_gw_apps
  • testing_brp_apps
  • apps_FGRP3_1.07
  • apps_FGRP3_1.08
25 results

bmplib.cpp

Blame
  • bmplib.cpp 5.29 KiB
    #ifdef _WIN32
    #include "boinc_win.h"
    #else
    #include "config.h"
    #endif
    
    #include "bmplib.h"
    
    // Returns true for success -- false otherwise
    bool DIB_BITMAP::set_size(int width, int height, int channels)	
    {
     
    	// If DIB_BITMAP has already been set -- clear it out first
    	FreeDIB_BMP();
    
    	// Create a temporary compatible device context
    	HDC temp_hdc = CreateCompatibleDC(NULL);
    		
    		// Error Check
    		if(!temp_hdc)
    			return false;
    
    	bmp_width = width; // Set the width
    	bmp_height = height; // Set the height
    	bmp_channels = channels; // Set the channels (3 == 24-bit, 4 == 32-bit)
    	
    	// Set stride -- The stride is the TRUE number of bytes in a line of pixels
    	// Windows makes all the .bmps DWORD aligned (divisible evenly by 4)
    	// So if you bitmap say was 103x103 pixels, Windows would add 1 "padding byte" to it
    	// so in memory it would be 104x103 pixels.  The "padding bytes" do not get blit (drawn)
    	// to the screen, they're just there so again everything is DWORD aligned which makes 
    	// blitting (drawing to the screen) easier for the OS
    	bmp_stride = bmp_width * bmp_channels;
    
    	while((bmp_stride % 4) != 0) // Ensure bmp_stride is DWORD aligned
    		bmp_stride++;
    		
    	BITMAPINFO bmp_info = {0};
    
    	// Initialize the parameters that we care about
    	bmp_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    	bmp_info.bmiHeader.biWidth = width;
    	bmp_info.bmiHeader.biHeight = height;
    	bmp_info.bmiHeader.biPlanes = 1; // Always equal 1
    	bmp_info.bmiHeader.biBitCount = channels * 8;
    	bmp_info.bmiHeader.biCompression = BI_RGB; // No compression
    	bmp_info.bmiHeader.biClrUsed = 0; // Always equals 0 with a 24 or 32-bit .bmp
    
    	// Create a DIBSection -- This returns us two things, an HBITMAP handle and
    	// a memory pointer (pointer to the pixels) in surface_bits
    	hbitmap = CreateDIBSection(temp_hdc, &bmp_info, DIB_RGB_COLORS,
    							   (void**)&surface_bits, 0, 0);
    
    	// Release our temporary HDC
    	DeleteDC(temp_hdc);
    
    		// Error Check -- Make sure the call to CreateDIBSection() DID NOT fail
    		if(!hbitmap)
    			return false;		
    		
    	return true; // We're sized :)
    
    } // end of set_size(int width, int height, int channels)
    
    bool DIB_BITMAP::loadBMP(const char *file_name)
    {
    	// If DIB_BITMAP has already been set -- clear it out first
    	FreeDIB_BMP();
    
    		// Error Check -- Make sure they passed in a valid file name
    		if(!file_name)
    			return false;
    
    	FILE *bmp_file = fopen(file_name, "rb");
    
    		// Error Check -- Make sure the file could be opened
    		if(!bmp_file)
    			return false;
    
    	BITMAPFILEHEADER bmp_fileheader;
    
    	// Read the BITMAPFILEHEADER
    	if(!fread(&bmp_fileheader, sizeof(BITMAPFILEHEADER), 1, bmp_file))
    	{
    		fclose(bmp_file);
    			return false;
    	}
    
    	// Check the type field to make sure we have a .bmp file
    	if(memcmp(&bmp_fileheader.bfType, "BM", 2))
    	{
    		fclose(bmp_file);
    			return false;
    	}
    
    	BITMAPINFOHEADER bmp_infoheader;
    	
    	// Read the BITMAPINFOHEADER.
    	if(!fread(&bmp_infoheader, sizeof(BITMAPINFOHEADER), 1, bmp_file))
    	{
    		fclose(bmp_file);
    			return false;
    	}
    
    	// We only support 24-bit and 32-bit .bmps so make sure that's what we have
    	if((bmp_infoheader.biBitCount != 24) && (bmp_infoheader.biBitCount != 32))
    	{
    		fclose(bmp_file);
    			return false;
    	}
    
    	// Set the size of our DIB_BITMAP, once we do this we're ready to store the pixel
    	// data in it
    	if(set_size(bmp_infoheader.biWidth,bmp_infoheader.biHeight,bmp_infoheader.biBitCount / 8) == false)
    	{
    		fclose(bmp_file);
    			return false;
    	}
    
    	// Jump to the location where the pixel data is stored
    	if(fseek(bmp_file, bmp_fileheader.bfOffBits, SEEK_SET))
    	{
    		fclose(bmp_file);
    			return false;
    	}
    	
    	unsigned int bytesPerLine = bmp_width * bmp_channels; // Bytes per line (number of bytes
    														 // in a scan line)
    	
    	// Calculate how many "padding" bytes there are -- WE DO NOT want to read in the
    	// padding bytes (we will just skip over those)
    	// **Remember** Windows adds padding bytes to ensure ALL .bmps are DWORD aligned
    	// (divisible evenly by 4)
    	unsigned int padding = bmp_stride - bytesPerLine;
    
    		// Loop over all the scan lines (all the rows of pixels in the image)
    		for(int y = bmp_height-1; y >= 0; y--)
    		{
    			// Get the "current" line pointer
    			uchar *LinePtr = getLinePtr(y);
    
    			// Read the precise number of bytes that the scan line requires into the bitmap
    			if(!fread(LinePtr, bytesPerLine, 1, bmp_file))
    			{
    				fclose(bmp_file);
    					return false;
    			}
    
    			// Skip over any padding bytes.
    			if(fseek(bmp_file, padding, SEEK_CUR))
    			{
    				fclose(bmp_file);
    					return false;
    			}
    	
    		} // end of for (int y = 0; y < bmp_infoheader.biHeight; y++)
    
    
    	fclose(bmp_file);
    		return true; // If we get here .bmp was read in successfully
    
    } // end of loadBMP(char *file_name, HDC hdc)
    
    // Returns the address in memory of the specified line. This gives you a pointer to at least 
    // width * channels bytes. Lines are numbered such that when the bitmap
    // is displayed line zero is at the top.
    uchar* DIB_BITMAP::getLinePtr(int which_line)
    {
    	return (surface_bits + bmp_stride * which_line);
    }
    
    // Release the memory
    void DIB_BITMAP::FreeDIB_BMP() 
    {
    	// If we created an HBITMAP, delete it
    	if(hbitmap)
    		DeleteObject(hbitmap);
    
    	// Zero out all data associated with DIB_BITMAP
    	hbitmap = NULL;
    	surface_bits = NULL;
    	bmp_width = bmp_height = bmp_channels = bmp_stride = 0;
    		return;
    }
    
    // Deconstructor
    DIB_BITMAP::~DIB_BITMAP() { FreeDIB_BMP(); }
    	
    
    const char *BOINC_RCSID_1051ce617a = "$Id$";