public static Clip ReadClip(ChunkReader reader) { // index var index = reader.ReadUInt32(); // first subchunk header var type = reader.ReadID<ClipType>(); var subchunk_size = reader.ReadUInt16(); subchunk_size += (ushort)(subchunk_size & 1); Clip clip = null; using (var subChunkReader = reader.GetSubChunk(subchunk_size)) { switch (type) { case ClipType.ID_STIL: { var tmp_clip = new ClipStill(index); tmp_clip.Name = subChunkReader.ReadString(); clip = tmp_clip; break; } case ClipType.ID_ISEQ: { var tmp_clip = new ClipSequence(index); tmp_clip.Digits = subChunkReader.ReadUInt8(); tmp_clip.Flags = subChunkReader.ReadUInt8(); tmp_clip.Offset = subChunkReader.ReadSInt16(); subChunkReader.ReadUInt16(); // Legacy Cruft: Nothing to see here tmp_clip.Start = subChunkReader.ReadSInt16(); tmp_clip.End = subChunkReader.ReadSInt16(); tmp_clip.Prefix = subChunkReader.ReadString(); tmp_clip.Suffix = subChunkReader.ReadString(); clip = tmp_clip; break; } case ClipType.ID_ANIM: { var tmp_clip = new ClipAnim(index); tmp_clip.Name = subChunkReader.ReadString(); tmp_clip.Server = subChunkReader.ReadString(); tmp_clip.Data = subChunkReader.ReadBytes((uint)subChunkReader.BytesLeft); clip = tmp_clip; break; } case ClipType.ID_XREF: { var tmp_clip = new ClipCloned(index); tmp_clip.clip_reference_index = subChunkReader.ReadUInt32(); tmp_clip.Name = subChunkReader.ReadString(); clip = tmp_clip; break; } case ClipType.ID_STCC: { var tmp_clip = new ClipColorCycle(index); tmp_clip.lo = subChunkReader.ReadSInt16(); tmp_clip.hi = subChunkReader.ReadSInt16(); tmp_clip.Name = subChunkReader.ReadString(); clip = tmp_clip; break; } default: throw new Exception("Unknown Clip type"); // TODO: create proper exception class for this ... } } while (reader.BytesLeft > 0) { // process subchunks as they're encountered var id = reader.ReadID<ClipDataType>(); subchunk_size = reader.ReadUInt16(); subchunk_size += (ushort)(subchunk_size & 1); using (var subChunkReader = reader.GetSubChunk(subchunk_size)) { switch (id) { //case ClipDataType.ID_CLRS: // Color Space RGB - CLRS { flags[U2], colorspace[U2], filename[FNAM0] } //case ClipDataType.ID_CLRA: // Color Space Alpha - CLRA { flags[U2], colorspace[U2], filename[FNAM0] } //case ClipDataType.ID_FILT: // Image Filtering - FILT { flags[U2] } //case ClipDataType.ID_DITH: // Image Dithering - DITH { flags[U2] } // Contrast - CONT { contrast-delta[FP4], envelope[VX] } case ClipDataType.ID_CONT: { clip.Contrast.value = subChunkReader.ReadSingle(); clip.Contrast.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; } // Brightness - BRIT { brightness-delta[FP4], envelope[VX] } case ClipDataType.ID_BRIT: { clip.Brightness.value = subChunkReader.ReadSingle(); clip.Brightness.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; } // Saturation - SATR { saturation-delta[FP4], envelope[VX] } case ClipDataType.ID_SATR: { clip.Saturation.value = subChunkReader.ReadSingle(); clip.Saturation.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; } // Hue - HUE { hue-rotation[FP4], envelope[VX] } case ClipDataType.ID_HUE: { clip.Hue.value = subChunkReader.ReadSingle(); clip.Hue.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; } // Gamma Correction - GAMM { gamma[F4], envelope[VX] } case ClipDataType.ID_GAMM: { clip.Gamma.value = subChunkReader.ReadSingle(); clip.Gamma.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; } // Negative - NEGA { enable[U2] } case ClipDataType.ID_NEGA: { clip.Negative = subChunkReader.ReadUInt16() != 0; break; } // Time - TIME { start-time[FP4], duration[FP4], frame-rate[FP4] } case ClipDataType.ID_TIME: { clip.StartTime = subChunkReader.ReadSingle(); clip.Duration = subChunkReader.ReadSingle(); clip.FrameRate = subChunkReader.ReadSingle(); break; } // Plug-in Image Filters - IFLT { server-name[S0], flags[U2], data[...] } case ClipDataType.ID_IFLT: // Plug-in Pixel Filters - PFLT { server-name[S0], flags[U2], data[...] } case ClipDataType.ID_PFLT: { var filt = new LightwavePlugin(); filt.name = subChunkReader.ReadString(); filt.flags = subChunkReader.ReadUInt16(); filt.data = subChunkReader.ReadBytes((uint)subChunkReader.BytesLeft); if (id == ClipDataType.ID_IFLT) clip.ImageFilters.Add(filt); else clip.PixelFilters.Add(filt); break; } case ClipDataType.ID_FLAG: // not mentioned in documentation ... var flags = subChunkReader.ReadUInt16(); // unknown what they mean ... break; default: Console.WriteLine("Unknown clip type " + reader.GetIDString((uint)id)); break; } } } return clip; }
//====================================================================== // AddClip() // // Add a clip to the clip list. Used to store the contents of an RIMG or // TIMG surface subchunk. //====================================================================== static uint AddClip(string src, List<Clip> clist) { int pos = src.IndexOf("(sequence)"); if (pos != -1) { var clip = new ClipSequence((uint)clist.Count); clip.Prefix = src.Substring(pos); clip.Digits = 3; clist.Add(clip); return clip.Index; } else { var clip = new ClipStill((uint)clist.Count); clip.Name = src; clist.Add(clip); return clip.Index; } }