The fastest way (and where you have more control) is to loop among all pixels and map (with a LUT) each pixel to the right value. For example:
const
MAP: array [0..255] of byte = (
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // zone0: 0..12
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // zone1: 13..38
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // zone2?: ...
...etc...
);
var
i, j: integer;
pb: pbyte;
begin
ImageEnView1.LegacyBitmap := false;
ImageEnView1.IEBitmap.PixelFormat := ie8g;
for i := 0 to ImageEnView1.IEBitmap.Height - 1 do
begin
pb := ImageEnView1.IEBitmap.ScanLine[i];
for j := 1 to ImageEnView1.IEBitmap.Width do
begin
pb^ := MAP[pb^];
inc(pb);
end;
end;
ImageEnView1.Update();
end;
You have to fill MAP array with the right desired values. Otherwise you could replace...
pb^ := MAP[pb^];
...with a IF:
if pb^ < 12 then
pb^ := 0
else if pb^ < 38 then
pb^ := 1
etc...