Saving a BitMap
Save a BitMap manually (using a handle).

I've made several assumptions here:

  • You have a 24-bit (True-Colour) BitMap (BitCount = 24)
  • You want to save the entire bitmap (and not just a region)
  • The BitMap is not currently selected into any Device Contexts
Step 1:
Make a word-alignment function

function bmAlignDouble(Size: Integer): Integer;
begin
  Result := (Size + 31) div 32 * 4;
end;
Step 2:

Create the Function. This is based on the old BitMaps.Pas that shipped with Borland Pascal 1.5, only upgraded to Win32 IO calls.

function SaveToFile(FileName: PChar; HBM: HBitmap): Boolean;
var
  BM: Windows.TBitmap;          //Bitmap information
  BFH: TBitmapFileHeader;       //Bitmap file information
  BIP: PBitmapInfo;             //Part of bitmap file information
  DC: HDC;                      //Drawing context

  Buf: Pointer;                 //Memory for bitmap

  ColorSize, DataSize: Integer; //Size needed to store Color/Data
  BitCount: Word;               //Number of bits per pixel
  H: Integer;                   //File
  W: DWord;
begin
  Result := False;
  //Get the information about the Bitmap
  if GetObject(HBM, SizeOf(Windows.TBitmap), @BM) = 0 then Exit;

  BitCount := 24;  //or 1 or 8
  if (BitCount <> 24) then
    ColorSize := SizeOf(TRGBQuad) * (1 shl BitCount)
  else
    ColorSize := 0;
  DataSize := bmAlignDouble(bm.bmWidth * BitCount) * bm.bmHeight;
  //Create the file
  H := CreateFile(FileName, GENERIC_WRITE or GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, CREATE_ALWAYS, 0, 0);
  if H = INVALID_HANDLE_VALUE then Exit;

  //Allocate memory for the bitmap info structure
  GetMem(BIP, SizeOf(TBitmapInfoHeader) + ColorSize);

  if BIP <> nil then
    begin
      //Fill in the Bitmap info header
      with BIP^.bmiHeader do
        begin
          biSize := SizeOf(TBitmapInfoHeader);
          biWidth := bm.bmWidth;
          biHeight := bm.bmHeight;
          biPlanes := 1;
          biBitCount := BitCount;
          biCompression := 0;
          biSizeImage := DataSize;
          biXPelsPerMeter := 0;
          biYPelsPerMeter := 0;
          biClrUsed := 0;
          biClrImportant := 0;
        end;
      //Fill in the file header
      with BFH do
        begin
          bfOffBits := SizeOf(BFH) + SizeOf(TBitmapInfo) + ColorSize;
          bfReserved1 := 0;
          bfReserved2 := 0;
          bfSize := bfOffBits + DataSize;
          bfType := $4D42;      //Standard Bitmap header
        end;
      //Create the memory Bitmap
      GetMem(Buf, DataSize);
      //Get the bitmap bits in device independent format
      DC := GetDC(0);
      if GetDIBits(DC, hbm, 0, bm.bmHeight, Buf, BIP^, dib_RGB_Colors) <> 0 then
        begin
          //Write to file
          WriteFile(H, BFH, SizeOf(BFH), W, nil);
          WriteFile(H, BIP^, SizeOf(TBitmapInfo) + ColorSize, W, nil);
          WriteFile(H, Buf^, DataSize, W, nil);
          Result := True;
        end;
      ReleaseDC(0, DC);
      //Clean up
      FreeMem(Buf, DataSize);
    end;
  FreeMem(BIP, SizeOf(TBitmapInfoHeader) + ColorSize);
  CloseHandle(H);
end;
Notes:
You'll have to actually make the bitmap first. Seek the tutorial on loading bitmaps for help there.

By Playing with BitCount you can actually save in several formats. See the pictures below of Katie Price:
Original
1-bit

8-bit

24-bit

Home