Each scanline is a pointer to an array of pixels for that row, so you can save it by saving the first element of the scanline array. Here's some generalised code for saving 16, 24 and 32 bit bmps as RAW files (the usual disclaimers apply):


[pascal][background=#FFFFFF][comment=#0000FF][normal=#000000]
[number=#C00000][reserved=#000000][string=#00C000]type
TRawHeader = record
Width: Integer;
Height: Integer;
BitsPerPixel: Integer;
end;
PRawHeader = ^TRawHeader;

TPixelArray = array[0..0] of Byte;
PPixelArray = ^TPixelArray;

const
BitCount: array[TPixelFormat] of Integer = (-1, 1, 4, 8, 15, 16, 24, 32, -1);

// the following doesn't handle pfCustom
function PixelFormatToInt(PixFormat: TPixelFormat): Integer;
var
DC: HDC;
begin
if PixFormat = pfDevice then // get current screen bpp
begin
DC := GetDC(0);
try
// todo: confirm this is correct
Result := GetDeviceCaps(DC, PLANES) * GetDeviceCaps(DC, BITSPIXEL);
finally
ReleaseDC(0, DC);
end;
end
else
if (PixFormat >= pf1Bit) and (PixFormat <= pf32Bit) then
Result := BitCount[PixFormat]
else
raise Exception.Create('Unexpected pixel format in PixelFormatToInt');
end;

function IntToPixelFormat(BitsPerPixel: Integer): TPixelFormat;
begin
case BitsPerPixel of
1 : Result := pf1Bit;
4 : Result := pf4Bit;
8 : Result := pf8Bit;
15: Result := pf15Bit;
16: Result := pf16Bit;
24: Result := pf24Bit;
32: Result := pf32Bit;
else
raise Exception.CreateFmt('Unexpected bits per pixel count in IntToPixelFormat: %d', [BitsPerPixel]);
end;
end;

//
// SaveAsRaw
//
// loads up the bitmap file given by InFile (e.g. "c:\windows\setup.bmp") and
// saves it to a raw file in the given pixel format
//
procedure SaveAsRaw(const InFilename, OutFilename: String; PixFormat: TPixelFormat);
var
bmp: TBitmap;
i: integer;
F: File;
ThisLine: PPixelArray;
Header: TRawHeader;
BitsPerPixel: Integer;
WidthOfScanline: Integer;
begin
BitsPerPixel := PixelFormatToInt(PixFormat);

if not (BitsPerPixel in [16, 24, 32]) then
raise Exception.Create('SaveAsRaw only supports 16, 24 and 32 bpp at present');

if not FileExists(InFilename) then
raise Exception.Create('The file ' + InFilename + ' does not exist');

bmp := TBitmap.Create;
try
bmp.LoadFromFile(InFilename);
bmp.PixelFormat := PixFormat;

Header.Width := Bmp.Width;
Header.Height := Bmp.Height;
Header.BitsPerPixel := BitsPerPixel;

AssignFile(F, OutFilename);
try
Rewrite(F, 1);

WidthOfScanline := Bmp.Width * (BitsPerPixel div ; // bytes per scanline

BlockWrite(F, Header, SizeOf(TRawHeader));

for i := 0 to Bmp.Height - 1 do
begin
ThisLine := Bmp.ScanLine[i];
BlockWrite(F, ThisLine[0], WidthOfScanline);
end;
finally
CloseFile(F);
end;
finally
Bmp.free;
end;
end;

//
// LoadBitmapFromRAW
//
// Loads the RAW file given by filename into the supplied Bmp. The result
// will be a DIB of the RAW's pixel format
//
procedure LoadBitmapFromRAW(const Filename: String; Bmp: TBitmap);
var
F: File;
Header: TRawHeader;
y: Integer;
WidthOfScanline: Integer;
begin
if not FileExists(Filename) then
raise Exception.Create('The file ' + Filename + ' does not exist!');

AssignFile(F, Filename);
try
Reset(F, 1);

BlockRead(F, Header, SizeOf(TRawHeader));

if not (Header.BitsPerPixel in [16, 24, 32]) then
raise Exception.Create('LoadBitmapFromRAW only supports 16, 24 or 32 bits per pixel at present');

Bmp.PixelFormat := IntToPixelFormat(Header.BitsPerPixel);
Bmp.Width := Header.Width;
Bmp.Height := Header.Height;

WidthOfScanline := Bmp.Width * (Header.BitsPerPixel div ; // bytes per scanline

for y := 0 to Header.Height - 1 do
begin
BlockRead(F, PPixelArray(Bmp.Scanline[y])^[0], WidthOfScanline);
end;
finally
CloseFile(F);
end;
end;

////////////////////////////////////////////////////////////////////////////////
// QUICK TEST PROCEDURES
////////////////////////////////////////////////////////////////////////////////

procedure TForm1.btnSaveClick(Sender: TObject);
begin
SaveAsRaw('c:\windows\setup.bmp', 'c:\test.raw', pf24Bit);
end;

procedure TForm1.btnLoadClick(Sender: TObject);
var
Bmp: TBitmap;
begin
Bmp := TBitmap.Create;
try
LoadBitmapFromRAW('c:\test.raw', Bmp);
Canvas.Draw(0,0, Bmp);
finally
Bmp.Free;
end;
end;[/pascal]

You'd definitely want to encrypt them though! See the EFG link; saving in binary format with BlockWrite gives you no additional protection. You can also have a look around Torry for encryption components - there are plenty free ones there.