private void DrawPixels(ClutDefinitionSegment cds, int pixelCode, int runLength, ref int x, ref int y) { var c = Color.Red; if (cds != null) { foreach (var item in cds.Entries) { if (item.ClutEntryId == pixelCode) { c = item.GetColor(); break; } } } for (int k = 0; k < runLength; k++) { if (y < _fastImage.Height && x < _fastImage.Width) { _fastImage.SetPixel(x, y, c); } x++; } }
public Bitmap GetImage(ObjectDataSegment ods) { if (SubtitleSegments == null) { ParseSegments(); } if (ods.Image != null) { return(ods.Image); } int width = 720; int height = 576; ClutDefinitionSegment cds = GetClutDefinitionSegment(ods); var segments = SubtitleSegments; foreach (SubtitleSegment ss in segments) { if (ss.DisplayDefinition != null) { width = ss.DisplayDefinition.DisplayWith; height = ss.DisplayDefinition.DisplayHeight; } } if (ods == null) { return(new Bitmap(1, 1)); } ods.DecodeImage(DataBuffer, ods.BufferIndex, cds); return(ods.Image); }
public SubtitleSegment(byte[] buffer, int index) { if (buffer == null || buffer.Length < 7) { return; } SyncByte = buffer[index]; SegmentType = buffer[index + 1]; PageId = Helper.GetEndianWord(buffer, index + 2); SegmentLength = Helper.GetEndianWord(buffer, index + 4); if (buffer.Length - 6 < SegmentLength) { return; } if (index + 6 + SegmentLength > buffer.Length) { return; } IsValid = true; switch (SegmentType) { case PageCompositionSegment: PageComposition = new PageCompositionSegment(buffer, index + 6, SegmentLength - 2); break; case RegionCompositionSegment: RegionComposition = new RegionCompositionSegment(buffer, index + 6, SegmentLength - 10); break; case ClutDefinitionSegment: ClutDefinition = new ClutDefinitionSegment(buffer, index + 6, SegmentLength); break; case ObjectDataSegment: ObjectData = new ObjectDataSegment(buffer, index + 6); break; case DisplayDefinitionSegment: DisplayDefinition = new DisplayDefinitionSegment(buffer, index + 6); break; case EndOfDisplaySetSegment: break; } }
public void ParseSegments() { if (SubtitleSegments != null) { return; } SubtitleSegments = new List <SubtitleSegment>(); ClutDefinitions = new List <ClutDefinitionSegment>(); RegionCompositions = new List <RegionCompositionSegment>(); PageCompositions = new List <PageCompositionSegment>(); ObjectDataList = new List <ObjectDataSegment>(); int index = 2; var ss = new SubtitleSegment(DataBuffer, index); ClutDefinitionSegment cds = null; while (ss.SyncByte == Helper.B00001111) { SubtitleSegments.Add(ss); if (ss.ClutDefinition != null) { cds = ss.ClutDefinition; ClutDefinitions.Add(ss.ClutDefinition); } else if (ss.RegionComposition != null) { RegionCompositions.Add(ss.RegionComposition); } else if (ss.PageComposition != null) { PageCompositions.Add(ss.PageComposition); } else if (ss.ObjectData != null) { ObjectDataList.Add(ss.ObjectData); } index += 6 + ss.SegmentLength; if (index + 6 < DataBuffer.Length) { ss = new SubtitleSegment(DataBuffer, index); } else { ss.SyncByte = Helper.B11111111; } } }
public Bitmap GetImage(ObjectDataSegment ods) { if (SubtitleSegments == null) { ParseSegments(); } if (ods.Image != null) { return(ods.Image); } ClutDefinitionSegment cds = GetClutDefinitionSegment(ods); ods.DecodeImage(_dataBuffer, ods.BufferIndex, cds); return(ods.Image); }
public SubtitleSegment(byte[] buffer, int index) { if (buffer == null || buffer.Length < 7) return; SyncByte = buffer[index]; SegmentType = buffer[index + 1]; PageId = Helper.GetEndianWord(buffer, index + 2); SegmentLength = Helper.GetEndianWord(buffer, index + 4); if (buffer.Length - 6 < SegmentLength) return; if (index + 6 + SegmentLength > buffer.Length) return; IsValid = true; switch (SegmentType) { case PageCompositionSegment: PageComposition = new PageCompositionSegment(buffer, index + 6, SegmentLength-2); break; case RegionCompositionSegment: RegionComposition = new RegionCompositionSegment(buffer, index + 6, SegmentLength-10); break; case ClutDefinitionSegment: ClutDefinition = new ClutDefinitionSegment(buffer, index + 6, SegmentLength); break; case ObjectDataSegment: ObjectData = new ObjectDataSegment(buffer, index + 6); break; case DisplayDefinitionSegment: DisplayDefinition = new DisplayDefinitionSegment(buffer, index + 6); break; case EndOfDisplaySetSegment: break; } }
public void DecodeImage(byte[] buffer, int index, ClutDefinitionSegment cds) { switch (ObjectCodingMethod) { case 0: var twoToFourBitColorLookup = new List<int> { 0, 1, 2, 3 }; var twoToEightBitColorLookup = new List<int> { 0, 1, 2, 3 }; var fourToEightBitColorLookup = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; int pixelCode = 0; int runLength = 0; int dataType = buffer[index + 7]; int length = TopFieldDataBlockLength; index += 8; int start = index; int x = 0; int y = 0; // Pre-decoding to determine image size int width = 0; while (index < start + TopFieldDataBlockLength) { index = CalculateSize(buffer, index, ref dataType, start, ref x, ref y, length, ref runLength, ref width); } if (width > 2000) { width = 2000; } if (y > 500) { y = 500; } Image = new Bitmap(width, y + 1); fastImage = new FastBitmap(Image); fastImage.LockImage(); x = 0; y = 0; index = start; while (index < start + TopFieldDataBlockLength) { index = ProcessDataType(buffer, index, cds, ref dataType, start, twoToFourBitColorLookup, fourToEightBitColorLookup, twoToEightBitColorLookup, ref x, ref y, length, ref pixelCode, ref runLength); } x = 0; y = 1; if (BottomFieldDataBlockLength == 0) { index = start; } else { length = BottomFieldDataBlockLength; index = start + TopFieldDataBlockLength; start = index; } dataType = buffer[index - 1]; while (index < start + BottomFieldDataBlockLength - 1) { index = ProcessDataType(buffer, index, cds, ref dataType, start, twoToFourBitColorLookup, fourToEightBitColorLookup, twoToEightBitColorLookup, ref x, ref y, length, ref pixelCode, ref runLength); } fastImage.UnlockImage(); break; case 1: Image = new Bitmap(1, 1); NumberOfCodes = buffer[index + 3]; break; } }
private int ProcessDataType(byte[] buffer, int index, ClutDefinitionSegment cds, ref int dataType, int start, List<int> twoToFourBitColorLookup, List<int> fourToEightBitColorLookup, List<int> twoToEightBitColorLookup, ref int x, ref int y, int length, ref int pixelCode, ref int runLength) { switch (dataType) { case PixelDecoding2Bit: int bitIndex = 0; while (index < start + length - 1 && TwoBitPixelDecoding(buffer, ref index, ref bitIndex, out pixelCode, out runLength)) { DrawPixels(cds, twoToFourBitColorLookup[pixelCode], runLength, ref x, ref y); } break; case PixelDecoding4Bit: bool startHalf = false; while (index < start + length - 1 && FourBitPixelDecoding(buffer, ref index, ref startHalf, out pixelCode, out runLength)) { DrawPixels(cds, fourToEightBitColorLookup[pixelCode], runLength, ref x, ref y); } break; case PixelDecoding8Bit: while (index < start + length - 1 && EightBitPixelDecoding(buffer, ref index, out pixelCode, out runLength)) { DrawPixels(cds, pixelCode, runLength, ref x, ref y); } break; case MapTable2To4Bit: //4 entry numbers of 4-bits each; entry number 0 first, entry number 3 last twoToFourBitColorLookup[0] = buffer[index] >> 4; twoToFourBitColorLookup[1] = buffer[index] & Helper.B00001111; index++; twoToFourBitColorLookup[2] = buffer[index] >> 4; twoToFourBitColorLookup[3] = buffer[index] & Helper.B00001111; index++; break; case MapTable2To8Bit: //4 entry numbers of 8-bits each; entry number 0 first, entry number 3 last twoToEightBitColorLookup[0] = buffer[index]; index++; twoToEightBitColorLookup[1] = buffer[index]; index++; twoToEightBitColorLookup[2] = buffer[index]; index++; twoToEightBitColorLookup[3] = buffer[index]; index++; break; case MapTable4To8Bit: // 16 entry numbers of 8-bits each for (int k = 0; k < 16; k++) { fourToEightBitColorLookup[k] = buffer[index]; index++; } break; case EndOfObjectLineCode: x = 0; y += 2; // interlaced - skip one line break; } if (index >= start + length) { return index; } dataType = buffer[index]; index++; return index; }
private void DrawPixels(ClutDefinitionSegment cds, int pixelCode, int runLength, ref int x, ref int y) { var c = Color.Red; if (cds != null) { foreach (var item in cds.Entries) { if (item.ClutEntryId != pixelCode) { continue; } c = item.GetColor(); break; } } for (int k = 0; k < runLength; k++) { if (y < fastImage.Height && x < fastImage.Width) { fastImage.SetPixel(x, y, c); } x++; } }
public void DecodeImage(byte[] buffer, int index, ClutDefinitionSegment cds) { if (ObjectCodingMethod == 0) { var twoToFourBitColorLookup = new List <int> { 0, 1, 2, 3 }; var twoToEightBitColorLookup = new List <int> { 0, 1, 2, 3 }; var fourToEightBitColorLookup = new List <int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; int pixelCode = 0; int runLength = 0; int dataType = buffer[index + 7]; int length = TopFieldDataBlockLength; index += 8; int start = index; int x = 0; int y = 0; // Pre-decoding to determine image size int width = 0; while (index < start + TopFieldDataBlockLength) { index = CalculateSize(buffer, index, ref dataType, start, ref x, ref y, length, ref runLength, ref width); } if (width > 2000) { width = 2000; } if (y > 500) { y = 500; } Image = new Bitmap(width, y + 1); _fastImage = new FastBitmap(Image); _fastImage.LockImage(); x = 0; y = 0; index = start; while (index < start + TopFieldDataBlockLength) { index = ProcessDataType(buffer, index, cds, ref dataType, start, twoToFourBitColorLookup, fourToEightBitColorLookup, twoToEightBitColorLookup, ref x, ref y, length, ref pixelCode, ref runLength); } x = 0; y = 1; if (BottomFieldDataBlockLength == 0) { index = start; } else { length = BottomFieldDataBlockLength; index = start + TopFieldDataBlockLength; start = index; } dataType = buffer[index - 1]; while (index < start + BottomFieldDataBlockLength - 1) { index = ProcessDataType(buffer, index, cds, ref dataType, start, twoToFourBitColorLookup, fourToEightBitColorLookup, twoToEightBitColorLookup, ref x, ref y, length, ref pixelCode, ref runLength); } _fastImage.UnlockImage(); } else if (ObjectCodingMethod == 1) { Image = new Bitmap(1, 1); NumberOfCodes = buffer[index + 3]; } }
private int ProcessDataType(byte[] buffer, int index, ClutDefinitionSegment cds, ref int dataType, int start, List <int> twoToFourBitColorLookup, List <int> fourToEightBitColorLookup, List <int> twoToEightBitColorLookup, ref int x, ref int y, int length, ref int pixelCode, ref int runLength) { if (dataType == PixelDecoding2Bit) { int bitIndex = 0; while (index < start + length - 1 && TwoBitPixelDecoding(buffer, ref index, ref bitIndex, out pixelCode, out runLength)) { DrawPixels(cds, twoToFourBitColorLookup[pixelCode], runLength, ref x, ref y); } } else if (dataType == PixelDecoding4Bit) { bool startHalf = false; while (index < start + length - 1 && FourBitPixelDecoding(buffer, ref index, ref startHalf, out pixelCode, out runLength)) { DrawPixels(cds, fourToEightBitColorLookup[pixelCode], runLength, ref x, ref y); } } else if (dataType == PixelDecoding8Bit) { while (index < start + length - 1 && EightBitPixelDecoding(buffer, ref index, out pixelCode, out runLength)) { DrawPixels(cds, pixelCode, runLength, ref x, ref y); } } else if (dataType == MapTable2To4Bit) { //4 entry numbers of 4-bits each; entry number 0 first, entry number 3 last twoToFourBitColorLookup[0] = buffer[index] >> 4; twoToFourBitColorLookup[1] = buffer[index] & Helper.B00001111; index++; twoToFourBitColorLookup[2] = buffer[index] >> 4; twoToFourBitColorLookup[3] = buffer[index] & Helper.B00001111; index++; } else if (dataType == MapTable2To8Bit) { //4 entry numbers of 8-bits each; entry number 0 first, entry number 3 last twoToEightBitColorLookup[0] = buffer[index]; index++; twoToEightBitColorLookup[1] = buffer[index]; index++; twoToEightBitColorLookup[2] = buffer[index]; index++; twoToEightBitColorLookup[3] = buffer[index]; index++; } else if (dataType == MapTable4To8Bit) { // 16 entry numbers of 8-bits each for (int k = 0; k < 16; k++) { fourToEightBitColorLookup[k] = buffer[index]; index++; } } else if (dataType == EndOfObjectLineCode) { x = 0; y += 2; // interlaced - skip one line } if (index < start + length) { dataType = buffer[index]; index++; } return(index); }