diff --git a/Common/CommonTypes.h b/Common/CommonTypes.h index 59d5814262..bc67c19ac5 100644 --- a/Common/CommonTypes.h +++ b/Common/CommonTypes.h @@ -28,6 +28,14 @@ #endif #endif +struct u24_be { + unsigned char value[3]; + + operator unsigned int(){ + return 0x00000000 | (value[0] << 16) | (value[1] << 8) | (value[2] << 0); + } +}; + #ifdef _WIN32 typedef unsigned __int8 u8; diff --git a/Core/HLE/sceJpeg.cpp b/Core/HLE/sceJpeg.cpp index 50a30e5777..68d5ce7858 100644 --- a/Core/HLE/sceJpeg.cpp +++ b/Core/HLE/sceJpeg.cpp @@ -52,7 +52,7 @@ u32 convertYCbCrToABGR (int y, int cb, int cr) { if (g > 0xFF) g = 0xFF; if(g < 0) g = 0; if (b > 0xFF) b = 0xFF; if(b < 0) b = 0; - return 0xFF000000 | (r << 16) | (g << 8) | (b << 0); + return 0xFF000000 | (b << 16) | (g << 8) | (r << 0); } //Uncomment if you want to dump JPEGs loaded through sceJpeg to a file @@ -64,38 +64,7 @@ int sceJpegDecompressAllImage() return 0; } -int sceJpegMJpegCsc(u32 imageAddr, u32 yCbCrAddr, int widthHeight, int bufferWidth) -{ - ERROR_LOG_REPORT(ME, "UNIMPL sceJpegMJpegCsc(%i, %i, %i, %i)", imageAddr, yCbCrAddr, widthHeight, bufferWidth); - return 0; -} - -int sceJpegDecodeMJpeg(u32 jpegAddr, int jpegSize, u32 imageAddr, int dhtMode) -{ - ERROR_LOG_REPORT(ME, "UNIMPL sceJpegDecodeMJpeg(%i, %i, %i, %i)", jpegAddr, jpegSize, imageAddr, dhtMode); - return 0; -} - -int sceJpegDecodeMJpegYCbCrSuccessively(u32 jpegAddr, int jpegSize, u32 yCbCrAddr, int yCbCrSize, int dhtMode) -{ - ERROR_LOG_REPORT(ME, "UNIMPL sceJpegDecodeMJpegYCbCrSuccessively(%i, %i, %i, %i, %i)", jpegAddr, jpegSize, yCbCrAddr, yCbCrSize, dhtMode); - return 0; -} - -int sceJpegDeleteMJpeg() -{ - ERROR_LOG_REPORT(ME, "UNIMPL sceJpegDeleteMJpeg()"); - return 0; -} - -int sceJpegDecodeMJpegSuccessively(u32 jpegAddr, int jpegSize, u32 imageAddr, int dhtMode) -{ - ERROR_LOG_REPORT(ME, "UNIMPL sceJpegDecodeMJpegSuccessively(%i, %i, %i, %i)", jpegAddr, jpegSize, imageAddr, dhtMode); - return 0; -} - -int sceJpegCsc(u32 imageAddr, u32 yCbCrAddr, int widthHeight, int bufferWidth, int colourInfo) -{ +void __JpegCsc(u32 imageAddr, u32 yCbCrAddr, int widthHeight, int bufferWidth) { int height = widthHeight & 0xFFF; int width = (widthHeight >> 16) & 0xFFF; int lineWidth = std::min(width, bufferWidth); @@ -132,6 +101,41 @@ int sceJpegCsc(u32 imageAddr, u32 yCbCrAddr, int widthHeight, int bufferWidth, i imageBuffer += width; imageBuffer += skipEndOfLine; } +} +int sceJpegMJpegCsc(u32 imageAddr, u32 yCbCrAddr, int widthHeight, int bufferWidth) +{ + __JpegCsc(imageAddr, yCbCrAddr, widthHeight, bufferWidth); + DEBUG_LOG(ME, "UNIMPL sceJpegMJpegCsc(%i, %i, %i, %i)", imageAddr, yCbCrAddr, widthHeight, bufferWidth); + return 0; +} + +int sceJpegDecodeMJpeg(u32 jpegAddr, int jpegSize, u32 imageAddr, int dhtMode) +{ + ERROR_LOG_REPORT(ME, "UNIMPL sceJpegDecodeMJpeg(%i, %i, %i, %i)", jpegAddr, jpegSize, imageAddr, dhtMode); + return 0; +} + +int sceJpegDecodeMJpegYCbCrSuccessively(u32 jpegAddr, int jpegSize, u32 yCbCrAddr, int yCbCrSize, int dhtMode) +{ + ERROR_LOG_REPORT(ME, "UNIMPL sceJpegDecodeMJpegYCbCrSuccessively(%i, %i, %i, %i, %i)", jpegAddr, jpegSize, yCbCrAddr, yCbCrSize, dhtMode); + return 0; +} + +int sceJpegDeleteMJpeg() +{ + ERROR_LOG_REPORT(ME, "UNIMPL sceJpegDeleteMJpeg()"); + return 0; +} + +int sceJpegDecodeMJpegSuccessively(u32 jpegAddr, int jpegSize, u32 imageAddr, int dhtMode) +{ + ERROR_LOG_REPORT(ME, "UNIMPL sceJpegDecodeMJpegSuccessively(%i, %i, %i, %i)", jpegAddr, jpegSize, imageAddr, dhtMode); + return 0; +} + +int sceJpegCsc(u32 imageAddr, u32 yCbCrAddr, int widthHeight, int bufferWidth, int colourInfo) +{ + __JpegCsc(imageAddr, yCbCrAddr, widthHeight, bufferWidth); DEBUG_LOG(ME, "UNIMPL sceJpegCsc(%i, %i, %i, %i, %i)", imageAddr, yCbCrAddr, widthHeight, bufferWidth, colourInfo); return 0; } @@ -192,6 +196,10 @@ int sceJpegGetOutputInfo(u32 jpegAddr, int jpegSize, u32 colourInfoAddr, int dht uint32 jpeg_cityhash = CityHash32((const char *)jpegBuf, jpegSize); sprintf(jpeg_fname, "Jpeg\\%X.jpg", jpeg_cityhash); FILE *wfp = fopen(jpeg_fname, "wb"); + if (!wfp) { + _wmkdir(L"Jpeg\\"); + wfp = fopen(jpeg_fname, "wb"); + } fwrite(jpegBuf, 1, jpegSize, wfp); fclose(wfp); #endif //JPEG_DEBUG @@ -204,6 +212,57 @@ int getWidthHeight(int width, int height) return (width << 16) | height; } +u32 convertRGBToYCbCr(u32 rgb) { + //see http://en.wikipedia.org/wiki/Yuv#Y.27UV444_to_RGB888_conversion for more information. + u8 r = (rgb >> 16) & 0xFF; + u8 g = (rgb >> 8) & 0xFF; + u8 b = (rgb >> 0) & 0xFF; + int y = 0.299f * r + 0.587f * g + 0.114f * b + 0; + int cb = -0.169f * r - 0.331f * g + 0.499f * b + 128.0f; + int cr = 0.499f * r - 0.418f * g - 0.0813f * b + 128.0f; + + // check yCbCr value + if ( y > 0xFF) y = 0xFF; if ( y < 0) y = 0; + if (cb > 0xFF) cb = 0xFF; if (cb < 0) cb = 0; + if (cr > 0xFF) cr = 0xFF; if (cr < 0) cr = 0; + + return (y << 16) | (cb << 8) | cr; +} + +int __JpegConvertRGBToYCbCr (const void *data, u32 bufferOutputAddr, int width, int height) { + u24_be *imageBuffer = (u24_be*)data; + int sizeY = width * height; + int sizeCb = sizeY >> 2; + u8 *Y = (u8*)Memory::GetPointer(bufferOutputAddr); + u8 *Cb = Y + sizeY; + u8 *Cr = Cb + sizeCb; + + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; x += 4) { + u32 abgr0 = imageBuffer[x + 0]; + u32 abgr1 = imageBuffer[x + 1]; + u32 abgr2 = imageBuffer[x + 2]; + u32 abgr3 = imageBuffer[x + 3]; + + u32 yCbCr0 = convertRGBToYCbCr(abgr0); + u32 yCbCr1 = convertRGBToYCbCr(abgr1); + u32 yCbCr2 = convertRGBToYCbCr(abgr2); + u32 yCbCr3 = convertRGBToYCbCr(abgr3); + + Y[x + 0] = (yCbCr0 >> 16) & 0xFF; + Y[x + 1] = (yCbCr1 >> 16) & 0xFF; + Y[x + 2] = (yCbCr2 >> 16) & 0xFF; + Y[x + 3] = (yCbCr3 >> 16) & 0xFF; + + *Cb++ = (yCbCr0 >> 8) & 0xFF; + *Cr++ = yCbCr0 & 0xFF; + } + imageBuffer += width; + Y += width ; + } + return (width << 16) | height; +} + int sceJpegDecodeMJpegYCbCr(u32 jpegAddr, int jpegSize, u32 yCbCrAddr, int yCbCrSize, int dhtMode) { ERROR_LOG_REPORT(ME, "sceJpegDecodeMJpegYCbCr(%i, %i, %i, %i, %i)", jpegAddr, jpegSize, yCbCrAddr, yCbCrSize, dhtMode); @@ -225,7 +284,8 @@ int sceJpegDecodeMJpegYCbCr(u32 jpegAddr, int jpegSize, u32 yCbCrAddr, int yCbCr } if (jpegBuf == NULL) return getWidthHeight(0, 0); - + if (actual_components == 3) + __JpegConvertRGBToYCbCr(jpegBuf, yCbCrAddr, width, height); // TODO: There's more... return getWidthHeight(width, height); diff --git a/Core/HLE/sceMpeg.cpp b/Core/HLE/sceMpeg.cpp index 55d4043089..5b0e0cc25e 100644 --- a/Core/HLE/sceMpeg.cpp +++ b/Core/HLE/sceMpeg.cpp @@ -1363,11 +1363,11 @@ u32 sceMpegAvcResourceInit(u32 mpeg) return 0; } -u32 convertARGBToYCbCr(u32 abgr) { +u32 convertABGRToYCbCr(u32 abgr) { //see http://en.wikipedia.org/wiki/Yuv#Y.27UV444_to_RGB888_conversion for more information. - u8 r = (abgr >> 16) & 0xFF; + u8 r = (abgr >> 0) & 0xFF; u8 g = (abgr >> 8) & 0xFF; - u8 b = (abgr >> 0) & 0xFF; + u8 b = (abgr >> 16) & 0xFF; int y = 0.299f * r + 0.587f * g + 0.114f * b + 0; int cb = -0.169f * r - 0.331f * g + 0.499f * b + 128.0f; int cr = 0.499f * r - 0.418f * g - 0.0813f * b + 128.0f; @@ -1390,15 +1390,15 @@ int __MpegAvcConvertToYuv420(const void *data, u32 bufferOutputAddr, int width, for (int y = 0; y < height; ++y) { for (int x = 0; x < width; x += 4) { - u32 argb0 = imageBuffer[x + 0]; - u32 argb1 = imageBuffer[x + 1]; - u32 argb2 = imageBuffer[x + 2]; - u32 argb3 = imageBuffer[x + 3]; + u32 abgr0 = imageBuffer[x + 0]; + u32 abgr1 = imageBuffer[x + 1]; + u32 abgr2 = imageBuffer[x + 2]; + u32 abgr3 = imageBuffer[x + 3]; - u32 yCbCr0 = convertARGBToYCbCr(argb0); - u32 yCbCr1 = convertARGBToYCbCr(argb1); - u32 yCbCr2 = convertARGBToYCbCr(argb2); - u32 yCbCr3 = convertARGBToYCbCr(argb3); + u32 yCbCr0 = convertABGRToYCbCr(abgr0); + u32 yCbCr1 = convertABGRToYCbCr(abgr1); + u32 yCbCr2 = convertABGRToYCbCr(abgr2); + u32 yCbCr3 = convertABGRToYCbCr(abgr3); Y[x + 0] = (yCbCr0 >> 16) & 0xFF; Y[x + 1] = (yCbCr1 >> 16) & 0xFF;