The one thing to understand first
A plain index scan is great for high selectivity (few rows) and a sequential scan is great for low selectivity (most rows). In between — say 1–15% of a table — both are suboptimal: the index scan jumps around the heap in random order, while the seq scan reads far too much. The bitmap scan fills this gap and is implemented in src/backend/executor/nodeBitmapHeapScan.c and the bitmap index scan nodes.
A bitmap scan trades index order for heap order: it collects all matching row locations first, then reads the heap once in physical block order. That single reordering is what turns thousands of random I/Os into mostly sequential ones — and it’s why bitmaps can also intersect several indexes on the fly.
Two phases
A bitmap scan splits into a Bitmap Index Scan and a Bitmap Heap Scan: