конвертация I420 в RGB
От: temofey  
Дата: 14.05.04 08:45
Оценка:
Работал с камерой, от которой получал картинку — буффер и его длину. Проблема в том, что картинка с камеры
идет в формате i420..экономит канал...нодо конвертнуть i420 в RGB. Изучив информацию, которая приводится на www.fourcc.org
набросал код, который вроде бы должен работать...и он работает, но картинка частично "плывет". Возможно кто-нибудь уже сталкивался с такой проблемой..и если да — имеет кусок кода осуществляющего данное преобразование. В любом случае, привожу код, посмотрите — может у Вас получится увидеть ошибку, которую не вижу я.

Заранее благодарен.

struct TM_YUV
{
        TM_YUV(){ Y=0; U=0; V=0; };
        BYTE Y;
        BYTE U;
        BYTE V;
};
//---------------------------------------------------------------------------

struct TM_RGB24
{
        TM_RGB24(){ R=0; G=0; B=0; };
        BYTE R;
        BYTE G;
        BYTE B;
};
//---------------------------------------------------------------------------
пример набросан в среде борланд с++ билдер 6.0

void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{
  Graphics::TBitmap* bmp = new Graphics::TBitmap();

  bmp->Width  = 352;
  bmp->Height = 288;
  bmp->PixelFormat = pf24bit;

  vector<BYTE>     i420; // данные формата i420
  vector<TM_YUV>   yuv; // данные формата YUV
  vector<TM_RGB24> rgb; // данные RGB

// в файле "i420image.dat" содержатся данные одной картники формата i420

  TFileStream* fs = new TFileStream( ExtractFilePath(Application->ExeName) + "i420image.dat", fmOpenRead );

  i420.resize( fs->Size );
  fs->Read( i420.begin(), fs->Size );
  delete fs;

  yuv.resize(bmp->Width*bmp->Height);

// Переписали все компоненты яркости, в данном формате их по каждой на пиксел
  for( int i = 0; i < bmp->Width*bmp->Height; i++ )
  {
       yuv[i].Y = i420[i];
  }

  int Counter = 0;

// Теперь компоненты цветоразностей, они одинаковы в каждом макропикселе, который представляет собой квадрат размером 2х2 пиксела
  for( int  i = 0; i < bmp->Width*bmp->Height/4; i++ )
  {
       yuv[Counter].U                  =
       yuv[Counter + 1].U              =
       yuv[Counter + bmp->Width].U     =
       yuv[Counter + bmp->Width + 1].U = i420[bmp->Width*bmp->Height + i];

       yuv[Counter].V                  =
       yuv[Counter + 1].V              =
       yuv[Counter + bmp->Width].V     =
       yuv[Counter + bmp->Width + 1].V = i420[bmp->Width*bmp->Height + i + bmp->Width*bmp->Height/4];

       Counter += 2;
       if( Counter%bmp->Width == 0 )
           if( (Counter/bmp->Width)%2 != 0 )
                Counter += bmp->Width;
  }

// теперь конфертнем из YUV в RGB
  rgb.resize( bmp->Width*bmp->Height );
  for( int i = 0; i < rgb.size(); i++ )
  {
       rgb[i].B = 1.164*(yuv[i].Y - 16)                   + 2.018*(yuv[i].U - 128);
       rgb[i].G = 1.164*(yuv[i].Y - 16) - 0.813*(yuv[i].V - 128) - 0.391*(yuv[i].U - 128);
       rgb[i].R = 1.164*(yuv[i].Y - 16) + 1.596*(yuv[i].V - 128);
  }

// выведем на канву формы
  for( int y = 0; y < bmp->Height; y++ )
  {
      Byte* ptr = (Byte*)bmp->ScanLine[y];
      int c=0;
      for(int x = 0; x < bmp->Width; x++)
      {
          ptr[c]   = rgb[y*bmp->Width + x].B;
          ptr[c+1] = rgb[y*bmp->Width + x].G;
          ptr[c+2] = rgb[y*bmp->Width + x].R;
          c+=3;
      }
  }
  Canvas->Draw( 0, 0, bmp );
  delete bmp;
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.