public static CursorFile FromFileSystemEntry(FileSystemEntry entry) { if (entry.FilePath.EndsWith(".ani")) { var aniFile = AniFile.FromFileSystemEntry(entry); var jiffy = TimeSpan.FromSeconds(1 / 60.0); CursorAnimationFrame[] animationFrames; if (aniFile.Sequence != null) { animationFrames = new CursorAnimationFrame[aniFile.Sequence.FrameIndices.Length]; for (var i = 0; i < animationFrames.Length; i++) { var frameDuration = aniFile.Rates != null ? aniFile.Rates.Durations[i] : aniFile.DefaultFrameDisplayRate; animationFrames[i] = new CursorAnimationFrame( aniFile.Sequence.FrameIndices[i], frameDuration * jiffy); } } else { animationFrames = Array.Empty <CursorAnimationFrame>(); } return(new CursorFile( aniFile.Images, animationFrames)); } else if (entry.FilePath.EndsWith(".cur")) { var curFile = CurFile.FromFileSystemEntry(entry); return(new CursorFile( new[] { curFile.Image }, Array.Empty <CursorAnimationFrame>())); } else { throw new InvalidOperationException(); } }
public static AniFile FromFileSystemEntry(FileSystemEntry entry) { RiffChunk rootChunk; using (var stream = entry.Open()) using (var reader = new BinaryReader(stream, Encoding.ASCII, true)) { rootChunk = RiffChunk.Parse(reader); } var result = new AniFile(); foreach (var chunk in ((RiffChunkList)rootChunk.Content).Chunks) { switch (chunk.Content) { case RiffChunkList list: switch (list.ListType) { case "INFO": var iconNameChunk = list.Chunks.FirstOrDefault(x => x.ChunkType == "INAM"); if (iconNameChunk != null) { result.IconName = ((InfoChunkContent)iconNameChunk.Content).Value; } var iconArtistChunk = list.Chunks.FirstOrDefault(x => x.ChunkType == "IART"); if (iconArtistChunk != null) { result.ArtistName = ((InfoChunkContent)iconArtistChunk.Content).Value; } break; case "fram": var iconIndex = 0; foreach (var iconChunk in list.Chunks) { if (iconChunk.ChunkType != "icon") { throw new InvalidDataException(); } var iconChunkContent = (IconChunkContent)iconChunk.Content; result.Images[iconIndex++] = iconChunkContent.GetImage(0); } break; } break; case AniHeaderChunkContent anih: result.Images = new CursorImage[anih.NumFrames]; result.DefaultFrameDisplayRate = anih.DefaultFrameDisplayRate; break; case RateChunkContent rate: result.Rates = rate; break; case SequenceChunkContent seq: result.Sequence = seq; break; default: throw new InvalidDataException(); } } return(result); }
public static AniFile FromFileSystemEntry(FileSystemEntry entry) { RiffChunk rootChunk; using (var stream = entry.Open()) using (var reader = new BinaryReader(stream, Encoding.ASCII, true)) { rootChunk = RiffChunk.Parse(reader); } var result = new AniFile(); foreach (var chunk in ((RiffChunkList)rootChunk.Content).Chunks) { switch (chunk.Content) { case RiffChunkList list: switch (list.ListType) { case "INFO": var iconNameChunk = list.Chunks.FirstOrDefault(x => x.ChunkType == "INAM"); if (iconNameChunk != null) { result.IconName = ((InfoChunkContent)iconNameChunk.Content).Value; } var iconArtistChunk = list.Chunks.FirstOrDefault(x => x.ChunkType == "IART"); if (iconArtistChunk != null) { result.ArtistName = ((InfoChunkContent)iconArtistChunk.Content).Value; } break; case "fram": var iconIndex = 0; foreach (var iconChunk in list.Chunks) { if (iconChunk.ChunkType != "icon") { throw new InvalidDataException(); } var iconChunkContent = (IconChunkContent)iconChunk.Content; var iconDirEntry = iconChunkContent.IconDirEntries[0]; if (result.IconWidth == 0) { result.IconWidth = iconDirEntry.Width; result.IconHeight = iconDirEntry.Height; result.HotspotX = iconDirEntry.HotspotX; result.HotspotY = iconDirEntry.HotspotY; } else { if (result.IconWidth != iconDirEntry.Width || result.IconHeight != iconDirEntry.Height) { throw new InvalidDataException(); } } var icon = iconChunkContent.Images[0]; var pixels = new byte[result.IconWidth * result.IconHeight * 4]; var index = 0; for (var y = 0; y < result.IconHeight; y++) { for (var x = 0; x < result.IconWidth; x++) { var pixelIndex = (y * result.IconWidth) + x; var isTransparent = icon.AndMask.Pixels[pixelIndex] == 1; var color = icon.ColorTable.Entries[icon.XorMask.Pixels[pixelIndex]]; pixels[index++] = color.Blue; pixels[index++] = color.Green; pixels[index++] = color.Red; pixels[index++] = isTransparent ? (byte)0 : (byte)255; } } result.Images[iconIndex] = new AniCursorImage(pixels); iconIndex++; } break; } break; case AniHeaderChunkContent anih: result.Images = new AniCursorImage[anih.NumFrames]; result.DefaultFrameDisplayRate = anih.DefaultFrameDisplayRate; break; case RateChunkContent rate: result.Rates = rate; break; case SequenceChunkContent seq: result.Sequence = seq; break; default: throw new InvalidDataException(); } } return(result); }