PDA

Visualizza versione completa : [C/C++] [ALGORITMI]


yag[YOG]
23-01-2007, 12.38.54
salve
vorrei scrivere un programmino che converta il
formato 4:2:0 planare in RGB24

Mi sono documentato ed ho letto parecchi articoli in
rete conosco il c ed il c++
ho visto parecchio codice in rete
Però c'è qualcosa che mi sfugge

Una cosa che non mi è chiarissima è
come è fatta la struttura binaria del file
questo credo sia essenziale
dalle varie letture mi sembra di capire che
prima sono presenti tutti gli
Y poi u e poi v

però non riesco a capire come accedervi tramite codice

grazie
a tutti
ciao

P8257 WebMaster
23-01-2007, 13.02.42
Dovrebbe risolversi semplicemente con un cast a DWORD (ti consiglio di dichiarare un tipo dword24)..


DWORD rgb24;
BYTE r,g,b;
DWORD rgb555;


b=rgb555 & 0x1f; // extract blue
rgb555 >>= 5;
g=rgb555 & 0x1f; // green
rgb555 >>= 5;
r=rgb555 & 0x1f; // and red


rgb24=r; rgb24 <<=8;
rgb24|=g; rgb24 <<=8;
rgb24|=b;



Codice trovato su internet

L'implementazione parta da un RGB standard, volendo la puoi usare così com'é convertendo il formato planare in esadecimale prima di procedere.

yag[YOG]
23-01-2007, 13.08.18
rgb555 lo carico tramite per fread ma perchè di >> di 5 ?

MI puoi passare il link ? (rimani in onda se puoi così vediamo se risco a risolvere /capire )

grazie

ok ho trocato il link:
http://groups.google.it/group/comp.graphics.algorithms/browse_thread/thread/989001630034e1aa/73153130892ad009?lnk=st&q=b%3Drgb555+%26+0x1f%3B+%2F%2F+extract+blue+&rnum=1&hl=it#73153130892ad009

ma questo "fa" da RGB555->RGB24
come dice il topi c
io devo fare da
yuv 4:2:0 planare a RGB24

P8257 WebMaster
23-01-2007, 13.14.12
Si ma vai per gradi,
planare -> rgb555 - rgb24...

P8257 WebMaster
23-01-2007, 13.17.35
E' relativamente semplice arrivare al formato 555, si tratta anche qui di un cast (questi formati sono tutti dei cast), in questo caso vanno troncati gli ultimi bit...

http://groups.google.it/group/comp.os.ms-windows.programmer.win32/browse_thread/thread/b4ac98906e0edf53/c1e9b286c0d5a915?lnk=st&q=rgb555&rnum=6&hl=it#c1e9b286c0d5a915

yag[YOG]
23-01-2007, 14.03.42
E ok fin qui ci sono ... Ma poi ...
Io non riesco a materializzare la struttura fisica di sto file ,
Tipo una volta ho scritto un reader per file 3ds però era più chiaro
avevo stuttura dimensione delle stesse etc.
In questo caso mi "vedo" perso ...

P8257 WebMaster
23-01-2007, 14.31.02
Non mi sono mai occupato di questo genere di letture, ciò che ricordo è il modello matematico, vedi se questo può esserti utile

http://homepages.borland.com/efg2lab/Graphics/Colors/YUV.htm

yag[YOG]
23-01-2007, 14.34.24
Si già visitato... (mi sa che ho visto tutto in rete è per quello che sono finito qui)
Per dire già
da qui:
http://www.comlab.uniroma3.it/ens/ENS_MPEG.pdf
Alla decima pagina non riesco a capire bene i vari schemi
il primo è ovvio 4:4:4 ma già nell'altro mi perdo...

yag[YOG]
23-01-2007, 14.51.54
']Si già visitato... (mi sa che ho visto tutto in rete è per quello che sono finito qui)
Per dire già
da qui:
http://www.comlab.uniroma3.it/ens/ENS_MPEG.pdf
Alla decima pagina non riesco a capire bene i vari schemi
il primo è ovvio 4:4:4 ma già nell'altro mi perdo...

Sto incominciando a capire:
il formato che usa in questo file è
YVU
[codice pascal]

FilePointer := 0;
StreamY.Seek(FilePointer, soFromBeginning);
//ok la y è all'inizio

FilePointer := YRowCount * YColumnCount;
StreamV.Seek(FilePointer, soFromBeginning);
//ok la v sta dopo la y alla fine quindi mi sposta
//allla prima V


FilePointer := FilePointer + (YRowCount DIV Factor) *
(YColumnCount DIV Factor);
StreamU.Seek(FilePointer, soFromBeginning);

//qua mi sono perso .... in pratica
//vado nella posizione uguale a numero righe
//diviso 4 * numero colonne / 4 non
//capisco dove sto andando a finire...
[/pascal]

P8257 WebMaster
23-01-2007, 14.57.13
Secondo me vai a finire al primo V del GOP

yag[YOG]
23-01-2007, 15.08.54
Secondo me vai a finire al primo V del GOP
Ok questo a livello logico ...
Group oF Picture giusto ?
(che non ho capito neanche bene)

Cmq ho fatto un pò di conti
immaginando di avere una img 8x8
e di "vederla" come sequenza di byte (o celle)
otteniamo che:
la y sta alla cella 0
la v sta alla cella 64 = (8x8)
la u sta alla cella 64 + 16 = ( (8/4)*(8/4))

non capisco perchè la u la calcola così...
p.s
hai visto le slide ?

P8257 WebMaster
23-01-2007, 15.23.38
Penso che il tuo modello sia giusto, ho visto purtroppo solo brevemente le slide dagli schemi e se la memoria non mi inganna tutto si gioca su un discorso di interpolazione, ovvero prima cella indica la presenza del pixel, seconda cella indica il gradiente del pixel orizzontale, terza cella indica il gradiente verticale...

Per evitare di sparare cavolate però mi riservo di guardarci meglio.

yag[YOG]
24-01-2007, 16.14.04
Dunque io ho capito l'algoritmo credo...
Ora non riesco a capire come caricare dal file yuv
le dimensioni width ed height dovrevi (generalmente è così)
caricarle dall'header ma non so dove è...

P8257 WebMaster
24-01-2007, 16.40.10
Prova a postare quello che hai messo giù

yag[YOG]
24-01-2007, 16.48.30
Prova a postare quello che hai messo giù
In definitiva sono riuscito a capire questo listato anche se è in pascal ed io lo voglio fare in c


unit ScreenYVUtoRGBDemo;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls;

type
TFormYVUtoRGB = class(TForm)
ImageRGB: TImage;
RadioGroupYVURGB: TRadioGroup;
RadioGroup129: TRadioGroup;
procedure FormCreate(Sender: TObject);
procedure RadioGroupClick(Sender: TObject);
private
PROCEDURE UpdateYUV;
public
{ Public declarations }
end;

var
FormYVUtoRGB: TFormYVUtoRGB;

implementation
{$R *.DFM}

CONST
MaxPixelCount = 32768; // Arbitrary large constant for any bitmap

TYPE
TRGBTripleArray = ARRAY[0..MaxPixelCount-1] OF TRGBTriple;
pRGBTripleArray = ^TRGBTripleArray;

// Convert YVU to RGB.

// For YVU12, the "Y" plane is twice as large as the
// "U" and "V" planes in both dimensions -- so the "Y" plane
// has four times as many bytes as the "U" and "V" planes.
//
// For YVU9, the "Y" plane is four times as large as the
// "U" and "V" planes in both dimensions -- so the "Y" plane
// has 16-times as many bytes as the "U" and "V" planes.
//
// Many values are "hardwired" here to process only the sample file

PROCEDURE TFormYVUtoRGB.UpdateYUV;
CONST
YRowCount = 288;
YColumnCount = 352;
UV12ColumnCount = YColumnCount DIV 2;

VAR
Bitmap : TBitmap;

BufferY : ARRAY[0..YColumnCount-1] OF BYTE;
BufferU : ARRAY[0..UV12ColumnCount-1] OF BYTE;
BufferV : ARRAY[0..UV12ColumnCount-1] OF BYTE;

DisplayIndex: INTEGER;

Factor : INTEGER; // 2 for YVU12, 4 for YVU9
Filename : STRING;
FilePointer : INTEGER;
i : INTEGER;
InFile : STRING; // 'YVU12.Stream' or 'YVU9.Stream'

j : INTEGER;
OutFile : STRING; // 'WeatherLady' or 'NewsGuy'
Row : pRGBTripleArray;

StreamY : TFileStream;
StreamU : TFileStream;
StreamV : TFileStream;

Y : BYTE;
U : BYTE;
V : BYTE;

// R, G and B values must be in the range 0..255
FUNCTION FixRange(CONST x: Double): BYTE;
VAR
temp: INTEGER;
BEGIN
temp := ROUND(x);
IF temp > 255
THEN temp := 255
ELSE
IF temp < 0
THEN temp := 0;

RESULT := temp
END;

BEGIN
U := 0; // avoid compiler warning
V := 0; // avoid compiler warning

CASE RadioGroup129.ItemIndex OF
// YVU12
0: BEGIN
Factor := 2;
InFile := 'YVU12.Stream';
OutFile := 'WeatherLady.BMP';
END;

// YVU9
1: BEGIN
Factor := 4;
InFile := 'YVU9.Stream';
OutFile := 'NewsGuy.BMP'
END;

ELSE
Factor := 0; // avoid compiler warnings
Filename := '';
OutFile := ''
END;

// YVU order here.
StreamY := TFileStream.Create(InFile, fmOpenRead + fmShareDenyNone);
StreamV := TFileStream.Create(InFile, fmOpenRead + fmShareDenyNone);
StreamU := TFileStream.Create(InFile, fmOpenRead + fmShareDenyNone);


TRY
// Read same file as three different streams. YVU order.
FilePointer := 0;
StreamY.Seek(FilePointer, soFromBeginning);

FilePointer := YRowCount * YColumnCount;
StreamV.Seek(FilePointer, soFromBeginning);

FilePointer := FilePointer + (YRowCount DIV Factor) *
(YColumnCount DIV Factor);
StreamU.Seek(FilePointer, soFromBeginning);


DisplayIndex := RadioGroupYVURGB.ItemIndex;

Bitmap := TBitmap.Create;
TRY
Bitmap.Width := YColumnCount;
Bitmap.Height := YRowCount;
Bitmap.PixelFormat := pf24Bit;

FOR j := 0 TO YRowCount-1 DO
BEGIN

// Read each "row" of data
StreamY.Read(BufferY, YColumnCount {bytes});

// YUV12: Read U and V "row" of data on even-numbered rows
// Re-use the same row of data for the odd-numbered rows
//
// YUV9: Read new row every fourth output row. Re-use
// the same row for the other rows.
IF j MOD Factor = 0
THEN BEGIN
StreamU.Read(BufferU, YColumnCount DIV Factor {bytes});
StreamV.Read(BufferV, YColumnCount DIV Factor {bytes});
END;

Row := Bitmap.Scanline[j];
FOR i := 0 TO YColumnCount-1 DO
BEGIN
Y := BufferY[i];
IF i MOD Factor = 0
THEN BEGIN
U := BufferU[i DIV Factor];
V := BufferV[i DIV Factor]
END;

WITH Row[i] DO
BEGIN
CASE DisplayIndex OF
// Y plane
0: BEGIN
rgbtBlue := Y;
rgbtGreen := Y;
rgbtRed := Y
END;

// U plane
1: BEGIN
rgbtBlue := U;
rgbtGreen := U;
rgbtRed := U
END;

// V plane
2: BEGIN
rgbtBlue := V;
rgbtGreen := V;
rgbtRed := V
END;

// YUV to RGB Conversion
// see www.webartz.com/fourcc/fccyvrgb.htm
// It's unclear whether U and V are switched, or whether
// the formula from this web site is correct with
// U = Cb and V = Cr
3: BEGIN
rgbtBlue := FixRange( 1.164*(Y - 16) + 2.018*(U-128) );
rgbtGreen := FixRange( 1.164*(Y - 16) - 0.813*(U-128)
- 0.391*(V-128) );
rgbtRed := FixRange( 1.164*(Y - 16) + 1.596*(V-128) );
END;
END;
END
END
END;

Bitmap.SaveToFile(OutFile);
ImageRGB.Picture.Graphic := Bitmap
FINALLY
Bitmap.Free
END
FINALLY
StreamY.Free;
StreamU.Free;
StreamV.Free
END;

// Change size of TImage to reflect (but fake) size of real data
CASE DisplayIndex OF
// Y plane or RGB
0,3: BEGIN
ImageRGB.Width := YColumnCount;
ImageRGB.Height := YRowCount;
ImageRGB.Stretch := FALSE
END;

// U or V planes
1,2: BEGIN
ImageRGB.Width := YColumnCount DIV Factor;
ImageRGB.Height := YRowCount DIV Factor;
ImageRGB.Stretch := TRUE
END;

END;

END {UpdateYUV};


procedure TFormYVUtoRGB.FormCreate(Sender: TObject);
begin
UpdateYUV;
end;

procedure TFormYVUtoRGB.RadioGroupClick(Sender: TObject);
begin
UpdateYUV
end;

end.

Questo è delphi ma è banale
ti posto anche dei link assolutamente utili:

http://msdn2.microsoft.com/en-us/library/ms867704.aspx
http://www.reference.com/search?q=YUV
che mi hanno permesso di capire un pò cose.

ora mi manca capire come dicevo prima recupere le info sul file.

LoryOne
24-01-2007, 18.00.14
Ti rubo solo un secondo: Le info sul file non le hai direttamente nel codice Delphi che hai postato ?

yag[YOG]
24-01-2007, 18.02.17
Anche più di uno...
Le info che mi servono nel codice delphi che ho postato (non mio ma preso in rete perchè a me interessa capire l'algoritmo )
sono cablate direttamente nel codice ad esempio le
dimensioni...

P8257 WebMaster
25-01-2007, 11.52.15
Allora, ho avuto un po' di tempo per guardare l'algoritmo, come dicevi tu, è piuttosto banale, anzi, più che banale è lineare, non mi sembra ci sia molto da spiegare, per quanto riguarda le dimensioni e gli altri valori cablati, secondo me li puoi recuperare senza fatica dalle dimensioni in byte del file stesso..

Per esempio sai che il segmento Y ha 64 byte e da questo calcoli il numero di segmenti Y, il V ne ha 16 e così calcoli il numero di V.. e così via ..

Costruisci una matrice (Y-V) e da questa matrice calcoli il columncount, il rowcount lo calcoli in base ad U o direttamente contando le righe della matrice...

Spero di non aver sparato cazzate codificate ma a me il discorso fila

yag[YOG]
30-01-2007, 14.18.53
Allora, ho avuto un po' di tempo per guardare l'algoritmo, come dicevi tu, è piuttosto banale, anzi, più che banale è lineare, non mi sembra ci sia molto da spiegare, per quanto riguarda le dimensioni e gli altri valori cablati, secondo me li puoi recuperare senza fatica dalle dimensioni in byte del file stesso..

Per esempio sai che il segmento Y ha 64 byte e da questo calcoli il numero di segmenti Y, il V ne ha 16 e così calcoli il numero di V.. e così via ..
[quote]
16 = 64/4 mmm una

[quote]
Costruisci una matrice (Y-V) e da questa matrice calcoli il columncount, il rowcount lo calcoli in base ad U o direttamente contando le righe della matrice...

Spero di non aver sparato cazzate codificate ma a me il discorso fila
Qua mi sono perso mi servirebbe un pò di codice...

P8257 WebMaster
30-01-2007, 21.58.21
Si, forse sono stato un po' confusionario, vedrò di scrivere qualcosa nei prossimi giorni...