sws_scale YUV -> RGB искаженное изображение - PullRequest
9 голосов
/ 13 декабря 2011

Я хочу преобразовать YUV420P изображение (полученное из H.264 stream) в RGB, а также изменить его размер, используя sws_scale.
Размер исходного изображения 480 × 800.Просто преобразование с одинаковыми размерами работает нормально.
Но когда я пытаюсь изменить размеры, я получаю искаженное изображение со следующей схемой:

  • , изменяющееся на 481 × 800, приведет к искаженному черно-беломуизображение, которое выглядит как вырезанное посередине
  • 482 × 800 будет еще более искажено
  • 483 × 800 искажено, но в цвете
  • 484 × 800 в порядке (масштабированоправильно).

Теперь этот шаблон следует - масштабирование будет работать нормально только в том случае, если разница между делится на 4.

Вот пример кода способа, которым я декодирую и преобразовываю изображение,Все методы показывают «успех».

int srcX = 480;
int srcY = 800;
int dstX = 481; // or 482, 483 etc
int dstY = 800;

AVFrame* avFrameYUV = avcodec_alloc_frame();
avpicture_fill((AVPicture *)avFrameYUV, decoded_yuv_frame, PIX_FMT_YUV420P, srcX , srcY);

AVFrame *avFrameRGB = avcodec_alloc_frame();

AVPacket avPacket;
av_init_packet(&avPacket);
avPacket.size = read; // size of raw data
avPacket.data = raw_data; // raw data before decoding to YUV

int frame_decoded = 0;
int decoded_length = avcodec_decode_video2(g_avCodecContext, avFrameYUV, &frame_decoded, &avPacket);
int size = dstX * dstY * 3;

struct SwsContext *img_convert_ctx = sws_getContext(srcX, srcY, SOURCE_FORMAT, dstX, dstY, PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);

avpicture_fill((AVPicture *)avFrameRGB, rgb_frame, PIX_FMT_RGB24, dstX, dstY);
sws_scale(img_convert_ctx, avFrameYUV->data, avFrameYUV->linesize, 0, srcY, avFrameRGB->data, avFrameRGB->linesize);

// draws the resulting frame with windows BitBlt
DrawBitmap(hdc, dstX, dstY, rgb_frame, size);

sws_freeContext(img_convert_ctx); 

1 Ответ

0 голосов
/ 19 ноября 2013

Когда вы создаете растровое изображение, ширина изображения ДОЛЖНА быть кратна 4.

Таким образом, вы должны изменить ширину, например, 480, 484, 488, 492 ...

ЗдесьЭто метод, который нужно изменить на кратное 4

#define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4)

void main()
{
    BITMAPFILEHEADER bmFileHeader;
    BITMAPINFOHEADER bmInfoHeader;

    // load image
    // ...

    // when you use the method, put parameter like this.
    int tempWidth = WIDTHBYTES(width * bmInfoHeader.biBitCount);
}

. Надеюсь, вы решите проблему.

...