Promoción de Delphi 10.4, últimos 3 días

Imagen
Disfrute de un desarrollo de Windows sin igual con Rad Studio 10.4

Mejoras significativas de Windows. Entrega aplicaciones visualmente deslumbrantes con elementos de IU con alto DPI de gran nitidez en monitores 4K y una nueva y versátil compatibilidad con estilos para los controles visuales. Integra tecnologías web modernas y seguras a través del nuevo WebView2 de Microsoft basado en Chromium. Crea barras de título modernas y mejoradas similares a las de Office, Explorer, Google Chrome y otros. Significativas mejoras de estabilidad, con un nuevo depurador para Windows 64 bits C++.

Mayor productividad. Incrementa la productividad con rápido completamiento de código en el IDE. Mejor compatibilidad con el código existente y codificación más sencilla a través de la administración de memoria unificada. Vincula datos rápidamente con la arquitectura optimizada y el rendimiento mejorado de Visual LiveBindings. Accede fácilmente a bibliotecas populares de C++ como ZeroMQ, SDL2, SOCI, libSIMDpp y Nematode. Más amplia compatibilidad con la nube de Amazon AWS.

Mejoras de rendimiento y calidad. Más de 1000 mejoras de calidad y rendimiento. Logra una mejor eficiencia del código a través de los nuevos registros de administración personalizada. Ejecuta el código más rápido con las tareas paralelas mejoradas en procesadores multinúcleo modernos. Experimenta un mejor rendimiento del renderizado en pantalla para macOS e iOS y compatibilidad con la API de Metal. Mayor compatibilidad con el código existente y codificación más sencilla a través de la administración de memoria unificada.

!Embarcadero está llevando a cabo un ENORME esfuerzo en la promoción de la versión 10.4! ¡ Póngase en contacto con su representante de ventas o socios para obtener más información!
Aproveche estos últimos 3 días 
para tener un gran descuento





Efectos con Scanline


 How to use ScanLine property for 24-bit bitmaps? - Stack Overflow

Tbitmap.scanline es una propiedad indexada de solo lectura que devuelve un puntero a una fila de pixeles de un bitmap.
Es la forma más rápida de acceder a los píxeles de una imagen aunque depende del formato de mapa de bits que se establezca desde la propiedad Pixelformat de la unit Graphics.

TPixelFormat = (pfDevice, pf1bit, pf4bit, pf8bit, pf15bit, pf16bit, pf24bit, pf32bit, pfCustom);

Ejemplo de carga un bitmap:

VAR
  bmp: tbitmap;
BEGIN
  bmp := tbitmap.Create;
  TRY
    IF OpenDialog1.Execute THEN
    BEGIN
      bmp.LoadFromFile(OpenDialog1.FileName);
      bmp.PixelFormat := pf24bit;
      Invalidate; { Mostrar la imagen }
    END;
  FINALLY
    bmp.Free;
  END;
END;
 

Cuando creamos un mapa de bits cada pixel se inicializa al máximo valor, es decir a 255 por eso el mapa de bits es blanco, ese el formato de pixel predeterminado.
Un pixel en un mapa de bits de 24 bits se describe con 3 valores rojo, verde y azul, que se almacenan en la memoria en orden inverso: azul, verde y rojo.
El puntero a la matriz de bytes que hace scanline se vería de la siguiente forma:
 




Para obtener el resultado anterior hay que asignar el resultado de Scanline a un puntero de bytes: pByteArray

  VAR
    p: PByteArray;
  BEGIN
    p := FImage.ScanLine[0];
  END;

Por ejemplo para poner el primer pixel de la primera fila de la imagen de color negro y el segundo de color blanco habría que hacer:


VAR
  p: PByteArray;
BEGIN
  p := FImage.ScanLine[0]; { lee la primera fila }
  p[0] := 0; { primer pixel de color negro }
  p[1] := 0;
  p[2] := 0;
  p[3] := 255; { segundo pixel de color blanco }
  p[4] := 255;
  p[5] := 255;
  Invalidate;
END;


También podemos usar la siguiente estructura:


 type
  TRGBTriple = packed record
    rgbtBlue: Byte;
    rgbtGreen: Byte;
    rgbtRed: Byte;
  end;

Para conseguir que la segunda fila del bitmap sea de color negro:

type
  PRGBTripleArray = ^TRGBTripleArray;
  TRGBTripleArray = array[0..4095] of TRGBTriple;

procedure TForm1.Button1Click(Sender: TObject);
var
  I: Integer;
  Bitmap: TBitmap;
  Pixels: PRGBTripleArray;
begin
  Bitmap := TBitmap.Create;
  try
    Bitmap.Width := 3;
    Bitmap.Height := 2;
    Bitmap.PixelFormat := pf24bit;
    // get pointer to the second row's raw data
    Pixels := Bitmap.ScanLine[1];
    // iterate our row pixel data array in a whole width
    for I := 0 to Bitmap.Width - 1 do
    begin
      Pixels[I].rgbtBlue := 0;
      Pixels[I].rgbtGreen := 0;
      Pixels[I].rgbtRed := 0;
    end;
    Bitmap.SaveToFile('c:\Image.bmp');
  finally
    Bitmap.Free;
  end;
end;
 

De lo anterior podemos observar que el primer pixel del bitmap se encuentra en el offset 0 de la primera fila, el segundo en el offset 3, el tercero en el offset 6 esto quiere decir que el byte en la ubicación x*3 es el componente azul, el byte de la ubicación x*3+1 es el componente verde y el x*3+2 es el rojo.
Entonces si quisiéramos poner una imagen en color negro habría que hacer lo siguiente:

VAR
  p: PByteArray;
  x: Integer;
  y: Integer;
BEGIN { Iterar entre todas las líneas}
  FOR y := 0 TO Pred(FImage.Height) DO
  BEGIN
    p := FImage.ScanLine[y];
    FOR x := 0 TO Pred(FImage.Width) DO
    BEGIN
      p[x * 3] := 0;
      p[x * 3 + 1] := 0;
      p[x * 3 + 2] := 0;
    END;
 END;
END;
 

Ahora vamos a profundizar un poco más en este aspecto, hemos visto que cambiando los valores de los bytes de un pixel podemos conseguir los diferentes tipos de colores y si vamos un poco más allá conseguiremos espectaculares efectos visuales como los siguientes:

- Solarize

VAR
  p: PByteArray;
  x: Integer;
  y: Integer;
BEGIN
  FOR y := 0 TO Pred(FImage.Height) DO
  BEGIN
    p := FImage.ScanLine[y];
    FOR x := 0 TO Pred(FImage.Width) DO
    BEGIN
      IF p[x * 3] > 127 THEN
        p[x * 3] := 255 - p[x * 3];
      IF p[x * 3 + 1] > 127 THEN
        p[x * 3 + 1] := 255 - p[x * 3 + 1];
      IF p[x * 3 + 2] > 127 THEN
        p[x * 3 + 2] := 255 - p[x * 3 + 2];
    END;
  END;
END;


- Invertir colores
 
VAR
  p: PByteArray;
  x: Integer;
  y: Integer;
BEGIN
  FOR y := 0 TO Pred(FImage.Height) DO
  BEGIN { get the pointer to the y line }
    p := FImage.ScanLine[y];
    FOR x := 0 TO Pred(FImage.Width) DO
    BEGIN { modificar el color azul }
      p[x * 3] := 255 - p[x * 3]; { modificar el color verde  }
      p[x * 3 + 1] := 255 - p[x * 3 + 1]; { modificar el color rojo  }
      p[x * 3 + 2] := 255 - p[x * 3 + 2];
    END;
  END;
END;


- Convertir a escala de grises

 Se hace con la siguiente fórmula
Gray = (Red * 3 + Blue * 4 + Green * 2) div 9

VAR
  p: PMyPixelArray;
  x: Integer;
  y: Integer;
  gray: Integer;
BEGIN
  FOR y := 0 TO Pred(FImage.Height) DO
  BEGIN
    p := FImage.ScanLine[y];
    FOR x := 0 TO Pred(FImage.Width) DO
      WITH p[x] DO
      BEGIN
        gray := (Red * 3 + Blue * 4 + Green * 2) DIV 9;
        Blue := gray;
        Red := gray;
        Green := gray;
      END;
  END;
END;



- Hacer un espejo vertical

  procedure TForm1.Button1Click(Sender: TObject);

   procedure EspejoVertical(Origen,Destino:TBitmap);
   var
      x,y          : integer;
      Alto         : integer;
      Po,Pd        : PByteArray;
      tmpBMP       : TBitmap;
      LongScan     : integer;
   begin
     {Si es un modo raro... pasamos}
     case Origen.PixelFormat of
       pfDevice,
       pfCustom:
         Raise exception.create( 'Formato no soportado'+#13+
                                 'Bitmap Format not valid');
     end;

     {Calculamos variables intermedias}
     Alto :=Image1.Picture.Bitmap.Height-1;
     try
       {Calculo de cuánto ocupa un scan}
       LongScan:= Abs( Integer(Origen.ScanLine[0])-
                       Integer(Origen.ScanLine[1]) );
     except
       Raise exception.create( 'ScanLine Error...');
     end;

     {Cremos un bitmap intermedio}
     tmpBMP:=TBitmap.Create;
     with tmpBMP do
     begin
       {Lo asignamos, así se copia la paleta si la hay}
       Assign(Origen);
       {Esto es para que sea un bitmap nuevo... es un bug de D3 y D4}
       Canvas.Pixels[0,0]:=Origen.Canvas.Pixels[0,0];
     end;

     {Damos la vuelta al bitmap}
     for y:=0 to Alto do
     begin
       Po := Origen.ScanLine[y];
       Pd := tmpBMP.ScanLine[Alto-y];
       for x := 0 to LongScan-1 do
       begin
           Pd^[X]:=Po^[X];
       end;
     end;
     {Lo asignamos al bitmap destino}
     Destino.Assign(tmpBMP);
     {Esto es para parchear un bug de Delphi 3 y Delphi4...}
     Destino.Canvas.Pixels[0,0]:=tmpBMP.Canvas.Pixels[0,0];
     tmpBMP.Free;
   end;
 begin
   EspejoVertical( Image1.Picture.Bitmap,
                   Image1.Picture.Bitmap);
   Image1.Refresh;
 end;



- Ajustar el brillo  

 Se hace con la siguiente fórmula:
NewPixel = OldPixel + (1 * Percent) div 200


FUNCTION IntToByte(AInteger: Integer): Byte; INLINE;
BEGIN
  IF AInteger > 255 THEN
    Result := 255
  ELSE IF AInteger < 0 THEN
    Result := 0
  ELSE
    Result := AInteger;
END;

PROCEDURE TMainForm.AdjustBrightness(Percent: Integer);
VAR
  p: PMyPixelArray;
  x: Integer;
  y: Integer;
  amount: Integer;
BEGIN
  amount := (255 * Percent) DIV 200;
  FOR y := 0 TO Pred(FImage.Height) DO
  BEGIN
    p := FImage.ScanLine[y];
    FOR x := 0 TO Pred(FImage.Width) DO
      WITH p[x] DO
      BEGIN
        Blue := IntToByte(Blue + amount);
        Green := IntToByte(Green + amount);
        Red := IntToByte(Red + amount);
      END;
  END;
  Invalidate;
END;

PROCEDURE TMainForm.ScanLineBrightnessClick(Sender: TObject);
VAR
  amount: Integer;
BEGIN
  amount := StrToInt(InputBox('Brightness Level', 'Enter a value from -100 to 100:', '50'));
  AdjustBrightness(amount);
END;

Nueva versión de la app GPS TOTAL RUN



 

Ya pueden descargar la nueva versión de la app gratuita y sin publicidad GPS TOTAL RUN (Android).
Para los que aún no la conozcan es una app que he programado con RAD Studio 10.3.3 que sirve para grabar las rutas que realizamos cuando hacemos deporte, vamos en bici, hacemos un viaje,etc.
Permite utilizar dispositivos Bluetooth LE, para obtener las pulsaciones por minuto, o la cadencia de pedaleo cuando hacemos rutas en bicicleta.
Se pueden hacer estadísticas por dias, semanas, meses y también hace cálculo de tiempos por tramos en 27 actividades distintas.

Tiene más de 30 utilidades:
Actualiza datos AGPS, información de 15 parámetros del GPS, cálculo de UTM, brújula, hora en la que amanece, anochece en un calendario perpetuo, altímetro, mapas del Instituto Geográfico Nacional de España, creación de puntos de interés, mapas offline, información de los sensores del dispositivo, etc...

En la última versión incorporo varias novedades:

- Permite compartir la ruta en tiempo real a tus contactos, por email, por whastapp, etc...
lo que te da seguridad en caso de que ocurra algún problema.

- Se puede enviar la ruta en formato kml, para que se pueda abrir desde Google Earth directamente.

- Cientos de rutas realizadas en varios países (Brasil, Argentina, Chile, México, Perú, Colombia, Francia, Italia, Portugal, etc...) con mapas interactivos de openstreetmap y opentopomap.

- Permite medir distancias y calcular áreas sobre mapas.

- Se mejora el módulo que calcula el sobrepeso, mostrando cuántos kilos nos sobran para llegar a un peso normal.

- Medida del riesgo cardiovascular: indica el tanto por ciento de posibilidades de sufrir un accidente cardio-vascular, en función de varios parámetros (sexo, edad, diabetes, presión arterial, etc...).

 


Si les gusta la app y creen que puede ser de utilidad les agradecería que la difundan en sus redes sociales.

Pantallas de la app: