Generic YUV conversion (Delphi 4.0)

Note:

At the beginning of the Unit1 file, add LTDLLUNT, LTDLLTYP, and LTDLLDEF to the uses section.

Generic YUV conversion provides the ability to convert any YUV format to any supported color space, using the YUV_PARAMS structure and adhering to the restrictions listed below. After defining the YUV format, you can proceed with the conversion normally, just like any other conversion. Use L_ClrConvert to perform the conversion and call L_ClrFree to free the conversion handle. Currently the conversion from any color space to Generic YUV is not supported.

Generic YUV conversion currently has the following restrictions:

1.

No sub-sampling of Y is supported

2.

The number of Y elements must be a multiple of both U, and V.

3.

With non-planar formats, vertical sub-sampling of Y, U, and V is not supported.

4.

No alignment supported in planar format; line width must not contain additional bytes.

5.

The horizontal sub-sampling periods of U, and V must be multiples of each other, and the vertical sub-sampling periods of U, and V must be multiples of each other.

Examples:

1.

Converting Y41P to RGB using Generic YUV Conversion:

procedure GenericY41PToRGB({in}pIn: Pointer; {out}pOut: Pointer; {in}nWidth: Integer; {in}nHeight: Integer);
var
   hClrHandle : THandle (* Color Handle *);
   cpParams : CONVERSION_PARAMS (* Conversion options *);
   yuvParams : YUV_PARAMS (* Declare YUV Params structure *);
   pOff: array[0..11] of Integer (* Byte ordering of the YUV format *);
begin

   (*
    * Byte ordering of the format; for Y41P:
    * U0 Y0 V0 Y1 U4 Y2 V4 Y3 Y4 Y5 Y6 Y7
    * 0    1    2    3    4    5    6    7    8   9    10  11
    * Put the Y component order first then the U and V last as follows:
    * Y positions: 1,3,5,7,8,9,10,11
    * U positions: 0,4
    * V positions: 2,6
    *)

   pOff[0]  := 1;
   pOff[1]  := 3;
   pOff[2]  := 5;
   pOff[3]  := 7;
   pOff[4]  := 8;
   pOff[5]  := 9;
   pOff[6]  := 10;
   pOff[7]  := 11;
   pOff[8]  := 0;
   pOff[9]  := 4;
   pOff[10] := 2;
   pOff[11] := 6;

   ZeroMemory (@cpParams, sizeof (CONVERSION_PARAMS));
   (* Determine the size of the structure *)
   yuvParams.uStructSize := sizeof(YUV_PARAMS);
   (* Determine the horizontal sub-sampling of U *)
   yuvParams.nUh := 4;
   (* Determine the vertical sub-sampling of U *)
   yuvParams.nUv := 1;
   (* Determine the horizontal sub-sampling of V *)
   yuvParams.nVh := 4;
   (* Determine the vertical sub-sampling of V */
   yuvParams.nVv = 1;
   (* Set the byte ordering *)
   yuvParams.pOffsets := @pOff;
   (* The YUV values range *)
   yuvParams.nRange := YUVRANGE_FULL;
   (*
    * This represents the macro pixels(smallest group of pixels allowed) , which indicates
    * how many actual pixels are in the macro pixel, this value is important only in non –
    * planar format
    *)

   yuvParams.nMacroPixel := 8;
  (*
    * This is a Boolean value that represents the type of the YUV format (Planar = TRUE,
    * or non – Planar = FALSE.)
    *)
   yuvParams.bPlanar := 0; (* Flase *)

   (* Fill the pYuvParams value with the address of the YUV_PARAMS structure *)
   cpParams.pYuvParams := @yuvParams;
   (* Determine the size of CONVERSION_PARAMS *)
   cpParams.uStructSize := SizeOf (CONVERSION_PARAMS);
   (*
    * Determine the type of conversion to be used in the conversion, for YUVGeneric, only use
    * USE_BUILTIN
    *)
   cpParams.nMethod := USE_BUILTIN;
   (*
    * Determine the type of conversion to be activated. For YUVGeneric,
    * only USE_BUILTIN
    *)
   cpParams.nActiveMethod := USE_BUILTIN;

   (* Initialize the conversion *)
   L_ClrInit(@hClrHandle, CCS_YUV, CCS_RGB, @cpParams);

   (* Convert the buffers pIn to pOut *)
   L_ClrConvert (hClrHandle, pIn, pOut, nWidth, nHeight, 0, 0);

   (* Free the handles *)
   L_ClrFree (hClrHandle);
end;

2.

Converting YVU9 (Planar) to RGB using Generic YUV Conversion:

procedure GenericYVU9ToRGB({in}pIn: Pointer; {out}pOut: Pointer; {in}nWidth: Integer; {in}nHeight: Integer);
var
   hClrHandle : THandle (* Color Handle *);
   cpParams : CONVERSION_PARAMS (* Conversion options *);
   yuvParams : YUV_PARAMS (* Declare YUV Params structure *);
   pOff: array[0..0] of Integer    (* Byte ordering of the YUV format *);
begin

   (*
    * This array of integers specifies the byte order of the yuv format. For planar
    * formats it takes only a single value that represents planes sequence in the buffer:
    * YUV, YVU, UYV, UVY, VYU, or VUY.
    *)
   pOff[0] := PLANAR_YVU; (*
                           * PLANAR_YVU means the Y plane comes first in
                           * the buffer, then the V plane, and the U plane is last
                           *)

   ZeroMemory (@cpParams, SizeOf (CONVERSION_PARAMS));

   (* Determine the size of the structure *)
   yuvParams.uStructSize := SizeOf(YUV_PARAMS);

   (* Determine the horizontal sub-sampling of U *)
   yuvParams.nUh := 4;

   (* Determine the vertical sub-sampling of U *)
   yuvParams.nUv := 4;

   (* Determine the horizontal sub-sampling of V *)
   yuvParams.nVh := 4;

   (* Determine the vertical sub-sampling of V *)
   yuvParams.nVv := 4;

   (* This is a pointer to an integer. Pass the byte ordering array *)
   yuvParams.pOffsets := @pOff;

   (* The range value determines the YUV range values *)
   yuvParams.nRange := YUVRANGE_FULL;

   (*
    * This represents the macro pixels(smallest group of pixels allowed) , which indicates
    * how many actual pixels are in the macro pixel. This value is important only in non – p
    * planar format
    *)
   yuvParams.nMacroPixel := 16;

   (*
    * This is a Boolean value that represents the type of the YUV format (Planar, or non
    * - Planar.)
    *)
   yuvParams.bPlanar := 1; (* True *)

   (*
    * Pass the YUV_PARAMS structure address to the pYuvParams member of the
    * CONVERSION_PARAMS structure
    *)
   cpParams.pYuvParams := @yuvParams;

   (* Determine the size of the CONVERSION_PARAMS structure*)
   cpParams.uStructSize := SizeOf (CONVERSION_PARAMS);

   (*
    * Determine the type of conversion to be used. For YUVGeneric, use
    * only USE_BUILTIN
    *)
   cpParams.nMethod := USE_BUILTIN;

   (*
    * Determine the type of conversion to be activated. For
    * YUVGeneric, use only USE_BUILTIN
    *)
   cpParams.nActiveMethod := USE_BUILTIN;

   (* Initialize the conversion *)
   L_ClrInit(@hClrHandle, CCS_YUV, CCS_RGB, @cpParams);

   (* Convert the buffers pIn to pOut *)
   L_ClrConvert (hClrHandle, pIn, pOut, nWidth, nHeight, 0, 0);

   (* Free the handles *)
   L_ClrFree (hClrHandle);
end;

;