Bueno, pues ya he hecho una prueba de velocidad de LCMS y me temo que tendremos que hacerlo una sola vez sobre toda la imagen y guardar dos buffers por cada revelado.
He convertido de un perfil a otro una imagen de 800x600 (y podemos tener vistas más grandes que eso) 1000 veces y ha tardado 122.5 segundos, es decir que tenemos poco más de 8 fotogramas por segundo. Eso no es suficiente para dar un aspecto suave al scroll/zoom de las vistas, que necesita un mínimo de 20 fps.
Hago 1000 veces sólo la conversión, no la carga de los perfiles y lo hago en toda la imagen en un sólo paso. LCMS podría ir más rápido si compilara con la opción de usar algoritmos en ensamblador, pero eso limitaría la portabilidad y requeriría cambios más laboriosos en su código fuente (porque la sintaxis para incluir ensamblador en gcc es muy diferente a la que usa LCMS... lo malo es que LCMS no admite el uso de ensamblador en entornos que no sean Windows, así que creo que es mejor dejarlo así. De momento no se puede hacer más rápido. Pego un poco de código:
Código:
#ifdef NON_WINDOWS
[...]
#ifdef USE_ASSEMBLER
# undef USE_ASSEMBLER
# define USE_C 1
#endif
¿Alguno os animáis a traducir de la sintaxis de ensamblador de VC++ a la de gcc? Esto sería lo que habría que reescribir:
Código:
ASM {
xor eax, eax
mov ax, word ptr ss:Value
mov edx, ss:xDomain
mul edx // val3 = p -> Domain * Value;
shld edx, eax, 16 // Convert it to fixed 15.16
shl eax, 16 // * 65536 / 65535
mov ebx, 0x0000ffff
div ebx
mov ecx, eax
sar ecx, 16 // ecx = cell0
mov edx, eax // rest = (val2 & 0xFFFFU)
and edx, 0x0000ffff // edx = rest
mov ebx, ss:LutTable
lea eax, dword ptr [ebx+2*ecx] // Ptr to LUT
xor ebx, ebx
mov bx, word ptr [eax] // EBX = y0
movzx eax, word ptr [eax+2] // EAX = y1
sub eax, ebx // EAX = y1-y0
js IsNegative
mul edx // EAX = EAX * rest
shld edx, eax, 16 // Pass it to fixed
sal eax, 16 // * 65536 / 65535
mov ecx, 0x0000ffff
div ecx
add eax, 0x8000 // Rounding
sar eax, 16
add eax, ebx // Done!
}
RET((WORD) _EAX);
IsNegative:
ASM {
neg eax
mul edx // EAX = EAX * rest
shld edx, eax, 16 // Pass it to fixed
sal eax, 16 // * 65536 / 65535
mov ecx, 0x0000ffff
div ecx
sub eax, 0x8000
neg eax
sar eax, 16
add eax, ebx // Done!
}
RET((WORD) _EAX);
}
Es que el formato de ensamblador de gcc es un peñazo. Un enlace por si alguien se anima. Al final acabaré perdiendo una tarde que me aburra mucho.
Otra opción sería compilar el .c que tiene las funciones en asm con VC++ y enlazarlo. Lo he intentado pero no lo he conseguido. Finalmente no he conseguido llamar a la DLL ya compilada que se puede descargar de la página web desde C, lo que sería otro posibilidad de ir más rápido.
Por tanto, yo apuesto por dos buffers.
Fernando, toma nota: lo que sí que vamos a probar es a cambiar la conversión de 16 a 8 bits que usamos, out=(PX8)(in>>8), por ésta otra que usa LCMS y que debe ser más precisa (que no más rápida):
Código:
#define RGB_16_TO_8(rgb) (PX8) ((((rgb) * 65281 + 8388608) >> 24) & 0xFF)
Un saludo:
Marcadores