@@ -540,33 +540,43 @@ QImage LibCameraWorker::convertBufferToImage(
540540 }
541541 }
542542 } else if (cfg.pixelFormat == libcamera::formats::YUV420) {
543- // YUV420 planar format (I420)
543+ // YUV420 planar format - Pi camera uses I420 (Y, U, V order)
544+ // But colors appear swapped, so this might be YV12 (Y, V, U order)
544545 unsigned int width = cfg.size .width ;
545546 unsigned int height = cfg.size .height ;
547+ unsigned int stride = cfg.stride ;
546548 image = QImage (width, height, QImage::Format_RGB888);
547549
548550 const uint8_t *src = static_cast <const uint8_t *>(memory);
549551 const uint8_t *yPlane = src;
550- const uint8_t *uPlane = src + width * height;
551- const uint8_t *vPlane = uPlane + (width * height / 4 );
552+ // Swap U and V planes - Pi outputs Y, V, U (YV12) not Y, U, V (I420)
553+ const uint8_t *vPlane = src + stride * height;
554+ const uint8_t *uPlane = vPlane + (stride / 2 ) * (height / 2 );
552555
553556 for (unsigned int y = 0 ; y < height; y++) {
557+ uint8_t *destRow = image.scanLine (y);
554558 for (unsigned int x = 0 ; x < width; x++) {
555- int yVal = yPlane[y * width + x];
556- int uVal = uPlane[(y / 2 ) * (width / 2 ) + (x / 2 )];
557- int vVal = vPlane[(y / 2 ) * (width / 2 ) + (x / 2 )];
558-
559- auto clamp = [](int val) { return std::max (0 , std::min (255 , val)); };
559+ int yVal = yPlane[y * stride + x];
560+ int uVal = uPlane[(y / 2 ) * (stride / 2 ) + (x / 2 )];
561+ int vVal = vPlane[(y / 2 ) * (stride / 2 ) + (x / 2 )];
560562
563+ // YUV to RGB conversion
561564 int c = yVal - 16 ;
562565 int d = uVal - 128 ;
563566 int e = vVal - 128 ;
564567
565- int r = clamp ((298 * c + 409 * e + 128 ) >> 8 );
566- int g = clamp ((298 * c - 100 * d - 208 * e + 128 ) >> 8 );
567- int b = clamp ((298 * c + 516 * d + 128 ) >> 8 );
568+ int r = (298 * c + 409 * e + 128 ) >> 8 ;
569+ int g = (298 * c - 100 * d - 208 * e + 128 ) >> 8 ;
570+ int b = (298 * c + 516 * d + 128 ) >> 8 ;
571+
572+ // Clamp values
573+ r = r < 0 ? 0 : (r > 255 ? 255 : r);
574+ g = g < 0 ? 0 : (g > 255 ? 255 : g);
575+ b = b < 0 ? 0 : (b > 255 ? 255 : b);
568576
569- image.setPixel (x, y, qRgb (r, g, b));
577+ destRow[x * 3 + 0 ] = static_cast <uint8_t >(r);
578+ destRow[x * 3 + 1 ] = static_cast <uint8_t >(g);
579+ destRow[x * 3 + 2 ] = static_cast <uint8_t >(b);
570580 }
571581 }
572582 } else {
0 commit comments