Desconozco si en las nuevas versiones ha cambiado en algo las implementaciones de ScanLine[] como de los tipos para almacenar la tercia RGB y el puntero a dicha estructura.
Lo que si recuerdo es que al menos para las versiones anteriores, había que incrementar el puntero para ubicarse en el siguiente pixel:
Esto compila en D6, D7, y si no me equivoco al menos hasta D2006 (y quizá hasta XE1):
const
{* Constantes asociadas a los canales *}
BLUE = 1; // Canal 1 -> Frecuencias Bajas
GREEN = 2; // Canal 2 -> Frecuencias Medianas
RED = 3; // Canal 3 -> Frecuencias Altas
type
{* Estructuras asociadas al canal *}
TRGBChannel = array[BLUE..RED] of byte;
PTRGBChannel = ^TRGBChannel;
TRGBArray = array[1..3] of byte;
function RGBtoGray(RGB: TRGBArray; Option: TGrayOption): byte;
{******************************************************************************
Descripción:
Calcula el nuevo valor de gris en función del formato a utilizar.
Parámetros:
- RGB: Estructura del Canal a evaluar
- Option: Formato de conversión a utilizar.
* goBrightness: Basado en el brillo.
* goIntensity: Basada en la intensidad.
******************************************************************************}
var i, sum: integer;
begin
sum := 0;
if Option = goBrightness
then result := Round((0.3 * RGB[RED]) + (0.59 * RGB[GREEN]) +
(0.11 * RGB[BLUE]))
else begin
for i:= RED downto BLUE do
sum := sum + RGB[i];
result := Round(sum/3);
end;
end; {* Fin F. RGBtoGray *}
function ImageToGray(Image: TPicture; Option: TGrayOption): dword;
{******************************************************************************
Descripción:
Convierte una imagen en color a nivel de gris dependiendo del formato de con-
versión elegido.
La imagen resultante es formateada a mapas de bits, independientemente del for-
mato inicial.
Parámetros:
- Image: Imagen a convertir.
- Option: formato de conversión a utilizar.
* goBrightness: Basado en el brillo.
* goIntensity: Basada en la intensidad.
Resultados:
- CONVERT_TO_GRAY: ante una operación exitosa.
- NOT_CONVERT_TO_GRAY: ante una operación fallida.
******************************************************************************}
var PChannel: ^TRGBChannel;
i, j: integer;
B: byte;
Bmp: TBitmap;
RGB: TRGBArray;
begin
// Damos por supuesto que no se pudo realizar la operación
result := NOT_CONVERT_TO_GRAY;
// Si no es formato de mapa de bits hay que convertirla
if not (Image.Graphic is TBitmap)
then begin
Bmp := TBitmap.Create;
try
Bmp.Width := Image.Width;
Bmp.Height := Image.Height;
Bmp.Canvas.Draw(0,0,Image.Graphic);
Image.Assign(Bmp);
finally
Bmp.Free;
end;
end;
// Asignamos un formato de 24 bits (pero a nivel de gris)
Image.Bitmap.PixelFormat := pf24bit;
for j := 0 to Image.Bitmap.Height - 1 do
begin
PChannel := Image.Bitmap.ScanLine[j];
for i := 0 to Image.Bitmap.Width - 1 do
begin
// guardamos los valores en un vector
RGB[BLUE] := PChannel^[BLUE];
RGB[GREEN] := PChannel^[GREEN];
RGB[RED] := PChannel^[RED];
// obtenemos el nuevo valor según opción
// los tres canales deben tener igual valor para formar gris
B := RGBToGray(RGB,Option);
PChannel^[BLUE] := B;
PChannel^[GREEN] := B;
PChannel^[RED] := B;
inc(PChannel);
end;
end;
// Finalizó la operación en forma exitosa
result := CONVERT_TO_GRAY;
end; {* Fin F. ImageToGray *}
Esta muestra de código es una pequeña parte de mis primeras implementaciones de mi "mini-framework" de tratamiento de imágenes. Tiene sus años, y debo actualizarlo para portarlo a Lazarus. Aunque no se si tendría sentido, ya que la suite BGRABitmap que viene incluída en CodeTyphon ya de base ofrece muchas de las funcionalidades que yo estuve haciendo en mi mini framework.
Puede verse que dentro del for width al final se realiza un Inc(). Al avanzar en 1, se consigue que ahora el puntero apunte al siguiente pixel.
Ahora desconozco si algo ha cambiado en los nuevos Delphi como para que no se necesite estar desplazando el puntero y lo hace automáticamente.
Lo que si sería oportuno mencionar es el tipo de algoritmo que implementa cada versión. Tu ConvertToGrayScale1 se basa en la teoría del brillo (que según los entendidos es el algoritmo más apropiado) mientras que el ConvertToGrayScale2 se basa en la teoría de la intensidad.
En lo posible debe evitarse recorrer los pixels mediante Pixels[]. Es una forma ineficiente. En su lugar se aconseja emplear Scanline[] que trabaja a bajo nivel y está optimizada. No creo que te resulte difícil implementar una versión de ConvertToGrayScale1 utilizando Scanline[] como si lo aplicas en la versión 2. 
Saludos,