internal static bool packSprites(string sheetFile, string mapFile = "") { bool result = true; // generate our output ImagePacker imagePacker = new ImagePacker(); Bitmap outputSheet; Dictionary <string, Rectangle> outputMap; try { // pack the image, generating a map only if desired if (imagePacker.PackImage(images, false, true, 1024, 1024, 3, mapFile != "", out outputSheet, out outputMap) == 0) { outputSheet.Save(sheetFile); if (mapFile != "") { saveMap(mapFile, outputMap); } Console.WriteLine("Generated Sprite Sheet: {0}.", sheetFile); } else { Console.WriteLine("There was an error making the image sheet {0}.", sheetFile); result = false; } } catch (Exception e) { Console.WriteLine("Error saving sheet: {0} {1}", sheetFile, e.Message); result = false; } return(result); }
public override AtlasContent Process(AtlasDeclaration input, ContentProcessorContext context) { Dictionary <int, Bitmap> images = new Dictionary <int, Bitmap>(); Dictionary <int, string> imageNames = new Dictionary <int, string>(); ImagePacker imagePacker = new ImagePacker(); var imgFiles = input.Images.Select(i => Path.Combine(input.AtlasRootDir, i.Replace('/', '\\'))); if (imgFiles.Count() == 0) { throw new ArgumentException("No Image found"); } Bitmap output; Dictionary <string, Sprite> map; imagePacker.PackImage(imgFiles, true, true, 4096, 4096, 0, true, out output, out map); var finalSprites = map.Select(s => { s.Value.Name = s.Key.Substring(0, s.Key.LastIndexOf('.')).Substring(input.AtlasRootDir.Length + 1).Replace('\\', '/').Trim('.', '/'); return(s.Value); }).ToArray(); var atlasPngPath = Path.Combine(input.AtlasRootDir, input.Name + ".png"); using (FileStream outputSpriteFile = new FileStream(atlasPngPath, FileMode.Create)) { output.Save(outputSpriteFile, ImageFormat.Png); } context.AddOutputFile(atlasPngPath); ExternalReference <TextureContent> texture = new ExternalReference <TextureContent>(atlasPngPath); texture = BuildTexture($"{input.Name}Texture", texture, context); return(new AtlasContent { Texture = texture, Sprites = finalSprites }); }
/// <inheritdoc /> public virtual async Task <Result <IWebhook> > ModifyWebhookWithTokenAsync ( Snowflake webhookID, string token, Optional <string> name = default, Optional <Stream?> avatar = default, CancellationToken ct = default ) { var packAvatar = await ImagePacker.PackImageAsync(avatar, ct); if (!packAvatar.IsSuccess) { return(Result <IWebhook> .FromError(new GenericError("Failed to pack avatar."), packAvatar)); } var avatarData = packAvatar.Entity; return(await _discordHttpClient.PatchAsync <IWebhook> ( $"webhooks/{webhookID}/{token}", b => b.WithJson ( json => { json.Write("name", name, _jsonOptions); json.Write("avatar", avatarData, _jsonOptions); } ), ct : ct )); }
/// <inheritdoc /> public virtual async Task <Result <IGuild> > CreateGuildAsync ( string name, Optional <Stream> icon = default, Optional <VerificationLevel> verificationLevel = default, Optional <MessageNotificationLevel> defaultMessageNotifications = default, Optional <ExplicitContentFilterLevel> explicitContentFilter = default, Optional <IReadOnlyList <IRole> > roles = default, Optional <IReadOnlyList <IPartialChannel> > channels = default, Optional <Snowflake> afkChannelID = default, Optional <TimeSpan> afkTimeout = default, Optional <Snowflake> systemChannelID = default, Optional <SystemChannelFlags> systemChannelFlags = default, CancellationToken ct = default ) { if (name.Length < 2 || name.Length > 100) { return(new GenericError("The name must be between 2 and 100 characters.")); } await using var memoryStream = new MemoryStream(); var packIcon = await ImagePacker.PackImageAsync(new Optional <Stream?>(icon.Value), ct); if (!packIcon.IsSuccess) { return(Result <IGuild> .FromError(new GenericError("Failed to pack icon."), packIcon)); } var iconData = packIcon.Entity; return(await _discordHttpClient.PostAsync <IGuild> ( "guilds", b => b.WithJson ( json => { json.WriteString("name", name); json.Write("icon", iconData, _jsonOptions); json.Write("verification_level", verificationLevel, _jsonOptions); json.Write("default_message_notifications", defaultMessageNotifications, _jsonOptions); json.Write("explicit_content_filter", explicitContentFilter, _jsonOptions); json.Write("roles", roles, _jsonOptions); json.Write("channels", channels, _jsonOptions); json.Write("afk_channel_id", afkChannelID, _jsonOptions); if (afkTimeout.HasValue) { json.WriteNumber("afk_timeout", (ulong)afkTimeout.Value.TotalSeconds); } json.Write("system_channel_id", systemChannelID, _jsonOptions); json.Write("system_channel_flags", systemChannelFlags, _jsonOptions); } ), ct : ct )); }
public void PackWithNoBufferMosiacTests(RectInt[] rects, int padding, Vector2Int expectedSize) { RectInt[] packedRect; int packedWidth, packedHeight; ImagePacker.Pack(rects, padding, out packedRect, out packedWidth, out packedHeight); Assert.AreEqual(expectedSize.x, packedWidth); Assert.AreEqual(expectedSize.y, packedHeight); Assert.AreEqual(rects.Length, packedRect.Length); // Ensure all rects exists for (int i = 0; i < packedRect.Length; ++i) { // Ensure rect doesn't overlap with other rects RectInt testRect = packedRect[i]; for (int k = i + 1; k < packedRect.Length; ++k) { RectInt other = packedRect[k]; var contains = !((other.xMax + padding <= testRect.xMin || other.yMax + padding <= testRect.yMin) || (other.xMin >= testRect.xMax + padding || other.yMin >= testRect.yMax + padding)); Assert.IsFalse(contains); } // Ensure rects has the correct padding Assert.AreEqual(rects[i].width, testRect.width); Assert.AreEqual(rects[i].height, testRect.height); } }
/// <inheritdoc /> public virtual async Task <Result <IWebhook> > ModifyWebhookAsync ( Snowflake webhookID, Optional <string> name = default, Optional <Stream?> avatar = default, Optional <Snowflake> channelID = default, CancellationToken ct = default ) { var packAvatar = await ImagePacker.PackImageAsync(avatar, ct); if (!packAvatar.IsSuccess) { return(Result <IWebhook> .FromError(packAvatar)); } var avatarData = packAvatar.Entity; return(await this.DiscordHttpClient.PatchAsync <IWebhook> ( $"webhooks/{webhookID}", b => b.WithJson ( json => { json.Write("name", name, this.JsonOptions); json.Write("avatar", avatarData, this.JsonOptions); json.Write("channel_id", channelID, this.JsonOptions); } ), ct : ct )); }
public MainPage() { InitializeComponent(); _syncContext = SynchronizationContext.Current; PageModel = new MainPageModel(_syncContext); MainGrid.DataContext = PageModel; _loadPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "touhou_luna_nights"); if (!Directory.Exists(_loadPath)) { Directory.CreateDirectory(_loadPath); } _save0Path = Path.Combine(_loadPath, "game0.sav"); _save1Path = Path.Combine(_loadPath, "game1.sav"); _save2Path = Path.Combine(_loadPath, "game2.sav"); _saveEditor = new SaveEditor(); _imagePacker = new ImagePacker(_syncContext); ErrorTracker.UpdateError += ErrorTrackerUpdateError; Task.Run(ProcessCurrentSaves); }
/// <inheritdoc /> public virtual async Task <Result <IUser> > ModifyCurrentUserAsync ( Optional <string> username, Optional <Stream?> avatar = default, CancellationToken ct = default ) { var packAvatar = await ImagePacker.PackImageAsync(avatar, ct); if (!packAvatar.IsSuccess) { return(Result <IUser> .FromError(packAvatar)); } var avatarData = packAvatar.Entity; return(await this.DiscordHttpClient.PatchAsync <IUser> ( "users/@me", b => b.WithJson ( json => { json.Write("username", username, this.JsonOptions); json.Write("avatar", avatarData, this.JsonOptions); } ), ct : ct )); }
/// <inheritdoc /> public virtual async Task <Result <IGuild> > CreateGuildFromTemplateAsync ( string templateCode, string name, Optional <Stream> icon = default, CancellationToken ct = default ) { var packIcon = await ImagePacker.PackImageAsync(new Optional <Stream?>(icon.Value), ct); if (!packIcon.IsSuccess) { return(Result <IGuild> .FromError(new GenericError("Failed to pack icon."), packIcon)); } var iconData = packIcon.Entity; return(await _discordHttpClient.PostAsync <IGuild> ( $"guilds/templates/{templateCode}", b => b.WithJson ( j => { j.WriteString("name", name); j.Write("icon", iconData); } ), ct : ct )); }
public async Task CanPackGIFAsync() { // Create a dummy GIF image await using var image = new MemoryStream(); await using var binaryWriter = new BinaryWriter(image); binaryWriter.Write(0x00464947); image.Position = 0; var result = await ImagePacker.PackImageAsync(image); ResultAssert.Successful(result); }
public async Task CanPackPNGAsync() { // Create a dummy PNG image await using var image = new MemoryStream(); await using var binaryWriter = new BinaryWriter(image); binaryWriter.Write(9894494448401390090); image.Position = 0; var result = await ImagePacker.PackImageAsync(image); ResultAssert.Successful(result); }
public async Task ReturnsErrorIfFormatIsUnknown() { // Create a dummy unknown image await using var image = new MemoryStream(); await using var binaryWriter = new BinaryWriter(image); binaryWriter.Write(0x00000000); image.Position = 0; var result = await ImagePacker.PackImageAsync(image); ResultAssert.Unsuccessful(result); }
public static int Pack(string atlasDir, string imageOutputDir, string codeOutputDir, Func <string, string> namingFunc) { string imgFile = Path.Combine(imageOutputDir, "Atlas.png"); string codeFile = Path.Combine(codeOutputDir, "Atlas.cs"); // find all images List <string> images = new List <string>(); foreach (var file in Directory.GetFiles(atlasDir, "*.*", SearchOption.AllDirectories)) { FileInfo info = new FileInfo(file); if (info.Extension == ".png") { images.Add(info.FullName); } } // PACKIT! var imagePacker = new ImagePacker(); Bitmap outputImage; Dictionary <string, Rectangle> outputMap; int result = imagePacker.PackImage(images, true, true, MAXIMGSIZE, MAXIMGSIZE, 1, true, out outputImage, out outputMap); if (result != 0) { Dbg.Write("There was an error making the image sheet."); return(result); } if (File.Exists(imgFile)) { File.Delete(imgFile); } IImageExporter imageExporter = new PngImageExporter(); imageExporter.Save(imgFile, outputImage); if (File.Exists(codeFile)) { File.Delete(codeFile); } CsGenExporter mapExporter = new CsGenExporter(); mapExporter.namerFunc = namingFunc; mapExporter.atlasSize = outputImage.Width; mapExporter.Save(codeFile, outputMap); return(200); }
public void PackingWorks() { var files = GetSpriteFiles(); Assert.NotEmpty(files); var packer = new ImagePacker(); packer.PackImage(files, true, true, 4096, 4096, 2, out var image, out var map); Assert.NotNull(image); Assert.NotNull(map); var outFile = new FileInfo("TestOutput.png"); using (var stream = outFile.Open(FileMode.Create)) { image.Save(stream, new PngEncoder()); } }
/// <inheritdoc /> public virtual async Task <Result <IWebhook> > CreateWebhookAsync ( Snowflake channelID, string name, Optional <Stream?> avatar, CancellationToken ct = default ) { if (name.Length < 1 || name.Length > 80) { return(new GenericError("Names must be between 1 and 80 characters")); } if (name.Equals("clyde", StringComparison.InvariantCultureIgnoreCase)) { return(new GenericError("Names cannot be \"clyde\".")); } var packAvatar = await ImagePacker.PackImageAsync(avatar, ct); if (!packAvatar.IsSuccess) { return(Result <IWebhook> .FromError(new GenericError("Failed to pack avatar."), packAvatar)); } var avatarData = packAvatar.Entity; return(await _discordHttpClient.PostAsync <IWebhook> ( $"channels/{channelID}/webhooks", b => b.WithJson ( json => { json.WriteString("name", name); json.WriteString("avatar", avatarData.Value); } ), ct : ct )); }
private void GetImagesRecursively(DirectoryInfo dirPath, string prefix) { var files = SystemTool.GetDirectoryFiles(dirPath); foreach (var file in files) { if (!file.Name.EndsWith(".png")) { Logger.LogInfoLine("{0}Only accept png image:{1}", prefix, file); continue; } var imageFile = new ImageFile(file, true, true); //Logger.LogInfoLine("{0}File:\t{1}", prefix, file.FullName.Replace(PathManager.InputImagesPath.FullName, string.Empty)); bool isPacked = !file.Directory.FullName.Contains(PathManager.InputImageOtherPath.FullName); bool isPVREnabled = false; if (PublishTarget.Current.IsPVR) { isPVREnabled = mPVREnabledDirectoryNames.Any(pvrEnabledDirectoryName => file.Directory.FullName.Contains(pvrEnabledDirectoryName)); } //bool isEffectAnimation = file.Directory.FullName.Contains("EffectAnimation"); //isPacked &= !isEffectAnimation; //bool isOptimzed = !isEffectAnimation; if (!PublishTarget.Current.IsPack) { isPacked = false; } bool isOptimzed = PublishTarget.Current.IsOptimzed; bool isPOT = PublishTarget.Current.IsPOT; bool isSquare = PublishTarget.Current.IsSquare; if (isPVREnabled) { isPOT = true; isSquare = true; } ImagePacker.AddImage(imageFile, PublishTarget.Current, isPacked, isOptimzed, isPVREnabled, isPOT, isSquare); FilterImage(file); } }
/// <inheritdoc /> public virtual async Task <Result <IEmoji> > CreateGuildEmojiAsync ( Snowflake guildID, string name, Stream image, IReadOnlyList <Snowflake> roles, CancellationToken ct = default ) { if (image.Length > 256000) { return(new NotSupportedError("Image too large (max 256k).")); } var packImage = await ImagePacker.PackImageAsync(image, ct); if (!packImage.IsSuccess) { return(Result <IEmoji> .FromError(packImage)); } var emojiData = packImage.Entity; return(await this.DiscordHttpClient.PostAsync <IEmoji> ( $"guilds/{guildID}/emojis", b => b.WithJson ( json => { json.WriteString("name", name); json.WriteString("image", emojiData); json.WritePropertyName("roles"); JsonSerializer.Serialize(json, roles, this.JsonOptions); } ), ct : ct )); }
public void Test02_TextureTest() { Logfile log = UnitTestHelper.CreateLogfile(); Assert.IsNotNull(log); Assert.IsTrue(log.CanWrite); //create objects List <Texture> texturelist = null; XmlNodeList xmlTextureList = null; MapHandler mapHandler = new MapHandler(); ImagePacker imagePacker = new ImagePacker(); XmlDocument textureDocument = new XmlDocument(); //setup paths string testFileIn = Path.Combine(UnitTestHelper.ResourcesFolder, "battleAtlas.xml"); Assert.IsTrue(File.Exists(testFileIn)); string testFileOut = Path.Combine(UnitTestHelper.ResourcesFolder, "battleAtlas2.xml"); if (File.Exists(testFileOut)) { File.Delete(testFileOut); } //load sub-texture count to xml textureDocument.Load(testFileIn); xmlTextureList = textureDocument.SelectNodes("//SubTexture"); int numSubTextures = xmlTextureList.Count; //load texture list log.Write("Asserting to load a xml texture file to Texture list"); texturelist = mapHandler.LoadMapFile(testFileIn); log.Write(string.Format("Texture class load status: {0}", texturelist != null)); Assert.IsNotNull(texturelist); //compare texture count log.Write(string.Format("Xml node textures: {0}, parsed: {1}", numSubTextures, texturelist.Count)); Assert.AreEqual(numSubTextures, texturelist.Count); //for the packer, need to create bitmaps. we won't use them foreach (Texture tex in texturelist) { tex.AtlasImage = new Bitmap(1, 1); } //compare each individual texture log.Write("Asserting each texture matches from xml to texture list"); for (int i = 0; i < texturelist.Count; i++) { Texture texture = texturelist[i]; XmlElement xmlTexture = xmlTextureList[i] as XmlElement; //properties match lowercase xml properties names foreach (string propertyName in texture.PropertiesForSerializationElements()) { XmlElement element = xmlTexture.SelectSingleNode(propertyName.ToLower()) as XmlElement; Assert.IsNotNull(element); string xmlValue = element.InnerText.Trim(); //for reference //PropertyInfo property = listObjectType.GetProperty(attributeName); PropertyInfo property = typeof(Texture).GetProperty(propertyName); Assert.IsNotNull(property); object value = property.GetValue(texture); Assert.IsNotNull(value); Assert.AreEqual(xmlValue, value.ToString()); } } //pack textures FailCode code = imagePacker.PackImage(texturelist, true, false, true, 8192, 8192, 1, "battleAtlas.dds", out Bitmap map, out Dictionary <string, Rectangle> imageSizes); log.Write(string.Format("Packer fail code: {0}", code.ToString())); Assert.AreEqual(FailCode.None, code); //for the packer, need to dispose bitmaps map.Dispose(); foreach (Texture tex in texturelist) { tex.AtlasImage.Dispose(); } //save to new xml file mapHandler.SaveMapfile(testFileOut, imageSizes); Assert.IsTrue(File.Exists(testFileOut)); //compare texture count textureDocument = new XmlDocument(); textureDocument.Load(testFileOut); xmlTextureList = textureDocument.SelectNodes("//SubTexture"); numSubTextures = xmlTextureList.Count; log.Write(string.Format("Xml node textures: {0}, parsed: {1}", numSubTextures, imageSizes.Count)); Assert.AreEqual(numSubTextures, imageSizes.Count); //compare each individual texture log.Write("Asserting each texture matches from xml to dictionary"); for (int i = 0; i < xmlTextureList.Count; i++) { XmlElement xmlTexture = xmlTextureList[i] as XmlElement; Assert.IsNotNull(xmlTexture); string textureName = xmlTexture.SelectSingleNode(nameof(Texture.Name).ToLower()).InnerText.Trim(); Rectangle imageSize = imageSizes[textureName]; Assert.IsNotNull(imageSize); string[] propertiesToCheck = { nameof(imageSize.X), nameof(imageSize.Y), nameof(imageSize.Width), nameof(imageSize.Height) }; foreach (string propertyName in propertiesToCheck) { XmlElement xmlProperty = xmlTexture.SelectSingleNode(propertyName.ToLower()) as XmlElement; Assert.IsNotNull(xmlProperty); PropertyInfo property = imageSize.GetType().GetProperty(propertyName); Assert.IsNotNull(property); object propertyValue = property.GetValue(imageSize); Assert.IsNotNull(propertyValue); Assert.IsTrue(propertyValue is int); Assert.AreEqual(xmlProperty.InnerText.Trim(), propertyValue.ToString()); } } File.Delete(testFileOut); UnitTestHelper.DestroyLogfile(ref log, false); Assert.IsNull(log); }
public void PackWithBufferMosiacTests(RectInt[] rects, int padding, Vector2Int expectedSize) { RectInt[] packedRect; int packedWidth, packedHeight; // Find the largest buffer int maxWidth = -1, maxHeight = -1; for (int i = 0; i < rects.Length; ++i) { if (rects[i].width > maxWidth) { maxWidth = rects[i].width; } if (rects[i].height > maxHeight) { maxHeight = rects[i].height; } } // Setup color buffers NativeArray <Color32>[] buffers = new NativeArray <Color32> [rects.Length]; for (int i = 0; i < rects.Length; ++i) { buffers[i] = new NativeArray <Color32>(maxWidth * maxHeight, Allocator.Temp); for (int j = 0; j < maxHeight; ++j) { for (int k = 0; k < maxWidth; ++k) { int bufferIndex = (j * maxWidth + k); if (k >= rects[i].width || j >= rects[i].height) { buffers[i][bufferIndex] = new Color32(0, 0, 0, 0); } else { buffers[i][bufferIndex] = new Color32((byte)i, (byte)i, (byte)i, 255); } } } } NativeArray <Color32> packedBuffer; Vector2Int[] uvTransform; ImagePacker.Pack(buffers, maxWidth, maxHeight, padding, out packedBuffer, out packedWidth, out packedHeight, out packedRect, out uvTransform); Assert.AreEqual(expectedSize.x, packedWidth); Assert.AreEqual(expectedSize.y, packedHeight); Assert.AreEqual(rects.Length, packedRect.Length); // Ensure all rects exists int bytesPerRow = packedWidth; for (int i = 0; i < packedRect.Length; ++i) { // Ensure rect doesn't overlap with other rects RectInt testRect = packedRect[i]; for (int k = i + 1; k < packedRect.Length; ++k) { RectInt other = packedRect[k]; var contains = !((other.xMax + padding <= testRect.xMin || other.yMax + padding <= testRect.yMin) || (other.xMin >= testRect.xMax + padding || other.yMin >= testRect.yMax + padding)); Assert.IsFalse(contains); } // Ensure rects has the correct padding Assert.AreEqual(rects[i].width, testRect.width); Assert.AreEqual(rects[i].height, testRect.height); // Ensure buffers are blitted to the correct place. We will just sample min, max and center point if (testRect.width > 0 && testRect.height > 0) { Assert.IsTrue(PixelColorEqual(packedBuffer, packedWidth, bytesPerRow, testRect.xMin + padding, testRect.yMin, new Color32((byte)i, (byte)i, (byte)i, 255))); Assert.IsTrue(PixelColorEqual(packedBuffer, packedWidth, bytesPerRow, testRect.xMax - 1, testRect.yMax - 1, new Color32((byte)i, (byte)i, (byte)i, 255))); Assert.IsTrue(PixelColorEqual(packedBuffer, packedWidth, bytesPerRow, (int)testRect.center.x - 1, (int)testRect.center.y - 1, new Color32((byte)i, (byte)i, (byte)i, 255))); } } packedBuffer.Dispose(); for (int i = 0; i < buffers.Length; ++i) { buffers[i].Dispose(); } }
public int NextPowerOfTwoTest(int value) { return((int)ImagePacker.NextPowerOfTwo((ulong)value)); }
public static int Main(string[] args) { var app = new CommandLineApplication(false); var folderOption = app.Option("-f | --folder", "Specifies input folder", CommandOptionType.SingleValue); var outputOption = app.Option("-o | --output", "Specifies the output image's file name", CommandOptionType.SingleValue); var mapOption = app.Option("-m | --map", "Specifies the map's file name", CommandOptionType.SingleValue); var powTwoOption = app.Option("-2 | --pow2", "Forces that the output to have power of two dimensions", CommandOptionType.NoValue); var squareOption = app.Option("-s | --square", "Forces that the output to be have equal width and length", CommandOptionType.NoValue); var maxWidthOption = app.Option("-w | --maxwidth", "Specifies the maximum allowed output width", CommandOptionType.SingleValue); var maxHeightOption = app.Option("-h | --maxwidth", "Specifies the maximum allowed output height", CommandOptionType.SingleValue); var paddingOption = app.Option("-p | --padding", "Specifies the padding in pixel between packed subimages", CommandOptionType.SingleValue); app.HelpOption("-? | -h | --help"); app.OnExecute(() => { if (!folderOption.HasValue() || !outputOption.HasValue()) { Console.WriteLine("An input folder and an output filename are required"); return(1); } var inputDir = new DirectoryInfo(folderOption.Value()); var inputFiles = inputDir.GetFiles().Where(d => ImagePacker.SupportedImageExtensions.Contains(d.Extension.ToLower())).ToArray(); if (!inputFiles.Any()) { Console.WriteLine("No supported files found"); return(1); } var outFile = new FileInfo(outputOption.Value()); var outEncoder = ImagePacker.GetEncoderFromExtension(outFile.Extension); if (outEncoder == null) { Console.WriteLine("Unsupported output file format"); return(1); } var outMap = mapOption.HasValue() ? new FileInfo(mapOption.Value()) : null; IMapGenerator outGenerator = null; if (outMap != null) { outGenerator = MapGenerators.FirstOrDefault(d => d.MapExtension == outMap.Extension.ToLower()); if (outGenerator == null) { Console.WriteLine("Unsupported output map format"); return(1); } } var valueParsed = int.TryParse(maxWidthOption.Value(), out var maxWidth); if (!valueParsed) { maxWidth = DefaultSize; } valueParsed = int.TryParse(maxHeightOption.Value(), out var maxHeight); if (!valueParsed) { maxHeight = DefaultSize; } valueParsed = int.TryParse(paddingOption.Value(), out var padding); if (!valueParsed) { padding = DefaultPadding; } var packer = new ImagePacker(); packer.PackImage(inputFiles, powTwoOption.HasValue(), squareOption.HasValue(), maxWidth, maxHeight, padding, out var packedImage, out var packedMap); using (var outStream = outFile.Open(FileMode.Create)) { packedImage.Save(outStream, outEncoder); } if (outGenerator != null) { var mapBytes = outGenerator.Generate(packedMap); using (var outStream = outMap.Open(FileMode.Create)) { outStream.Write(mapBytes, 0, mapBytes.Length); } } return(0); }); return(app.Execute(args)); }
public void PostCheck() { CheckUsage(); ImagePacker.Pack(PublishTarget.Current); }
/// <inheritdoc /> public virtual async Task <Result <IGuild> > ModifyGuildAsync ( Snowflake guildID, Optional <string> name = default, Optional <string?> region = default, Optional <VerificationLevel?> verificationLevel = default, Optional <MessageNotificationLevel?> defaultMessageNotifications = default, Optional <ExplicitContentFilterLevel?> explicitContentFilter = default, Optional <Snowflake?> afkChannelID = default, Optional <TimeSpan> afkTimeout = default, Optional <Stream?> icon = default, Optional <Snowflake> ownerID = default, Optional <Stream?> splash = default, Optional <Stream?> discoverySplash = default, Optional <Stream?> banner = default, Optional <Snowflake?> systemChannelID = default, Optional <SystemChannelFlags> systemChannelFlags = default, Optional <Snowflake?> rulesChannelID = default, Optional <Snowflake?> publicUpdatesChannelID = default, Optional <string?> preferredLocale = default, Optional <IReadOnlyList <GuildFeature> > features = default, Optional <string?> description = default, CancellationToken ct = default ) { await using var memoryStream = new MemoryStream(); Optional <string?> iconData = default; if (icon.HasValue) { if (icon.Value is null) { iconData = new Optional <string?>(null); } else { var packImage = await ImagePacker.PackImageAsync(icon.Value, ct); if (!packImage.IsSuccess) { return(Result <IGuild> .FromError(new GenericError("Failed to pack icon."), packImage)); } iconData = packImage.Entity; } } Optional <string?> splashData = default; if (splash.HasValue) { if (splash.Value is null) { splashData = new Optional <string?>(null); } else { var packImage = await ImagePacker.PackImageAsync(splash.Value, ct); if (!packImage.IsSuccess) { return(Result <IGuild> .FromError(new GenericError("Failed to pack splash."), packImage)); } splashData = packImage.Entity; } } Optional <string?> discoverySplashData = default; if (discoverySplash.HasValue) { if (discoverySplash.Value is null) { discoverySplashData = new Optional <string?>(null); } else { var packImage = await ImagePacker.PackImageAsync(discoverySplash.Value, ct); if (!packImage.IsSuccess) { return(Result <IGuild> .FromError(new GenericError("Failed to pack discovery splash."), packImage)); } discoverySplashData = packImage.Entity; } } var packBanner = await ImagePacker.PackImageAsync(banner, ct); if (!packBanner.IsSuccess) { return(Result <IGuild> .FromError(new GenericError("Failed to pack banner."), packBanner)); } var bannerData = packBanner.Entity; return(await _discordHttpClient.PatchAsync <IGuild> ( $"guilds/{guildID}", b => b.WithJson ( json => { json.Write("name", name, _jsonOptions); json.Write("region", region, _jsonOptions); json.WriteEnum("verification_level", verificationLevel, jsonOptions: _jsonOptions); json.WriteEnum ( "default_message_notifications", defaultMessageNotifications, jsonOptions: _jsonOptions ); json.WriteEnum("explicit_content_filter", explicitContentFilter, jsonOptions: _jsonOptions); json.Write("afk_channel_id", afkChannelID, _jsonOptions); if (afkTimeout.HasValue) { json.WriteNumber("afk_timeout", (ulong)afkTimeout.Value.TotalSeconds); } json.Write("icon", iconData, _jsonOptions); json.Write("owner_id", ownerID, _jsonOptions); json.Write("splash", splashData, _jsonOptions); json.Write("discovery_splash", discoverySplashData, _jsonOptions); json.Write("banner", bannerData, _jsonOptions); json.Write("system_channel_id", systemChannelID, _jsonOptions); json.Write("system_channel_flags", systemChannelFlags, _jsonOptions); json.Write("rules_channel_id", rulesChannelID, _jsonOptions); json.Write("public_updates_channel_id", publicUpdatesChannelID, _jsonOptions); json.Write("preferred_locale", preferredLocale, _jsonOptions); json.Write("features", features, _jsonOptions); json.Write("description", description, _jsonOptions); } ), ct : ct )); }
void PackOnce() { if (mPackTasks.Count == 0) { return; } // generate our output ImagePacker imagePacker = new ImagePacker(); Bitmap outputImage; Dictionary <string, System.Drawing.Rectangle> outputMap; PackTask pt = mPackTasks.Dequeue(); Console.WriteLine("Packing {0} ({1} left to pack)", pt.outputFile, mPackTasks.Count); // pack the image, generating a map only if desired int result = imagePacker.PackImage(pt.inputFiles, REQUIRE_POW2, REQUIRE_SQUARE, 4096, 4096, PADDING, true, out outputImage, out outputMap); if (result != 0) { Console.WriteLine("There was an error making the image sheet."); return; } // try to save using our exporters try { if (File.Exists(pt.outputFile)) { File.Delete(pt.outputFile); } mImageExporter.Save(pt.outputFile, outputImage); Console.WriteLine("Saved atlas {0}.", pt.outputFile); } catch (Exception e) { Console.WriteLine("Error saving file: " + e.Message); return; } if (mMapExporter != null) { try { if (File.Exists(pt.outputMap)) { File.Delete(pt.outputMap); } mMapExporter.Save(pt.outputMap, outputMap); Console.WriteLine("Saved atlas map {0}.", pt.outputMap); } catch (Exception e) { Console.WriteLine("Error saving file: " + e.Message); return; } } foreach (string filename in pt.inputFiles) { if (File.Exists(filename)) { try { File.Delete(filename); } catch (IOException) { // Welp } } } }
void ImportFromLayers(AssetImportContext ctx, Document doc) { NativeArray <Color32> output = default(NativeArray <Color32>); List <int> layerIndex = new List <int>(); List <int> spriteNameHash = new List <int>(); var oldPsdLayers = GetPSDLayers(); try { var psdLayers = new List <PSDLayer>(); ExtractLayerTask.Execute(psdLayers, doc.Layers, m_ImportHiddenLayers); var removedLayersSprite = oldPsdLayers.Where(x => psdLayers.FirstOrDefault(y => y.layerID == x.layerID) == null).Select(z => z.spriteID).ToArray(); for (int i = 0; i < psdLayers.Count; ++i) { int j = 0; var psdLayer = psdLayers[i]; for (; j < oldPsdLayers.Count; ++j) { if (psdLayer.layerID == oldPsdLayers[j].layerID) { psdLayer.spriteID = oldPsdLayers[j].spriteID; psdLayer.spriteName = oldPsdLayers[j].spriteName; psdLayer.mosaicPosition = oldPsdLayers[j].mosaicPosition; break; } } } int expectedBufferLength = doc.width * doc.height; var layerBuffers = new List <NativeArray <Color32> >(); for (int i = 0; i < psdLayers.Count; ++i) { var l = psdLayers[i]; if (l.texture.IsCreated && l.texture.Length == expectedBufferLength) { layerBuffers.Add(l.texture); layerIndex.Add(i); } } RectInt[] spritedata; int width, height; int padding = 4; Vector2Int[] uvTransform; ImagePacker.Pack(layerBuffers.ToArray(), doc.width, doc.height, padding, out output, out width, out height, out spritedata, out uvTransform); var spriteImportData = GetSpriteImportData(); if (spriteImportData.Count <= 0 || shouldResliceFromLayer) { var newSpriteMeta = new List <SpriteMetaData>(); for (int i = 0; i < spritedata.Length && i < layerIndex.Count; ++i) { var spriteSheet = spriteImportData.FirstOrDefault(x => x.spriteID == psdLayers[layerIndex[i]].spriteID); if (spriteSheet == null) { spriteSheet = new SpriteMetaData(); spriteSheet.border = Vector4.zero; spriteSheet.alignment = (SpriteAlignment)m_TextureImporterSettings.spriteAlignment; spriteSheet.pivot = m_TextureImporterSettings.spritePivot; } psdLayers[layerIndex[i]].spriteName = GetUniqueName(psdLayers[layerIndex[i]].name, spriteNameHash); spriteSheet.name = psdLayers[layerIndex[i]].spriteName; spriteSheet.rect = new Rect(spritedata[i].x, spritedata[i].y, spritedata[i].width, spritedata[i].height); spriteSheet.uvTransform = uvTransform[i]; psdLayers[layerIndex[i]].spriteID = spriteSheet.spriteID; psdLayers[layerIndex[i]].mosaicPosition = spritedata[i].position; newSpriteMeta.Add(spriteSheet); } spriteImportData.Clear(); spriteImportData.AddRange(newSpriteMeta); } else { spriteImportData.RemoveAll(x => removedLayersSprite.Contains(x.spriteID)); foreach (var spriteData in spriteImportData) { var psdLayer = psdLayers.FirstOrDefault(x => x.spriteID == spriteData.spriteID); if (psdLayer == null) { spriteData.uvTransform = new Vector2Int((int)spriteData.rect.position.x, (int)spriteData.rect.position.y); } // If it is user created rect or the name has been changed before // add it into the spriteNameHash and we don't copy it over from the layer if (psdLayer == null || psdLayer.spriteName != spriteData.name) { spriteNameHash.Add(spriteData.name.GetHashCode()); } // If the sprite name has not been changed, we ensure the new // layer name is still unique and use it as the sprite name if (psdLayer != null && psdLayer.spriteName == spriteData.name) { psdLayer.spriteName = GetUniqueName(psdLayer.name, spriteNameHash); spriteData.name = psdLayer.spriteName; } } //Update names for those user has not changed and add new sprite rect based on PSD file. for (int k = 0; k < layerIndex.Count; ++k) { int i = layerIndex[k]; var spriteSheet = spriteImportData.FirstOrDefault(x => x.spriteID == psdLayers[i].spriteID); var inOldLayer = oldPsdLayers.FindIndex(x => x.layerID == psdLayers[i].layerID) != -1; if (spriteSheet == null && !inOldLayer) { spriteSheet = new SpriteMetaData(); spriteImportData.Add(spriteSheet); spriteSheet.rect = new Rect(spritedata[k].x, spritedata[k].y, spritedata[k].width, spritedata[k].height); spriteSheet.border = Vector4.zero; spriteSheet.alignment = (SpriteAlignment)m_TextureImporterSettings.spriteAlignment; spriteSheet.pivot = m_TextureImporterSettings.spritePivot; psdLayers[i].spriteName = GetUniqueName(psdLayers[i].name, spriteNameHash); spriteSheet.name = psdLayers[i].spriteName; } else if (spriteSheet != null) { var r = spriteSheet.rect; r.position = spriteSheet.rect.position - psdLayers[i].mosaicPosition + spritedata[k].position; spriteSheet.rect = r; } if (spriteSheet != null) { spriteSheet.uvTransform = uvTransform[k]; psdLayers[i].spriteID = spriteSheet.spriteID; psdLayers[i].mosaicPosition = spritedata[k].position; } } } oldPsdLayers.Clear(); oldPsdLayers.AddRange(psdLayers); m_ResliceFromLayer = false; m_ImportedTextureHeight = textureActualHeight = height; m_ImportedTextureWidth = textureActualWidth = width; var generatedTexture = ImportTexture(ctx, output, width, height, 0, spriteImportData.Count); m_ImportedTextureHeight = generatedTexture.texture.height; m_ImportedTextureWidth = generatedTexture.texture.width; RegisterAssets(ctx, generatedTexture); } finally { if (output.IsCreated) { output.Dispose(); } foreach (var l in oldPsdLayers) { l.Dispose(); } } }