[Scummvm-git-logs] scummvm master -> 604708ad9897d2eeb687982c63e46bc8c2fc7ad8

sev- noreply at scummvm.org
Mon Apr 22 00:07:52 UTC 2024


This automated email contains information about 5 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
f683ecbf7b IMAGE: Cache the dithered Cinepak codebooks when using VFW-style dithering
ed59ab8a3b IMAGE: Make use of aligned loads and stores when dithering Cinepak videos
2cb46c19ed IMAGE: Split Cinepak CodebookConverterRaw into 8bpp and 24bpp versions
011e468fa1 IMAGE: Handle the surface pitch in Cinepak videos
604708ad98 IMAGE: Combine lookup tables for Cinepak with VFW dithering


Commit: f683ecbf7b2ccfd73ba326570862f18d2dd98c1d
    https://github.com/scummvm/scummvm/commit/f683ecbf7b2ccfd73ba326570862f18d2dd98c1d
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2024-04-22T02:07:47+02:00

Commit Message:
IMAGE: Cache the dithered Cinepak codebooks when using VFW-style dithering

Changed paths:
    image/codecs/cinepak.cpp
    image/codecs/cinepak.h


diff --git a/image/codecs/cinepak.cpp b/image/codecs/cinepak.cpp
index 1133eccd731..ad088959985 100644
--- a/image/codecs/cinepak.cpp
+++ b/image/codecs/cinepak.cpp
@@ -77,7 +77,7 @@ inline void putPixelRaw(byte *dst, const byte *clipTable, const Graphics::PixelF
  */
 struct CodebookConverterRaw {
 	template<typename PixelInt>
-	static inline void decodeBlock1(byte codebookIndex, const CinepakStrip &strip, PixelInt *(&rows)[4], const byte *clipTable, const byte *colorMap, const Graphics::PixelFormat &format) {
+	static inline void decodeBlock1(byte codebookIndex, const CinepakStrip &strip, PixelInt *(&rows)[4], const byte *clipTable, const Graphics::PixelFormat &format) {
 		const CinepakCodebook &codebook = strip.v1_codebook[codebookIndex];
 		putPixelRaw(rows[0] + 0, clipTable, format, codebook.y[0], codebook.u, codebook.v);
 		putPixelRaw(rows[0] + 1, clipTable, format, codebook.y[0], codebook.u, codebook.v);
@@ -101,7 +101,7 @@ struct CodebookConverterRaw {
 	}
 
 	template<typename PixelInt>
-	static inline void decodeBlock4(const byte (&codebookIndex)[4], const CinepakStrip &strip, PixelInt *(&rows)[4], const byte *clipTable, const byte *colorMap, const Graphics::PixelFormat &format) {
+	static inline void decodeBlock4(const byte (&codebookIndex)[4], const CinepakStrip &strip, PixelInt *(&rows)[4], const byte *clipTable, const Graphics::PixelFormat &format) {
 		const CinepakCodebook &codebook1 = strip.v4_codebook[codebookIndex[0]];
 		putPixelRaw(rows[0] + 0, clipTable, format, codebook1.y[0], codebook1.u, codebook1.v);
 		putPixelRaw(rows[0] + 1, clipTable, format, codebook1.y[1], codebook1.u, codebook1.v);
@@ -129,145 +129,10 @@ struct CodebookConverterRaw {
 };
 
 /**
- * Codebook converter that dithers in VFW-style
+ * Codebook converter that dithers in QT-style or VFW-style
  */
-struct CodebookConverterDitherVFW {
-	static inline void decodeBlock1(byte codebookIndex, const CinepakStrip &strip, byte *(&rows)[4], const byte *clipTable, const byte *colorMap, const Graphics::PixelFormat &format) {
-		const CinepakCodebook &codebook = strip.v1_codebook[codebookIndex];
-		byte blockBuffer[16];
-		ditherCodebookSmooth(codebook, blockBuffer, colorMap);
-		rows[0][0] = blockBuffer[0];
-		rows[0][1] = blockBuffer[1];
-		rows[0][2] = blockBuffer[2];
-		rows[0][3] = blockBuffer[3];
-		rows[1][0] = blockBuffer[4];
-		rows[1][1] = blockBuffer[5];
-		rows[1][2] = blockBuffer[6];
-		rows[1][3] = blockBuffer[7];
-		rows[2][0] = blockBuffer[8];
-		rows[2][1] = blockBuffer[9];
-		rows[2][2] = blockBuffer[10];
-		rows[2][3] = blockBuffer[11];
-		rows[3][0] = blockBuffer[12];
-		rows[3][1] = blockBuffer[13];
-		rows[3][2] = blockBuffer[14];
-		rows[3][3] = blockBuffer[15];
-	}
-
-	static inline void decodeBlock4(const byte (&codebookIndex)[4], const CinepakStrip &strip, byte *(&rows)[4], const byte *clipTable, const byte *colorMap, const Graphics::PixelFormat &format) {
-		byte blockBuffer[16];
-		ditherCodebookDetail(strip.v4_codebook[codebookIndex[0]], blockBuffer, colorMap);
-		rows[0][0] = blockBuffer[0];
-		rows[0][1] = blockBuffer[1];
-		rows[1][0] = blockBuffer[4];
-		rows[1][1] = blockBuffer[5];
-
-		ditherCodebookDetail(strip.v4_codebook[codebookIndex[1]], blockBuffer, colorMap);
-		rows[0][2] = blockBuffer[2];
-		rows[0][3] = blockBuffer[3];
-		rows[1][2] = blockBuffer[6];
-		rows[1][3] = blockBuffer[7];
-
-		ditherCodebookDetail(strip.v4_codebook[codebookIndex[2]], blockBuffer, colorMap);
-		rows[2][0] = blockBuffer[8];
-		rows[2][1] = blockBuffer[9];
-		rows[3][0] = blockBuffer[12];
-		rows[3][1] = blockBuffer[13];
-
-		ditherCodebookDetail(strip.v4_codebook[codebookIndex[3]], blockBuffer, colorMap);
-		rows[2][2] = blockBuffer[10];
-		rows[2][3] = blockBuffer[11];
-		rows[3][2] = blockBuffer[14];
-		rows[3][3] = blockBuffer[15];
-	}
-
-private:
-	static inline void ditherCodebookDetail(const CinepakCodebook &codebook, byte *dst, const byte *colorMap) {
-		int uLookup = (byte)codebook.u * 2;
-		int vLookup = (byte)codebook.v * 2;
-		uint32 uv1 = s_uLookup[uLookup] | s_vLookup[vLookup];
-		uint32 uv2 = s_uLookup[uLookup + 1] | s_vLookup[vLookup + 1];
-
-		int yLookup1 = codebook.y[0] * 2;
-		int yLookup2 = codebook.y[1] * 2;
-		int yLookup3 = codebook.y[2] * 2;
-		int yLookup4 = codebook.y[3] * 2;
-
-		uint32 pixelGroup1 = uv2 | s_yLookup[yLookup1 + 1];
-		uint32 pixelGroup2 = uv2 | s_yLookup[yLookup2 + 1];
-		uint32 pixelGroup3 = uv1 | s_yLookup[yLookup3];
-		uint32 pixelGroup4 = uv1 | s_yLookup[yLookup4];
-		uint32 pixelGroup5 = uv1 | s_yLookup[yLookup1];
-		uint32 pixelGroup6 = uv1 | s_yLookup[yLookup2];
-		uint32 pixelGroup7 = uv2 | s_yLookup[yLookup3 + 1];
-		uint32 pixelGroup8 = uv2 | s_yLookup[yLookup4 + 1];
-
-		dst[0] = getRGBLookupEntry(colorMap, pixelGroup1 & 0xFFFF);
-		dst[1] = getRGBLookupEntry(colorMap, pixelGroup2 >> 16);
-		dst[2] = getRGBLookupEntry(colorMap, pixelGroup5 & 0xFFFF);
-		dst[3] = getRGBLookupEntry(colorMap, pixelGroup6 >> 16);
-		dst[4] = getRGBLookupEntry(colorMap, pixelGroup3 & 0xFFFF);
-		dst[5] = getRGBLookupEntry(colorMap, pixelGroup4 >> 16);
-		dst[6] = getRGBLookupEntry(colorMap, pixelGroup7 & 0xFFFF);
-		dst[7] = getRGBLookupEntry(colorMap, pixelGroup8 >> 16);
-		dst[8] = getRGBLookupEntry(colorMap, pixelGroup1 >> 16);
-		dst[9] = getRGBLookupEntry(colorMap, pixelGroup6 & 0xFFFF);
-		dst[10] = getRGBLookupEntry(colorMap, pixelGroup5 >> 16);
-		dst[11] = getRGBLookupEntry(colorMap, pixelGroup2 & 0xFFFF);
-		dst[12] = getRGBLookupEntry(colorMap, pixelGroup3 >> 16);
-		dst[13] = getRGBLookupEntry(colorMap, pixelGroup8 & 0xFFFF);
-		dst[14] = getRGBLookupEntry(colorMap, pixelGroup7 >> 16);
-		dst[15] = getRGBLookupEntry(colorMap, pixelGroup4 & 0xFFFF);
-	}
-
-	static inline void ditherCodebookSmooth(const CinepakCodebook &codebook, byte *dst, const byte *colorMap) {
-		int uLookup = (byte)codebook.u * 2;
-		int vLookup = (byte)codebook.v * 2;
-		uint32 uv1 = s_uLookup[uLookup] | s_vLookup[vLookup];
-		uint32 uv2 = s_uLookup[uLookup + 1] | s_vLookup[vLookup + 1];
-
-		int yLookup1 = codebook.y[0] * 2;
-		int yLookup2 = codebook.y[1] * 2;
-		int yLookup3 = codebook.y[2] * 2;
-		int yLookup4 = codebook.y[3] * 2;
-
-		uint32 pixelGroup1 = uv2 | s_yLookup[yLookup1 + 1];
-		uint32 pixelGroup2 = uv1 | s_yLookup[yLookup2];
-		uint32 pixelGroup3 = uv1 | s_yLookup[yLookup1];
-		uint32 pixelGroup4 = uv2 | s_yLookup[yLookup2 + 1];
-		uint32 pixelGroup5 = uv2 | s_yLookup[yLookup3 + 1];
-		uint32 pixelGroup6 = uv1 | s_yLookup[yLookup3];
-		uint32 pixelGroup7 = uv1 | s_yLookup[yLookup4];
-		uint32 pixelGroup8 = uv2 | s_yLookup[yLookup4 + 1];
-
-		dst[0] = getRGBLookupEntry(colorMap, pixelGroup1 & 0xFFFF);
-		dst[1] = getRGBLookupEntry(colorMap, pixelGroup1 >> 16);
-		dst[2] = getRGBLookupEntry(colorMap, pixelGroup2 & 0xFFFF);
-		dst[3] = getRGBLookupEntry(colorMap, pixelGroup2 >> 16);
-		dst[4] = getRGBLookupEntry(colorMap, pixelGroup3 & 0xFFFF);
-		dst[5] = getRGBLookupEntry(colorMap, pixelGroup3 >> 16);
-		dst[6] = getRGBLookupEntry(colorMap, pixelGroup4 & 0xFFFF);
-		dst[7] = getRGBLookupEntry(colorMap, pixelGroup4 >> 16);
-		dst[8] = getRGBLookupEntry(colorMap, pixelGroup5 >> 16);
-		dst[9] = getRGBLookupEntry(colorMap, pixelGroup6 & 0xFFFF);
-		dst[10] = getRGBLookupEntry(colorMap, pixelGroup7 >> 16);
-		dst[11] = getRGBLookupEntry(colorMap, pixelGroup8 & 0xFFFF);
-		dst[12] = getRGBLookupEntry(colorMap, pixelGroup6 >> 16);
-		dst[13] = getRGBLookupEntry(colorMap, pixelGroup5 & 0xFFFF);
-		dst[14] = getRGBLookupEntry(colorMap, pixelGroup8 >> 16);
-		dst[15] = getRGBLookupEntry(colorMap, pixelGroup7 & 0xFFFF);
-	}
-
-	static inline byte getRGBLookupEntry(const byte *colorMap, uint16 index) {
-		return colorMap[s_defaultPaletteLookup[CLIP<int>(index, 0, 1023)]];
-	}
-};
-
-/**
- * Codebook converter that dithers in QT-style
- */
-struct CodebookConverterDitherQT {
-	static inline void decodeBlock1(byte codebookIndex, const CinepakStrip &strip, byte *(&rows)[4], const byte *clipTable, const byte *colorMap, const Graphics::PixelFormat &format) {
+struct CodebookConverterDithered {
+	static inline void decodeBlock1(byte codebookIndex, const CinepakStrip &strip, byte *(&rows)[4], const byte *clipTable, const Graphics::PixelFormat &format) {
 		const byte *colorPtr = strip.v1_dither + (codebookIndex << 2);
 		WRITE_UINT32(rows[0], READ_UINT32(colorPtr));
 		WRITE_UINT32(rows[1], READ_UINT32(colorPtr + 1024));
@@ -275,7 +140,7 @@ struct CodebookConverterDitherQT {
 		WRITE_UINT32(rows[3], READ_UINT32(colorPtr + 3072));
 	}
 
-	static inline void decodeBlock4(const byte (&codebookIndex)[4], const CinepakStrip &strip, byte *(&rows)[4], const byte *clipTable, const byte *colorMap, const Graphics::PixelFormat &format) {
+	static inline void decodeBlock4(const byte (&codebookIndex)[4], const CinepakStrip &strip, byte *(&rows)[4], const byte *clipTable, const Graphics::PixelFormat &format) {
 		const byte *colorPtr = strip.v4_dither + (codebookIndex[0] << 2);
 		WRITE_UINT16(rows[0] + 0, READ_UINT16(colorPtr + 0));
 		WRITE_UINT16(rows[1] + 0, READ_UINT16(colorPtr + 2));
@@ -295,7 +160,7 @@ struct CodebookConverterDitherQT {
 };
 
 template<typename PixelInt, typename CodebookConverter>
-void decodeVectorsTmpl(CinepakFrame &frame, const byte *clipTable, const byte *colorMap, Common::SeekableReadStream &stream, uint16 strip, byte chunkID, uint32 chunkSize) {
+void decodeVectorsTmpl(CinepakFrame &frame, const byte *clipTable, Common::SeekableReadStream &stream, uint16 strip, byte chunkID, uint32 chunkSize) {
 	uint32 flag = 0, mask = 0;
 	PixelInt *iy[4];
 	int32 startPos = stream.pos();
@@ -330,14 +195,14 @@ void decodeVectorsTmpl(CinepakFrame &frame, const byte *clipTable, const byte *c
 
 					// Get the codebook
 					byte codebook = stream.readByte();
-					CodebookConverter::decodeBlock1(codebook, frame.strips[strip], iy, clipTable, colorMap, frame.surface->format);
+					CodebookConverter::decodeBlock1(codebook, frame.strips[strip], iy, clipTable, frame.surface->format);
 				} else if (flag & mask) {
 					if ((stream.pos() - startPos + 4) > (int32)chunkSize)
 						return;
 
 					byte codebook[4];
 					stream.read(codebook, 4);
-					CodebookConverter::decodeBlock4(codebook, frame.strips[strip], iy, clipTable, colorMap, frame.surface->format);
+					CodebookConverter::decodeBlock4(codebook, frame.strips[strip], iy, clipTable, frame.surface->format);
 				}
 			}
 
@@ -438,7 +303,7 @@ const Graphics::Surface *CinepakDecoder::decodeFrame(Common::SeekableReadStream
 				_curFrame.strips[i].v4_codebook[j] = _curFrame.strips[i - 1].v4_codebook[j];
 			}
 
-			// Copy the QuickTime dither tables
+			// Copy the dither tables
 			memcpy(_curFrame.strips[i].v1_dither, _curFrame.strips[i - 1].v1_dither, 256 * 4 * 4 * 4);
 			memcpy(_curFrame.strips[i].v4_dither, _curFrame.strips[i - 1].v4_dither, 256 * 4 * 4 * 4);
 		}
@@ -513,6 +378,8 @@ void CinepakDecoder::initializeCodebook(uint16 strip, byte codebookType) {
 
 		if (_ditherType == kDitherTypeQT)
 			ditherCodebookQT(strip, codebookType, i);
+		else if (_ditherType == kDitherTypeVFW)
+			ditherCodebookVFW(strip, codebookType, i);
 	}
 }
 
@@ -552,6 +419,8 @@ void CinepakDecoder::loadCodebook(Common::SeekableReadStream &stream, uint16 str
 			// Dither the codebook if we're dithering for QuickTime
 			if (_ditherType == kDitherTypeQT)
 				ditherCodebookQT(strip, codebookType, i);
+			else if (_ditherType == kDitherTypeVFW)
+				ditherCodebookVFW(strip, codebookType, i);
 		}
 	}
 }
@@ -614,13 +483,99 @@ void CinepakDecoder::ditherCodebookQT(uint16 strip, byte codebookType, uint16 co
 	}
 }
 
+static inline byte getRGBLookupEntry(const byte *colorMap, uint16 index) {
+	return colorMap[s_defaultPaletteLookup[CLIP<int>(index, 0, 1023)]];
+}
+
+void CinepakDecoder::ditherCodebookVFW(uint16 strip, byte codebookType, uint16 codebookIndex) {
+	if (codebookType == 1) {
+		const CinepakCodebook &codebook = _curFrame.strips[strip].v1_codebook[codebookIndex];
+		byte *output = _curFrame.strips[strip].v1_dither + (codebookIndex << 2);
+
+		int uLookup = (byte)codebook.u * 2;
+		int vLookup = (byte)codebook.v * 2;
+		uint32 uv1 = s_uLookup[uLookup] | s_vLookup[vLookup];
+		uint32 uv2 = s_uLookup[uLookup + 1] | s_vLookup[vLookup + 1];
+
+		int yLookup1 = codebook.y[0] * 2;
+		int yLookup2 = codebook.y[1] * 2;
+		int yLookup3 = codebook.y[2] * 2;
+		int yLookup4 = codebook.y[3] * 2;
+
+		uint32 pixelGroup1 = uv2 | s_yLookup[yLookup1 + 1];
+		uint32 pixelGroup2 = uv1 | s_yLookup[yLookup2];
+		uint32 pixelGroup3 = uv1 | s_yLookup[yLookup1];
+		uint32 pixelGroup4 = uv2 | s_yLookup[yLookup2 + 1];
+		uint32 pixelGroup5 = uv2 | s_yLookup[yLookup3 + 1];
+		uint32 pixelGroup6 = uv1 | s_yLookup[yLookup3];
+		uint32 pixelGroup7 = uv1 | s_yLookup[yLookup4];
+		uint32 pixelGroup8 = uv2 | s_yLookup[yLookup4 + 1];
+
+		output[0x000] = getRGBLookupEntry(_colorMap, pixelGroup1 & 0xFFFF);
+		output[0x001] = getRGBLookupEntry(_colorMap, pixelGroup1 >> 16);
+		output[0x002] = getRGBLookupEntry(_colorMap, pixelGroup2 & 0xFFFF);
+		output[0x003] = getRGBLookupEntry(_colorMap, pixelGroup2 >> 16);
+		output[0x400] = getRGBLookupEntry(_colorMap, pixelGroup3 & 0xFFFF);
+		output[0x401] = getRGBLookupEntry(_colorMap, pixelGroup3 >> 16);
+		output[0x402] = getRGBLookupEntry(_colorMap, pixelGroup4 & 0xFFFF);
+		output[0x403] = getRGBLookupEntry(_colorMap, pixelGroup4 >> 16);
+		output[0x800] = getRGBLookupEntry(_colorMap, pixelGroup5 >> 16);
+		output[0x801] = getRGBLookupEntry(_colorMap, pixelGroup6 & 0xFFFF);
+		output[0x802] = getRGBLookupEntry(_colorMap, pixelGroup7 >> 16);
+		output[0x803] = getRGBLookupEntry(_colorMap, pixelGroup8 & 0xFFFF);
+		output[0xC00] = getRGBLookupEntry(_colorMap, pixelGroup6 >> 16);
+		output[0xC01] = getRGBLookupEntry(_colorMap, pixelGroup5 & 0xFFFF);
+		output[0xC02] = getRGBLookupEntry(_colorMap, pixelGroup8 >> 16);
+		output[0xC03] = getRGBLookupEntry(_colorMap, pixelGroup7 & 0xFFFF);
+	} else {
+		const CinepakCodebook &codebook = _curFrame.strips[strip].v4_codebook[codebookIndex];
+		byte *output = _curFrame.strips[strip].v4_dither + (codebookIndex << 2);
+
+		int uLookup = (byte)codebook.u * 2;
+		int vLookup = (byte)codebook.v * 2;
+		uint32 uv1 = s_uLookup[uLookup] | s_vLookup[vLookup];
+		uint32 uv2 = s_uLookup[uLookup + 1] | s_vLookup[vLookup + 1];
+
+		int yLookup1 = codebook.y[0] * 2;
+		int yLookup2 = codebook.y[1] * 2;
+		int yLookup3 = codebook.y[2] * 2;
+		int yLookup4 = codebook.y[3] * 2;
+
+		uint32 pixelGroup1 = uv2 | s_yLookup[yLookup1 + 1];
+		uint32 pixelGroup2 = uv2 | s_yLookup[yLookup2 + 1];
+		uint32 pixelGroup3 = uv1 | s_yLookup[yLookup3];
+		uint32 pixelGroup4 = uv1 | s_yLookup[yLookup4];
+		uint32 pixelGroup5 = uv1 | s_yLookup[yLookup1];
+		uint32 pixelGroup6 = uv1 | s_yLookup[yLookup2];
+		uint32 pixelGroup7 = uv2 | s_yLookup[yLookup3 + 1];
+		uint32 pixelGroup8 = uv2 | s_yLookup[yLookup4 + 1];
+
+		output[0x000] = getRGBLookupEntry(_colorMap, pixelGroup1 & 0xFFFF);
+		output[0x001] = getRGBLookupEntry(_colorMap, pixelGroup2 >> 16);
+		output[0x400] = getRGBLookupEntry(_colorMap, pixelGroup5 & 0xFFFF);
+		output[0x401] = getRGBLookupEntry(_colorMap, pixelGroup6 >> 16);
+		output[0x002] = getRGBLookupEntry(_colorMap, pixelGroup3 & 0xFFFF);
+		output[0x003] = getRGBLookupEntry(_colorMap, pixelGroup4 >> 16);
+		output[0x402] = getRGBLookupEntry(_colorMap, pixelGroup7 & 0xFFFF);
+		output[0x403] = getRGBLookupEntry(_colorMap, pixelGroup8 >> 16);
+		output[0x800] = getRGBLookupEntry(_colorMap, pixelGroup1 >> 16);
+		output[0x801] = getRGBLookupEntry(_colorMap, pixelGroup6 & 0xFFFF);
+		output[0xC00] = getRGBLookupEntry(_colorMap, pixelGroup5 >> 16);
+		output[0xC01] = getRGBLookupEntry(_colorMap, pixelGroup2 & 0xFFFF);
+		output[0x802] = getRGBLookupEntry(_colorMap, pixelGroup3 >> 16);
+		output[0x803] = getRGBLookupEntry(_colorMap, pixelGroup8 & 0xFFFF);
+		output[0xC02] = getRGBLookupEntry(_colorMap, pixelGroup7 >> 16);
+		output[0xC03] = getRGBLookupEntry(_colorMap, pixelGroup4 & 0xFFFF);
+	}
+}
+
 void CinepakDecoder::decodeVectors(Common::SeekableReadStream &stream, uint16 strip, byte chunkID, uint32 chunkSize) {
 	if (_curFrame.surface->format.bytesPerPixel == 1) {
-		decodeVectorsTmpl<byte, CodebookConverterRaw>(_curFrame, _clipTable, _colorMap, stream, strip, chunkID, chunkSize);
+		decodeVectorsTmpl<byte, CodebookConverterRaw>(_curFrame, _clipTable, stream, strip, chunkID, chunkSize);
 	} else if (_curFrame.surface->format.bytesPerPixel == 2) {
-		decodeVectorsTmpl<uint16, CodebookConverterRaw>(_curFrame, _clipTable, _colorMap, stream, strip, chunkID, chunkSize);
+		decodeVectorsTmpl<uint16, CodebookConverterRaw>(_curFrame, _clipTable, stream, strip, chunkID, chunkSize);
 	} else if (_curFrame.surface->format.bytesPerPixel == 4) {
-		decodeVectorsTmpl<uint32, CodebookConverterRaw>(_curFrame, _clipTable, _colorMap, stream, strip, chunkID, chunkSize);
+		decodeVectorsTmpl<uint32, CodebookConverterRaw>(_curFrame, _clipTable, stream, strip, chunkID, chunkSize);
 	}
 }
 
@@ -696,10 +651,7 @@ byte CinepakDecoder::findNearestRGB(int index) const {
 }
 
 void CinepakDecoder::ditherVectors(Common::SeekableReadStream &stream, uint16 strip, byte chunkID, uint32 chunkSize) {
-	if (_ditherType == kDitherTypeVFW)
-		decodeVectorsTmpl<byte, CodebookConverterDitherVFW>(_curFrame, _clipTable, _colorMap, stream, strip, chunkID, chunkSize);
-	else
-		decodeVectorsTmpl<byte, CodebookConverterDitherQT>(_curFrame, _clipTable, _colorMap, stream, strip, chunkID, chunkSize);
+	decodeVectorsTmpl<byte, CodebookConverterDithered>(_curFrame, _clipTable, stream, strip, chunkID, chunkSize);
 }
 
 } // End of namespace Image
diff --git a/image/codecs/cinepak.h b/image/codecs/cinepak.h
index a537ac8c3c5..c4ce7d774ff 100644
--- a/image/codecs/cinepak.h
+++ b/image/codecs/cinepak.h
@@ -101,6 +101,7 @@ private:
 	byte findNearestRGB(int index) const;
 	void ditherVectors(Common::SeekableReadStream &stream, uint16 strip, byte chunkID, uint32 chunkSize);
 	void ditherCodebookQT(uint16 strip, byte codebookType, uint16 codebookIndex);
+	void ditherCodebookVFW(uint16 strip, byte codebookType, uint16 codebookIndex);
 };
 
 } // End of namespace Image


Commit: ed59ab8a3b4155a555b2ce139fb328bffbe86875
    https://github.com/scummvm/scummvm/commit/ed59ab8a3b4155a555b2ce139fb328bffbe86875
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2024-04-22T02:07:47+02:00

Commit Message:
IMAGE: Make use of aligned loads and stores when dithering Cinepak videos

Changed paths:
    image/codecs/cinepak.cpp
    image/codecs/cinepak.h


diff --git a/image/codecs/cinepak.cpp b/image/codecs/cinepak.cpp
index ad088959985..4b795695877 100644
--- a/image/codecs/cinepak.cpp
+++ b/image/codecs/cinepak.cpp
@@ -133,29 +133,29 @@ struct CodebookConverterRaw {
  */
 struct CodebookConverterDithered {
 	static inline void decodeBlock1(byte codebookIndex, const CinepakStrip &strip, byte *(&rows)[4], const byte *clipTable, const Graphics::PixelFormat &format) {
-		const byte *colorPtr = strip.v1_dither + (codebookIndex << 2);
-		WRITE_UINT32(rows[0], READ_UINT32(colorPtr));
-		WRITE_UINT32(rows[1], READ_UINT32(colorPtr + 1024));
-		WRITE_UINT32(rows[2], READ_UINT32(colorPtr + 2048));
-		WRITE_UINT32(rows[3], READ_UINT32(colorPtr + 3072));
+		const uint32 *colorPtr = (const uint32 *)(strip.v1_dither + codebookIndex);
+		*((uint32 *)rows[0]) = colorPtr[0];
+		*((uint32 *)rows[1]) = colorPtr[256];
+		*((uint32 *)rows[2]) = colorPtr[512];
+		*((uint32 *)rows[3]) = colorPtr[768];
 	}
 
 	static inline void decodeBlock4(const byte (&codebookIndex)[4], const CinepakStrip &strip, byte *(&rows)[4], const byte *clipTable, const Graphics::PixelFormat &format) {
-		const byte *colorPtr = strip.v4_dither + (codebookIndex[0] << 2);
-		WRITE_UINT16(rows[0] + 0, READ_UINT16(colorPtr + 0));
-		WRITE_UINT16(rows[1] + 0, READ_UINT16(colorPtr + 2));
+		const uint16 *colorPtr = (const uint16 *)(strip.v4_dither + codebookIndex[0]);
+		*((uint16 *)(rows[0] + 0)) = colorPtr[0];
+		*((uint16 *)(rows[1] + 0)) = colorPtr[1];
 
-		colorPtr = strip.v4_dither + (codebookIndex[1] << 2);
-		WRITE_UINT16(rows[0] + 2, READ_UINT16(colorPtr + 1024));
-		WRITE_UINT16(rows[1] + 2, READ_UINT16(colorPtr + 1026));
+		colorPtr = (const uint16 *)(strip.v4_dither + codebookIndex[1]);
+		*((uint16 *)(rows[0] + 2)) = colorPtr[512];
+		*((uint16 *)(rows[1] + 2)) = colorPtr[513];
 
-		colorPtr = strip.v4_dither + (codebookIndex[2] << 2);
-		WRITE_UINT16(rows[2] + 0, READ_UINT16(colorPtr + 2048));
-		WRITE_UINT16(rows[3] + 0, READ_UINT16(colorPtr + 2050));
+		colorPtr = (const uint16 *)(strip.v4_dither + codebookIndex[2]);
+		*((uint16 *)(rows[2] + 0)) = colorPtr[1024];
+		*((uint16 *)(rows[3] + 0)) = colorPtr[1025];
 
-		colorPtr = strip.v4_dither + (codebookIndex[3] << 2);
-		WRITE_UINT16(rows[2] + 2, READ_UINT16(colorPtr + 3072));
-		WRITE_UINT16(rows[3] + 2, READ_UINT16(colorPtr + 3074));
+		colorPtr = (const uint16 *)(strip.v4_dither + codebookIndex[3]);
+		*((uint16 *)(rows[2] + 2)) = colorPtr[1536];
+		*((uint16 *)(rows[3] + 2)) = colorPtr[1537];
 	}
 };
 
@@ -304,8 +304,8 @@ const Graphics::Surface *CinepakDecoder::decodeFrame(Common::SeekableReadStream
 			}
 
 			// Copy the dither tables
-			memcpy(_curFrame.strips[i].v1_dither, _curFrame.strips[i - 1].v1_dither, 256 * 4 * 4 * 4);
-			memcpy(_curFrame.strips[i].v4_dither, _curFrame.strips[i - 1].v4_dither, 256 * 4 * 4 * 4);
+			memcpy(_curFrame.strips[i].v1_dither, _curFrame.strips[i - 1].v1_dither, 256 * 4 * 4 * sizeof(uint32));
+			memcpy(_curFrame.strips[i].v4_dither, _curFrame.strips[i - 1].v4_dither, 256 * 4 * 4 * sizeof(uint32));
 		}
 
 		_curFrame.strips[i].id = stream.readUint16BE();
@@ -428,7 +428,7 @@ void CinepakDecoder::loadCodebook(Common::SeekableReadStream &stream, uint16 str
 void CinepakDecoder::ditherCodebookQT(uint16 strip, byte codebookType, uint16 codebookIndex) {
 	if (codebookType == 1) {
 		const CinepakCodebook &codebook = _curFrame.strips[strip].v1_codebook[codebookIndex];
-		byte *output = _curFrame.strips[strip].v1_dither + (codebookIndex << 2);
+		byte *output = (byte *)(_curFrame.strips[strip].v1_dither + codebookIndex);
 
 		byte *ditherEntry = _colorMap + createDitherTableIndex(_clipTable, codebook.y[0], codebook.u, codebook.v);
 		output[0x000] = ditherEntry[0x0000];
@@ -455,7 +455,7 @@ void CinepakDecoder::ditherCodebookQT(uint16 strip, byte codebookType, uint16 co
 		output[0xC03] = ditherEntry[0x4000];
 	} else {
 		const CinepakCodebook &codebook = _curFrame.strips[strip].v4_codebook[codebookIndex];
-		byte *output = _curFrame.strips[strip].v4_dither + (codebookIndex << 2);
+		byte *output = (byte *)(_curFrame.strips[strip].v4_dither + codebookIndex);
 
 		byte *ditherEntry = _colorMap + createDitherTableIndex(_clipTable, codebook.y[0], codebook.u, codebook.v);
 		output[0x000] = ditherEntry[0x0000];
@@ -490,7 +490,7 @@ static inline byte getRGBLookupEntry(const byte *colorMap, uint16 index) {
 void CinepakDecoder::ditherCodebookVFW(uint16 strip, byte codebookType, uint16 codebookIndex) {
 	if (codebookType == 1) {
 		const CinepakCodebook &codebook = _curFrame.strips[strip].v1_codebook[codebookIndex];
-		byte *output = _curFrame.strips[strip].v1_dither + (codebookIndex << 2);
+		byte *output = (byte *)(_curFrame.strips[strip].v1_dither + codebookIndex);
 
 		int uLookup = (byte)codebook.u * 2;
 		int vLookup = (byte)codebook.v * 2;
@@ -529,7 +529,7 @@ void CinepakDecoder::ditherCodebookVFW(uint16 strip, byte codebookType, uint16 c
 		output[0xC03] = getRGBLookupEntry(_colorMap, pixelGroup7 & 0xFFFF);
 	} else {
 		const CinepakCodebook &codebook = _curFrame.strips[strip].v4_codebook[codebookIndex];
-		byte *output = _curFrame.strips[strip].v4_dither + (codebookIndex << 2);
+		byte *output = (byte *)(_curFrame.strips[strip].v4_dither + codebookIndex);
 
 		int uLookup = (byte)codebook.u * 2;
 		int vLookup = (byte)codebook.v * 2;
diff --git a/image/codecs/cinepak.h b/image/codecs/cinepak.h
index c4ce7d774ff..f978a140ad8 100644
--- a/image/codecs/cinepak.h
+++ b/image/codecs/cinepak.h
@@ -45,7 +45,7 @@ struct CinepakStrip {
 	uint16 length;
 	Common::Rect rect;
 	CinepakCodebook v1_codebook[256], v4_codebook[256];
-	byte v1_dither[256 * 4 * 4 * 4], v4_dither[256 * 4 * 4 * 4];
+	uint32 v1_dither[256 * 4 * 4], v4_dither[256 * 4 * 4];
 };
 
 struct CinepakFrame {


Commit: 2cb46c19eda11c6d2f720fcc342baaa29e22fdf2
    https://github.com/scummvm/scummvm/commit/2cb46c19eda11c6d2f720fcc342baaa29e22fdf2
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2024-04-22T02:07:47+02:00

Commit Message:
IMAGE: Split Cinepak CodebookConverterRaw into 8bpp and 24bpp versions

Changed paths:
    image/codecs/cinepak.cpp
    image/codecs/cinepak.h


diff --git a/image/codecs/cinepak.cpp b/image/codecs/cinepak.cpp
index 4b795695877..4ebf77a6319 100644
--- a/image/codecs/cinepak.cpp
+++ b/image/codecs/cinepak.cpp
@@ -57,74 +57,90 @@ inline uint16 createDitherTableIndex(const byte *clipTable, byte y, int8 u, int8
 }
 
 /**
- * Put a raw pixel to the destination surface
+ * The default codebook converter for 24bpp: RGB output.
  */
-template<typename PixelInt>
-inline void putPixelRaw(PixelInt *dst, const byte *clipTable, const Graphics::PixelFormat &format, byte y, byte u, byte v) {
-	*dst = convertYUVToColor(clipTable, format, y, u, v);
-}
-
-/**
- * Specialized putPixelRaw for palettized 8bpp output
- */
-template<>
-inline void putPixelRaw(byte *dst, const byte *clipTable, const Graphics::PixelFormat &format, byte y, byte u, byte v) {
-	*dst = y;
-}
-
-/**
- * The default codebook converter: raw output.
- */
-struct CodebookConverterRaw {
+struct CodebookConverterRGB {
 	template<typename PixelInt>
 	static inline void decodeBlock1(byte codebookIndex, const CinepakStrip &strip, PixelInt *(&rows)[4], const byte *clipTable, const Graphics::PixelFormat &format) {
 		const CinepakCodebook &codebook = strip.v1_codebook[codebookIndex];
-		putPixelRaw(rows[0] + 0, clipTable, format, codebook.y[0], codebook.u, codebook.v);
-		putPixelRaw(rows[0] + 1, clipTable, format, codebook.y[0], codebook.u, codebook.v);
-		putPixelRaw(rows[1] + 0, clipTable, format, codebook.y[0], codebook.u, codebook.v);
-		putPixelRaw(rows[1] + 1, clipTable, format, codebook.y[0], codebook.u, codebook.v);
-
-		putPixelRaw(rows[0] + 2, clipTable, format, codebook.y[1], codebook.u, codebook.v);
-		putPixelRaw(rows[0] + 3, clipTable, format, codebook.y[1], codebook.u, codebook.v);
-		putPixelRaw(rows[1] + 2, clipTable, format, codebook.y[1], codebook.u, codebook.v);
-		putPixelRaw(rows[1] + 3, clipTable, format, codebook.y[1], codebook.u, codebook.v);
-
-		putPixelRaw(rows[2] + 0, clipTable, format, codebook.y[2], codebook.u, codebook.v);
-		putPixelRaw(rows[2] + 1, clipTable, format, codebook.y[2], codebook.u, codebook.v);
-		putPixelRaw(rows[3] + 0, clipTable, format, codebook.y[2], codebook.u, codebook.v);
-		putPixelRaw(rows[3] + 1, clipTable, format, codebook.y[2], codebook.u, codebook.v);
-
-		putPixelRaw(rows[2] + 2, clipTable, format, codebook.y[3], codebook.u, codebook.v);
-		putPixelRaw(rows[2] + 3, clipTable, format, codebook.y[3], codebook.u, codebook.v);
-		putPixelRaw(rows[3] + 2, clipTable, format, codebook.y[3], codebook.u, codebook.v);
-		putPixelRaw(rows[3] + 3, clipTable, format, codebook.y[3], codebook.u, codebook.v);
+
+		const PixelInt rgb0 = convertYUVToColor(clipTable, format, codebook.y[0], codebook.u, codebook.v);
+		rows[0][0] = rows[0][1] = rows[1][0] = rows[1][1] = rgb0;
+
+		const PixelInt rgb1 = convertYUVToColor(clipTable, format, codebook.y[1], codebook.u, codebook.v);
+		rows[0][2] = rows[0][3] = rows[1][2] = rows[1][3] = rgb1;
+
+		const PixelInt rgb2 = convertYUVToColor(clipTable, format, codebook.y[2], codebook.u, codebook.v);
+		rows[2][0] = rows[2][1] = rows[3][0] = rows[3][1] = rgb2;
+
+		const PixelInt rgb3 = convertYUVToColor(clipTable, format, codebook.y[3], codebook.u, codebook.v);
+		rows[2][2] = rows[2][3] = rows[3][2] = rows[3][3] = rgb3;
 	}
 
 	template<typename PixelInt>
 	static inline void decodeBlock4(const byte (&codebookIndex)[4], const CinepakStrip &strip, PixelInt *(&rows)[4], const byte *clipTable, const Graphics::PixelFormat &format) {
 		const CinepakCodebook &codebook1 = strip.v4_codebook[codebookIndex[0]];
-		putPixelRaw(rows[0] + 0, clipTable, format, codebook1.y[0], codebook1.u, codebook1.v);
-		putPixelRaw(rows[0] + 1, clipTable, format, codebook1.y[1], codebook1.u, codebook1.v);
-		putPixelRaw(rows[1] + 0, clipTable, format, codebook1.y[2], codebook1.u, codebook1.v);
-		putPixelRaw(rows[1] + 1, clipTable, format, codebook1.y[3], codebook1.u, codebook1.v);
+		rows[0][0] = convertYUVToColor(clipTable, format, codebook1.y[0], codebook1.u, codebook1.v);
+		rows[0][1] = convertYUVToColor(clipTable, format, codebook1.y[1], codebook1.u, codebook1.v);
+		rows[1][0] = convertYUVToColor(clipTable, format, codebook1.y[2], codebook1.u, codebook1.v);
+		rows[1][1] = convertYUVToColor(clipTable, format, codebook1.y[3], codebook1.u, codebook1.v);
 
 		const CinepakCodebook &codebook2 = strip.v4_codebook[codebookIndex[1]];
-		putPixelRaw(rows[0] + 2, clipTable, format, codebook2.y[0], codebook2.u, codebook2.v);
-		putPixelRaw(rows[0] + 3, clipTable, format, codebook2.y[1], codebook2.u, codebook2.v);
-		putPixelRaw(rows[1] + 2, clipTable, format, codebook2.y[2], codebook2.u, codebook2.v);
-		putPixelRaw(rows[1] + 3, clipTable, format, codebook2.y[3], codebook2.u, codebook2.v);
+		rows[0][2] = convertYUVToColor(clipTable, format, codebook2.y[0], codebook2.u, codebook2.v);
+		rows[0][3] = convertYUVToColor(clipTable, format, codebook2.y[1], codebook2.u, codebook2.v);
+		rows[1][2] = convertYUVToColor(clipTable, format, codebook2.y[2], codebook2.u, codebook2.v);
+		rows[1][3] = convertYUVToColor(clipTable, format, codebook2.y[3], codebook2.u, codebook2.v);
 
 		const CinepakCodebook &codebook3 = strip.v4_codebook[codebookIndex[2]];
-		putPixelRaw(rows[2] + 0, clipTable, format, codebook3.y[0], codebook3.u, codebook3.v);
-		putPixelRaw(rows[2] + 1, clipTable, format, codebook3.y[1], codebook3.u, codebook3.v);
-		putPixelRaw(rows[3] + 0, clipTable, format, codebook3.y[2], codebook3.u, codebook3.v);
-		putPixelRaw(rows[3] + 1, clipTable, format, codebook3.y[3], codebook3.u, codebook3.v);
+		rows[2][0] = convertYUVToColor(clipTable, format, codebook3.y[0], codebook3.u, codebook3.v);
+		rows[2][1] = convertYUVToColor(clipTable, format, codebook3.y[1], codebook3.u, codebook3.v);
+		rows[3][0] = convertYUVToColor(clipTable, format, codebook3.y[2], codebook3.u, codebook3.v);
+		rows[3][1] = convertYUVToColor(clipTable, format, codebook3.y[3], codebook3.u, codebook3.v);
 
 		const CinepakCodebook &codebook4 = strip.v4_codebook[codebookIndex[3]];
-		putPixelRaw(rows[2] + 2, clipTable, format, codebook4.y[0], codebook4.u, codebook4.v);
-		putPixelRaw(rows[2] + 3, clipTable, format, codebook4.y[1], codebook4.u, codebook4.v);
-		putPixelRaw(rows[3] + 2, clipTable, format, codebook4.y[2], codebook4.u, codebook4.v);
-		putPixelRaw(rows[3] + 3, clipTable, format, codebook4.y[3], codebook4.u, codebook4.v);
+		rows[2][2] = convertYUVToColor(clipTable, format, codebook4.y[0], codebook4.u, codebook4.v);
+		rows[2][3] = convertYUVToColor(clipTable, format, codebook4.y[1], codebook4.u, codebook4.v);
+		rows[3][2] = convertYUVToColor(clipTable, format, codebook4.y[2], codebook4.u, codebook4.v);
+		rows[3][3] = convertYUVToColor(clipTable, format, codebook4.y[3], codebook4.u, codebook4.v);
+	}
+};
+
+/**
+ * The default codebook converter for 8bpp: palettized output.
+ */
+struct CodebookConverterPalette {
+	static inline void decodeBlock1(byte codebookIndex, const CinepakStrip &strip, byte *(&rows)[4], const byte *clipTable, const Graphics::PixelFormat &format) {
+		const CinepakCodebook &codebook = strip.v1_codebook[codebookIndex];
+		rows[0][0] = rows[0][1] = rows[1][0] = rows[1][1] = codebook.y[0];
+		rows[0][2] = rows[0][3] = rows[1][2] = rows[1][3] = codebook.y[1];
+		rows[2][0] = rows[2][1] = rows[3][0] = rows[3][1] = codebook.y[2];
+		rows[2][2] = rows[2][3] = rows[3][2] = rows[3][3] = codebook.y[3];
+	}
+
+	static inline void decodeBlock4(const byte (&codebookIndex)[4], const CinepakStrip &strip, byte *(&rows)[4], const byte *clipTable, const Graphics::PixelFormat &format) {
+		const CinepakCodebook &codebook1 = strip.v4_codebook[codebookIndex[0]];
+		rows[0][0] = codebook1.y[0];
+		rows[0][1] = codebook1.y[1];
+		rows[1][0] = codebook1.y[2];
+		rows[1][1] = codebook1.y[3];
+
+		const CinepakCodebook &codebook2 = strip.v4_codebook[codebookIndex[1]];
+		rows[0][2] = codebook2.y[0];
+		rows[0][3] = codebook2.y[1];
+		rows[1][2] = codebook2.y[2];
+		rows[1][3] = codebook2.y[3];
+
+		const CinepakCodebook &codebook3 = strip.v4_codebook[codebookIndex[2]];
+		rows[2][0] = codebook3.y[0];
+		rows[2][1] = codebook3.y[1];
+		rows[3][0] = codebook3.y[2];
+		rows[3][1] = codebook3.y[3];
+
+		const CinepakCodebook &codebook4 = strip.v4_codebook[codebookIndex[3]];
+		rows[2][2] = codebook4.y[0];
+		rows[2][3] = codebook4.y[1];
+		rows[3][2] = codebook4.y[2];
+		rows[3][3] = codebook4.y[3];
 	}
 };
 
@@ -350,8 +366,10 @@ const Graphics::Surface *CinepakDecoder::decodeFrame(Common::SeekableReadStream
 			case 0x32:
 				if (_ditherPalette)
 					ditherVectors(stream, i, chunkID, chunkSize);
+				else if (_bitsPerPixel == 8)
+					decodeVectors8(stream, i, chunkID, chunkSize);
 				else
-					decodeVectors(stream, i, chunkID, chunkSize);
+					decodeVectors24(stream, i, chunkID, chunkSize);
 				break;
 			default:
 				warning("Unknown Cinepak chunk ID %02x", chunkID);
@@ -569,13 +587,15 @@ void CinepakDecoder::ditherCodebookVFW(uint16 strip, byte codebookType, uint16 c
 	}
 }
 
-void CinepakDecoder::decodeVectors(Common::SeekableReadStream &stream, uint16 strip, byte chunkID, uint32 chunkSize) {
-	if (_curFrame.surface->format.bytesPerPixel == 1) {
-		decodeVectorsTmpl<byte, CodebookConverterRaw>(_curFrame, _clipTable, stream, strip, chunkID, chunkSize);
-	} else if (_curFrame.surface->format.bytesPerPixel == 2) {
-		decodeVectorsTmpl<uint16, CodebookConverterRaw>(_curFrame, _clipTable, stream, strip, chunkID, chunkSize);
+void CinepakDecoder::decodeVectors8(Common::SeekableReadStream &stream, uint16 strip, byte chunkID, uint32 chunkSize) {
+	decodeVectorsTmpl<byte, CodebookConverterPalette>(_curFrame, _clipTable, stream, strip, chunkID, chunkSize);
+}
+
+void CinepakDecoder::decodeVectors24(Common::SeekableReadStream &stream, uint16 strip, byte chunkID, uint32 chunkSize) {
+	if (_curFrame.surface->format.bytesPerPixel == 2) {
+		decodeVectorsTmpl<uint16, CodebookConverterRGB>(_curFrame, _clipTable, stream, strip, chunkID, chunkSize);
 	} else if (_curFrame.surface->format.bytesPerPixel == 4) {
-		decodeVectorsTmpl<uint32, CodebookConverterRaw>(_curFrame, _clipTable, stream, strip, chunkID, chunkSize);
+		decodeVectorsTmpl<uint32, CodebookConverterRGB>(_curFrame, _clipTable, stream, strip, chunkID, chunkSize);
 	}
 }
 
diff --git a/image/codecs/cinepak.h b/image/codecs/cinepak.h
index f978a140ad8..bcad3eb24a2 100644
--- a/image/codecs/cinepak.h
+++ b/image/codecs/cinepak.h
@@ -96,7 +96,8 @@ private:
 
 	void initializeCodebook(uint16 strip, byte codebookType);
 	void loadCodebook(Common::SeekableReadStream &stream, uint16 strip, byte codebookType, byte chunkID, uint32 chunkSize);
-	void decodeVectors(Common::SeekableReadStream &stream, uint16 strip, byte chunkID, uint32 chunkSize);
+	void decodeVectors8(Common::SeekableReadStream &stream, uint16 strip, byte chunkID, uint32 chunkSize);
+	void decodeVectors24(Common::SeekableReadStream &stream, uint16 strip, byte chunkID, uint32 chunkSize);
 
 	byte findNearestRGB(int index) const;
 	void ditherVectors(Common::SeekableReadStream &stream, uint16 strip, byte chunkID, uint32 chunkSize);


Commit: 011e468fa12255f1f65a1d160c785dcb93801dfd
    https://github.com/scummvm/scummvm/commit/011e468fa12255f1f65a1d160c785dcb93801dfd
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2024-04-22T02:07:47+02:00

Commit Message:
IMAGE: Handle the surface pitch in Cinepak videos

Changed paths:
    image/codecs/cinepak.cpp


diff --git a/image/codecs/cinepak.cpp b/image/codecs/cinepak.cpp
index 4ebf77a6319..909c0af6f8e 100644
--- a/image/codecs/cinepak.cpp
+++ b/image/codecs/cinepak.cpp
@@ -61,47 +61,64 @@ inline uint16 createDitherTableIndex(const byte *clipTable, byte y, int8 u, int8
  */
 struct CodebookConverterRGB {
 	template<typename PixelInt>
-	static inline void decodeBlock1(byte codebookIndex, const CinepakStrip &strip, PixelInt *(&rows)[4], const byte *clipTable, const Graphics::PixelFormat &format) {
+	static inline void decodeBlock1(byte codebookIndex, const CinepakStrip &strip, PixelInt *dst, size_t dstPitch, const byte *clipTable, const Graphics::PixelFormat &format) {
 		const CinepakCodebook &codebook = strip.v1_codebook[codebookIndex];
+		const int8 u = codebook.u, v = codebook.v;
 
-		const PixelInt rgb0 = convertYUVToColor(clipTable, format, codebook.y[0], codebook.u, codebook.v);
-		rows[0][0] = rows[0][1] = rows[1][0] = rows[1][1] = rgb0;
+		const PixelInt rgb0 = convertYUVToColor(clipTable, format, codebook.y[0], u, v);
+		const PixelInt rgb1 = convertYUVToColor(clipTable, format, codebook.y[1], u, v);
 
-		const PixelInt rgb1 = convertYUVToColor(clipTable, format, codebook.y[1], codebook.u, codebook.v);
-		rows[0][2] = rows[0][3] = rows[1][2] = rows[1][3] = rgb1;
+		dst[0] = dst[1] = rgb0;
+		dst[2] = dst[3] = rgb1;
+		dst = (PixelInt *)((uint8 *)dst + dstPitch);
 
-		const PixelInt rgb2 = convertYUVToColor(clipTable, format, codebook.y[2], codebook.u, codebook.v);
-		rows[2][0] = rows[2][1] = rows[3][0] = rows[3][1] = rgb2;
+		dst[0] = dst[1] = rgb0;
+		dst[2] = dst[3] = rgb1;
+		dst = (PixelInt *)((uint8 *)dst + dstPitch);
 
-		const PixelInt rgb3 = convertYUVToColor(clipTable, format, codebook.y[3], codebook.u, codebook.v);
-		rows[2][2] = rows[2][3] = rows[3][2] = rows[3][3] = rgb3;
+		const PixelInt rgb2 = convertYUVToColor(clipTable, format, codebook.y[2], u, v);
+		const PixelInt rgb3 = convertYUVToColor(clipTable, format, codebook.y[3], u, v);
+
+		dst[0] = dst[1] = rgb2;
+		dst[2] = dst[3] = rgb3;
+		dst = (PixelInt *)((uint8 *)dst + dstPitch);
+
+		dst[0] = dst[1] = rgb2;
+		dst[2] = dst[3] = rgb3;
+		dst = (PixelInt *)((uint8 *)dst + dstPitch);
 	}
 
 	template<typename PixelInt>
-	static inline void decodeBlock4(const byte (&codebookIndex)[4], const CinepakStrip &strip, PixelInt *(&rows)[4], const byte *clipTable, const Graphics::PixelFormat &format) {
+	static inline void decodeBlock4(const byte (&codebookIndex)[4], const CinepakStrip &strip, PixelInt *dst, size_t dstPitch, const byte *clipTable, const Graphics::PixelFormat &format) {
 		const CinepakCodebook &codebook1 = strip.v4_codebook[codebookIndex[0]];
-		rows[0][0] = convertYUVToColor(clipTable, format, codebook1.y[0], codebook1.u, codebook1.v);
-		rows[0][1] = convertYUVToColor(clipTable, format, codebook1.y[1], codebook1.u, codebook1.v);
-		rows[1][0] = convertYUVToColor(clipTable, format, codebook1.y[2], codebook1.u, codebook1.v);
-		rows[1][1] = convertYUVToColor(clipTable, format, codebook1.y[3], codebook1.u, codebook1.v);
-
 		const CinepakCodebook &codebook2 = strip.v4_codebook[codebookIndex[1]];
-		rows[0][2] = convertYUVToColor(clipTable, format, codebook2.y[0], codebook2.u, codebook2.v);
-		rows[0][3] = convertYUVToColor(clipTable, format, codebook2.y[1], codebook2.u, codebook2.v);
-		rows[1][2] = convertYUVToColor(clipTable, format, codebook2.y[2], codebook2.u, codebook2.v);
-		rows[1][3] = convertYUVToColor(clipTable, format, codebook2.y[3], codebook2.u, codebook2.v);
 
-		const CinepakCodebook &codebook3 = strip.v4_codebook[codebookIndex[2]];
-		rows[2][0] = convertYUVToColor(clipTable, format, codebook3.y[0], codebook3.u, codebook3.v);
-		rows[2][1] = convertYUVToColor(clipTable, format, codebook3.y[1], codebook3.u, codebook3.v);
-		rows[3][0] = convertYUVToColor(clipTable, format, codebook3.y[2], codebook3.u, codebook3.v);
-		rows[3][1] = convertYUVToColor(clipTable, format, codebook3.y[3], codebook3.u, codebook3.v);
+		dst[0] = convertYUVToColor(clipTable, format, codebook1.y[0], codebook1.u, codebook1.v);
+		dst[1] = convertYUVToColor(clipTable, format, codebook1.y[1], codebook1.u, codebook1.v);
+		dst[2] = convertYUVToColor(clipTable, format, codebook2.y[0], codebook2.u, codebook2.v);
+		dst[3] = convertYUVToColor(clipTable, format, codebook2.y[1], codebook2.u, codebook2.v);
+		dst = (PixelInt *)((uint8 *)dst + dstPitch);
+
+		dst[0] = convertYUVToColor(clipTable, format, codebook1.y[2], codebook1.u, codebook1.v);
+		dst[1] = convertYUVToColor(clipTable, format, codebook1.y[3], codebook1.u, codebook1.v);
+		dst[2] = convertYUVToColor(clipTable, format, codebook2.y[2], codebook2.u, codebook2.v);
+		dst[3] = convertYUVToColor(clipTable, format, codebook2.y[3], codebook2.u, codebook2.v);
+		dst = (PixelInt *)((uint8 *)dst + dstPitch);
 
+		const CinepakCodebook &codebook3 = strip.v4_codebook[codebookIndex[2]];
 		const CinepakCodebook &codebook4 = strip.v4_codebook[codebookIndex[3]];
-		rows[2][2] = convertYUVToColor(clipTable, format, codebook4.y[0], codebook4.u, codebook4.v);
-		rows[2][3] = convertYUVToColor(clipTable, format, codebook4.y[1], codebook4.u, codebook4.v);
-		rows[3][2] = convertYUVToColor(clipTable, format, codebook4.y[2], codebook4.u, codebook4.v);
-		rows[3][3] = convertYUVToColor(clipTable, format, codebook4.y[3], codebook4.u, codebook4.v);
+
+		dst[0] = convertYUVToColor(clipTable, format, codebook3.y[0], codebook3.u, codebook3.v);
+		dst[1] = convertYUVToColor(clipTable, format, codebook3.y[1], codebook3.u, codebook3.v);
+		dst[2] = convertYUVToColor(clipTable, format, codebook4.y[0], codebook4.u, codebook4.v);
+		dst[3] = convertYUVToColor(clipTable, format, codebook4.y[1], codebook4.u, codebook4.v);
+		dst = (PixelInt *)((uint8 *)dst + dstPitch);
+
+		dst[0] = convertYUVToColor(clipTable, format, codebook3.y[2], codebook3.u, codebook3.v);
+		dst[1] = convertYUVToColor(clipTable, format, codebook3.y[3], codebook3.u, codebook3.v);
+		dst[2] = convertYUVToColor(clipTable, format, codebook4.y[2], codebook4.u, codebook4.v);
+		dst[3] = convertYUVToColor(clipTable, format, codebook4.y[3], codebook4.u, codebook4.v);
+		dst = (PixelInt *)((uint8 *)dst + dstPitch);
 	}
 };
 
@@ -109,38 +126,59 @@ struct CodebookConverterRGB {
  * The default codebook converter for 8bpp: palettized output.
  */
 struct CodebookConverterPalette {
-	static inline void decodeBlock1(byte codebookIndex, const CinepakStrip &strip, byte *(&rows)[4], const byte *clipTable, const Graphics::PixelFormat &format) {
+	static inline void decodeBlock1(byte codebookIndex, const CinepakStrip &strip, byte *dst, size_t dstPitch, const byte *clipTable, const Graphics::PixelFormat &format) {
 		const CinepakCodebook &codebook = strip.v1_codebook[codebookIndex];
-		rows[0][0] = rows[0][1] = rows[1][0] = rows[1][1] = codebook.y[0];
-		rows[0][2] = rows[0][3] = rows[1][2] = rows[1][3] = codebook.y[1];
-		rows[2][0] = rows[2][1] = rows[3][0] = rows[3][1] = codebook.y[2];
-		rows[2][2] = rows[2][3] = rows[3][2] = rows[3][3] = codebook.y[3];
+
+		byte y0 = codebook.y[0], y1 = codebook.y[1];
+		byte y2 = codebook.y[2], y3 = codebook.y[3];
+
+		dst[0] = dst[1] = y0;
+		dst[2] = dst[3] = y1;
+		dst += dstPitch;
+
+		dst[0] = dst[1] = y0;
+		dst[2] = dst[3] = y1;
+		dst += dstPitch;
+
+		dst[0] = dst[1] = y2;
+		dst[2] = dst[3] = y3;
+		dst += dstPitch;
+
+		dst[0] = dst[1] = y2;
+		dst[2] = dst[3] = y3;
+		dst += dstPitch;
 	}
 
-	static inline void decodeBlock4(const byte (&codebookIndex)[4], const CinepakStrip &strip, byte *(&rows)[4], const byte *clipTable, const Graphics::PixelFormat &format) {
+	static inline void decodeBlock4(const byte (&codebookIndex)[4], const CinepakStrip &strip, byte *dst, size_t dstPitch, const byte *clipTable, const Graphics::PixelFormat &format) {
 		const CinepakCodebook &codebook1 = strip.v4_codebook[codebookIndex[0]];
-		rows[0][0] = codebook1.y[0];
-		rows[0][1] = codebook1.y[1];
-		rows[1][0] = codebook1.y[2];
-		rows[1][1] = codebook1.y[3];
-
 		const CinepakCodebook &codebook2 = strip.v4_codebook[codebookIndex[1]];
-		rows[0][2] = codebook2.y[0];
-		rows[0][3] = codebook2.y[1];
-		rows[1][2] = codebook2.y[2];
-		rows[1][3] = codebook2.y[3];
 
-		const CinepakCodebook &codebook3 = strip.v4_codebook[codebookIndex[2]];
-		rows[2][0] = codebook3.y[0];
-		rows[2][1] = codebook3.y[1];
-		rows[3][0] = codebook3.y[2];
-		rows[3][1] = codebook3.y[3];
+		dst[0] = codebook1.y[0];
+		dst[1] = codebook1.y[1];
+		dst[2] = codebook2.y[0];
+		dst[3] = codebook2.y[1];
+		dst += dstPitch;
+
+		dst[0] = codebook1.y[2];
+		dst[1] = codebook1.y[3];
+		dst[2] = codebook2.y[2];
+		dst[3] = codebook2.y[3];
+		dst += dstPitch;
 
+		const CinepakCodebook &codebook3 = strip.v4_codebook[codebookIndex[2]];
 		const CinepakCodebook &codebook4 = strip.v4_codebook[codebookIndex[3]];
-		rows[2][2] = codebook4.y[0];
-		rows[2][3] = codebook4.y[1];
-		rows[3][2] = codebook4.y[2];
-		rows[3][3] = codebook4.y[3];
+
+		dst[0] = codebook3.y[0];
+		dst[1] = codebook3.y[1];
+		dst[2] = codebook4.y[0];
+		dst[3] = codebook4.y[1];
+		dst += dstPitch;
+
+		dst[0] = codebook3.y[2];
+		dst[1] = codebook3.y[3];
+		dst[2] = codebook4.y[2];
+		dst[3] = codebook4.y[3];
+		dst += dstPitch;
 	}
 };
 
@@ -148,44 +186,55 @@ struct CodebookConverterPalette {
  * Codebook converter that dithers in QT-style or VFW-style
  */
 struct CodebookConverterDithered {
-	static inline void decodeBlock1(byte codebookIndex, const CinepakStrip &strip, byte *(&rows)[4], const byte *clipTable, const Graphics::PixelFormat &format) {
+	static inline void decodeBlock1(byte codebookIndex, const CinepakStrip &strip, byte *dst, size_t dstPitch, const byte *clipTable, const Graphics::PixelFormat &format) {
 		const uint32 *colorPtr = (const uint32 *)(strip.v1_dither + codebookIndex);
-		*((uint32 *)rows[0]) = colorPtr[0];
-		*((uint32 *)rows[1]) = colorPtr[256];
-		*((uint32 *)rows[2]) = colorPtr[512];
-		*((uint32 *)rows[3]) = colorPtr[768];
+
+		*((uint32 *)dst) = colorPtr[0];
+		dst += dstPitch;
+
+		*((uint32 *)dst) = colorPtr[256];
+		dst += dstPitch;
+
+		*((uint32 *)dst) = colorPtr[512];
+		dst += dstPitch;
+
+		*((uint32 *)dst) = colorPtr[768];
+		dst += dstPitch;
 	}
 
-	static inline void decodeBlock4(const byte (&codebookIndex)[4], const CinepakStrip &strip, byte *(&rows)[4], const byte *clipTable, const Graphics::PixelFormat &format) {
-		const uint16 *colorPtr = (const uint16 *)(strip.v4_dither + codebookIndex[0]);
-		*((uint16 *)(rows[0] + 0)) = colorPtr[0];
-		*((uint16 *)(rows[1] + 0)) = colorPtr[1];
+	static inline void decodeBlock4(const byte (&codebookIndex)[4], const CinepakStrip &strip, byte *dst, size_t dstPitch, const byte *clipTable, const Graphics::PixelFormat &format) {
+		const uint16 *colorPtr1 = (const uint16 *)(strip.v4_dither + codebookIndex[0]);
+		const uint16 *colorPtr2 = (const uint16 *)(strip.v4_dither + codebookIndex[1]);
+
+		*((uint16 *)(dst + 0)) = colorPtr1[0];
+		*((uint16 *)(dst + 2)) = colorPtr2[512];
+		dst += dstPitch;
+
+		*((uint16 *)(dst + 0)) = colorPtr1[1];
+		*((uint16 *)(dst + 2)) = colorPtr2[513];
+		dst += dstPitch;
 
-		colorPtr = (const uint16 *)(strip.v4_dither + codebookIndex[1]);
-		*((uint16 *)(rows[0] + 2)) = colorPtr[512];
-		*((uint16 *)(rows[1] + 2)) = colorPtr[513];
+		const uint16 *colorPtr3 = (const uint16 *)(strip.v4_dither + codebookIndex[2]);
+		const uint16 *colorPtr4 = (const uint16 *)(strip.v4_dither + codebookIndex[3]);
 
-		colorPtr = (const uint16 *)(strip.v4_dither + codebookIndex[2]);
-		*((uint16 *)(rows[2] + 0)) = colorPtr[1024];
-		*((uint16 *)(rows[3] + 0)) = colorPtr[1025];
+		*((uint16 *)(dst + 0)) = colorPtr3[1024];
+		*((uint16 *)(dst + 2)) = colorPtr4[1536];
+		dst += dstPitch;
 
-		colorPtr = (const uint16 *)(strip.v4_dither + codebookIndex[3]);
-		*((uint16 *)(rows[2] + 2)) = colorPtr[1536];
-		*((uint16 *)(rows[3] + 2)) = colorPtr[1537];
+		*((uint16 *)(dst + 0)) = colorPtr3[1025];
+		*((uint16 *)(dst + 2)) = colorPtr4[1537];
+		dst += dstPitch;
 	}
 };
 
 template<typename PixelInt, typename CodebookConverter>
 void decodeVectorsTmpl(CinepakFrame &frame, const byte *clipTable, Common::SeekableReadStream &stream, uint16 strip, byte chunkID, uint32 chunkSize) {
 	uint32 flag = 0, mask = 0;
-	PixelInt *iy[4];
 	int32 startPos = stream.pos();
+	PixelInt *dst;
 
 	for (uint16 y = frame.strips[strip].rect.top; y < frame.strips[strip].rect.bottom; y += 4) {
-		iy[0] = (PixelInt *)frame.surface->getBasePtr(frame.strips[strip].rect.left, + y);
-		iy[1] = iy[0] + frame.width;
-		iy[2] = iy[1] + frame.width;
-		iy[3] = iy[2] + frame.width;
+		dst = (PixelInt *)frame.surface->getBasePtr(frame.strips[strip].rect.left, + y);
 
 		for (uint16 x = frame.strips[strip].rect.left; x < frame.strips[strip].rect.right; x += 4) {
 			if ((chunkID & 0x01) && !(mask >>= 1)) {
@@ -211,19 +260,18 @@ void decodeVectorsTmpl(CinepakFrame &frame, const byte *clipTable, Common::Seeka
 
 					// Get the codebook
 					byte codebook = stream.readByte();
-					CodebookConverter::decodeBlock1(codebook, frame.strips[strip], iy, clipTable, frame.surface->format);
+					CodebookConverter::decodeBlock1(codebook, frame.strips[strip], dst, frame.surface->pitch, clipTable, frame.surface->format);
 				} else if (flag & mask) {
 					if ((stream.pos() - startPos + 4) > (int32)chunkSize)
 						return;
 
 					byte codebook[4];
 					stream.read(codebook, 4);
-					CodebookConverter::decodeBlock4(codebook, frame.strips[strip], iy, clipTable, frame.surface->format);
+					CodebookConverter::decodeBlock4(codebook, frame.strips[strip], dst, frame.surface->pitch, clipTable, frame.surface->format);
 				}
 			}
 
-			for (byte i = 0; i < 4; i++)
-				iy[i] += 4;
+			dst += 4;
 		}
 	}
 }


Commit: 604708ad9897d2eeb687982c63e46bc8c2fc7ad8
    https://github.com/scummvm/scummvm/commit/604708ad9897d2eeb687982c63e46bc8c2fc7ad8
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2024-04-22T02:07:47+02:00

Commit Message:
IMAGE: Combine lookup tables for Cinepak with VFW dithering

Changed paths:
    image/codecs/cinepak.cpp


diff --git a/image/codecs/cinepak.cpp b/image/codecs/cinepak.cpp
index 909c0af6f8e..d7c5dd8e656 100644
--- a/image/codecs/cinepak.cpp
+++ b/image/codecs/cinepak.cpp
@@ -550,7 +550,7 @@ void CinepakDecoder::ditherCodebookQT(uint16 strip, byte codebookType, uint16 co
 }
 
 static inline byte getRGBLookupEntry(const byte *colorMap, uint16 index) {
-	return colorMap[s_defaultPaletteLookup[CLIP<int>(index, 0, 1023)]];
+	return colorMap[CLIP<int>(index, 0, 1023)];
 }
 
 void CinepakDecoder::ditherCodebookVFW(uint16 strip, byte codebookType, uint16 codebookIndex) {
@@ -673,10 +673,10 @@ void CinepakDecoder::setDither(DitherType type, const byte *palette) {
 	_ditherType = type;
 
 	if (type == kDitherTypeVFW) {
-		_colorMap = new byte[221];
+		_colorMap = new byte[1024];
 
-		for (int i = 0; i < 221; i++)
-			_colorMap[i] = findNearestRGB(i);
+		for (int i = 0; i < 1024; i++)
+			_colorMap[i] = findNearestRGB(s_defaultPaletteLookup[i]);
 	} else {
 		// Generate QuickTime dither table
 		// 4 blocks of 0x4000 bytes (RGB554 lookup)




More information about the Scummvm-git-logs mailing list