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;
;