MovePelican
The purpose of program MovePelican is to copy a pelican from a photograph with the blue background of the sky to the unfamiliar setting of the Thames. The bitmaps (.bmp files) used here use 24 bits per pixel. They use one byte each for the red, green and blue intensities of each pixel; there is no colour table. After a 54 byte header, the bytes for each row are given in the order blue, green, and then red. The first row of data corresponds to the bottom row of the graphic. The format requires that padding bytes are included to keep each row to a multiple of 32 bits. For convenience, all three graphics have same width and height. The code copies pixels that are not in shades of background blue to the target file. The two starting images and the result are shown below.
You need a copy of pelican.bmp and london_eye.bmp in your program folder. We obtained both images (the-london-eye-and-the-aquarium_w725_h544 and pelicans-wings-flying_w725_h544) from Public-Domain-Image.com, but had to change the colour of pixels close to the pelican to create pelican.bmp in order to obtain a satisfactory result.
program MovePelican; {$APPTYPE CONSOLE} uses SysUtils; var Background, Foreground : file of byte; R, G, B, Dummy : byte; Start, Row, Col, Width, Height, RowDataMod4, PaddingWidth, i, FileSize: integer; function ReadInt(RecNo : integer) : integer; var Byte1, Byte2, Byte3, Byte4 : byte; begin seek(Foreground, RecNo); read(Foreground, Byte1); read(Foreground, Byte2); read(Foreground, Byte3); read(Foreground, Byte4); {Four bytes of integer stored 'little endian' (with least significant byte first)} result := Byte1 + Byte2 * 256 + Byte3 * 256 * 256 + Byte4 * 256 * 256 * 256; end; begin assignfile(Background, 'london_eye.bmp'); assignfile(Foreground, 'pelican.bmp'); reset(Background); reset(ForeGround); Start := ReadInt(10); writeln('Start: ', Start); Width := ReadInt(18); writeln('Width: ', Width); RowDataMod4 := (Width * 3) MOD 4; if RowDataMod4 = 0 then begin PaddingWidth := 0; end else begin PaddingWidth := 4 - RowDataMod4; end; writeln('PaddingWidth: ', PaddingWidth); Height := ReadInt(22); writeln('Height: ', Height); FileSize := (Width * 3 + PaddingWidth) * Height + 54; writeln('File size: ', FileSize); //Move file pointers to start of data then copy required pixels seek(Background, 54); seek(Foreground, 54); for Row := Height downto 1 do begin for Col := 1 to Width do begin read(Foreground, B); read(Foreground, G); read(Foreground, R); //Do not copy these shades of blue if (R > 60) and (R < 160) and (G > 90) and (G < 180) and (B > 150) and (B < 220) then begin //Move the target file pointer 3 places read(Background, Dummy); read(Background, Dummy); read(Background, Dummy); end else //Write byte of pelican begin write(Background, B); write(Background, G); write(Background, R); end; end; //Col if PaddingWidth > 0 then begin //Advance the pointer past the padding bytes in both files. for i := 1 to PaddingWidth do begin read(ForeGround, Dummy); read(Background, Dummy); end; end; end; //Row closefile(Background); closefile(Foreground); readln; end.