public static MagitekResult CopyPixels(DirectImage source, DirectImage dest, Point sourceStart, Point destStart, int copyWidth, int copyHeight) { var dimensionResult = CanCopyPixelDimensions(source, dest, sourceStart, destStart, copyWidth, copyHeight); if (dimensionResult.Value is MagitekResult.Failed) { return(dimensionResult); } if (ImageRegionContainsInvalidElements(source, sourceStart, copyWidth, copyHeight)) { return(new MagitekResult.Failed($"Source image copy region contains blank elements")); } if (ImageRegionContainsInvalidElements(dest, destStart, copyWidth, copyHeight)) { return(new MagitekResult.Failed($"Destination image paste region contains blank elements")); } for (int y = 0; y < copyHeight; y++) { for (int x = 0; x < copyWidth; x++) { var color = source.GetPixel(x + sourceStart.X, y + sourceStart.Y); dest.SetPixel(x + destStart.X, y + destStart.Y, color); } } return(MagitekResult.SuccessResult); }
/// <summary> /// Fills the surrounding, contiguous color area with a new color /// </summary> /// <param name="x">x-coordinate to start at in pixel coordinates</param> /// <param name="y">y-coordinate to start at in pixel coordinates</param> /// <param name="fillIndex">Palette index to fill with</param> /// <returns>True if any pixels were modified</returns> public static bool FloodFill(this DirectImage image, int x, int y, ColorRgba32 fillColor) { bool isModified = false; var replaceColor = image.GetPixel(x, y); if (fillColor.Color == replaceColor.Color) { return(false); } var openNodes = new Stack <(int x, int y)>(); openNodes.Push((x, y)); while (openNodes.Count > 0) { var nodePosition = openNodes.Pop(); if (nodePosition.x >= 0 && nodePosition.x < image.Width && nodePosition.y >= 0 && nodePosition.y < image.Height) { var nodeColor = image.GetPixel(nodePosition.x, nodePosition.y); if (nodeColor.Color == replaceColor.Color) { isModified = true; image.SetPixel(nodePosition.x, nodePosition.y, fillColor); openNodes.Push((nodePosition.x - 1, nodePosition.y)); openNodes.Push((nodePosition.x + 1, nodePosition.y)); openNodes.Push((nodePosition.x, nodePosition.y - 1)); openNodes.Push((nodePosition.x, nodePosition.y + 1)); } } } return(isModified); }
public static ImportResult ImportImage(ProjectTree projectTree, string imageFileName, string arrangerKey) { Console.Write($"Importing '{imageFileName}' to '{arrangerKey}'..."); if (!File.Exists(imageFileName)) { Console.WriteLine($"File does not exist"); return(ImportResult.MissingFile); } if (!projectTree.TryGetItem(arrangerKey, out ScatteredArranger arranger)) { Console.WriteLine($"Resource key does not exist or is not a {nameof(ScatteredArranger)}"); return(ImportResult.BadResourceKey); } if (arranger.ColorType == PixelColorType.Indexed) { var image = new IndexedImage(arranger); image.ImportImage(imageFileName, new ImageSharpFileAdapter(), ColorMatchStrategy.Exact); image.SaveImage(); } else if (arranger.ColorType == PixelColorType.Direct) { var image = new DirectImage(arranger); image.ImportImage(imageFileName, new ImageSharpFileAdapter()); image.SaveImage(); } Console.WriteLine("Completed successfully"); return(ImportResult.Success); }
public DirectBitmapAdapter(DirectImage image) { Image = image; Width = Image.Width; Height = Image.Height; Bitmap = new WriteableBitmap(Width, Height, DpiX, DpiY, PixelFormat, null); Invalidate(); }
public DirectPixelCopy(Arranger source, int pixelX, int pixelY, int width, int height) { Source = source; X = pixelX; Y = pixelY; Width = width; Height = height; Image = new DirectImage(Source, X, Y, Width, Height); }
private static void ApplyExactColorRemapPixels(DirectImage source, IndexedImage dest, Point sourceStart, Point destStart, int copyWidth, int copyHeight) { for (int y = 0; y < copyHeight; y++) { for (int x = 0; x < copyWidth; x++) { var color = source.GetPixel(x + sourceStart.X, y + sourceStart.Y); dest.SetPixel(x + destStart.X, y + destStart.Y, color); } } }
/// <summary> /// Creates a new IndexedImage from a DirectImage /// </summary> /// <param name="direct">The source DirectImage</param> /// <param name="pal">The palette for color conversion</param> /// <returns></returns> public static IndexedImage ToIndexed(DirectImage direct, Palette pal) { throw new NotImplementedException(); //var indexed = new IndexedImage(direct.Width, direct.Height); //for(int i = 0; i < direct.Width * direct.Height; i++) //{ // var index = pal.GetIndexByNativeColor(direct.Image[i], true); // indexed.Image[i] = index; //} //return indexed; }
private static MagitekResult CanRemapByExactPaletteColors(DirectImage source, IndexedImage dest, Point sourceStart, Point destStart, int copyWidth, int copyHeight) { for (int y = 0; y < copyHeight; y++) { for (int x = 0; x < copyWidth; x++) { var color = source.GetPixel(x + sourceStart.X, y + sourceStart.Y); if (dest.CanSetPixel(x + destStart.X, y + destStart.Y, color).Value is MagitekResult.Failed) { var palName = dest.GetElementAtPixel(x + destStart.X, y + destStart.Y)?.Palette?.Name ?? "Undefined"; return(new MagitekResult.Failed($"Destination image at (x: {destStart.X}, y: {destStart.Y}) with element palette '{palName}' could not be set to the source color ({color.A}, {color.R}, {color.G}, {color.B})")); } } } return(MagitekResult.SuccessResult); }
private static MagitekResult CanExactColorRemapPixels(DirectImage source, IndexedImage dest, Point sourceStart, Point destStart, int copyWidth, int copyHeight) { for (int y = 0; y < copyHeight; y++) { for (int x = 0; x < copyWidth; x++) { var color = source.GetPixel(x + sourceStart.X, y + sourceStart.Y); var result = dest.CanSetPixel(x + destStart.X, y + destStart.Y, color); if (result.Value is MagitekResult.Failed) { return(result); } } } return(MagitekResult.SuccessResult); }
private void Initialize(Arranger arranger, int viewX, int viewY, int viewWidth, int viewHeight) { Resource = arranger; WorkingArranger = arranger.CloneArranger(); _viewX = viewX; _viewY = viewY; _viewWidth = viewWidth; _viewHeight = viewHeight; _directImage = new DirectImage(WorkingArranger, _viewX, _viewY, _viewWidth, _viewHeight); BitmapAdapter = new DirectBitmapAdapter(_directImage); DisplayName = $"Pixel Editor - {WorkingArranger.Name}"; PrimaryColor = new ColorRgba32(255, 255, 255, 255); SecondaryColor = new ColorRgba32(0, 0, 0, 255); CreateGridlines(); }
public static MagitekResult CopyPixels(DirectImage source, IndexedImage dest, Point sourceStart, Point destStart, int copyWidth, int copyHeight, params PixelRemapOperation[] operationAttempts) { var dimensionResult = CanCopyPixelDimensions(source, dest, sourceStart, destStart, copyWidth, copyHeight); if (dimensionResult.Value is MagitekResult.Failed) { return(dimensionResult); } if (ImageRegionContainsInvalidElements(source, sourceStart, copyWidth, copyHeight)) { return(new MagitekResult.Failed($"Source image copy region contains blank elements")); } if (ImageRegionContainsInvalidElements(dest, destStart, copyWidth, copyHeight)) { return(new MagitekResult.Failed($"Destination image paste region contains blank elements")); } foreach (var operation in operationAttempts) { if (operation == PixelRemapOperation.RemapByExactIndex) { if (CanExactColorRemapPixels(source, dest, sourceStart, destStart, copyWidth, copyHeight).Value is MagitekResult.Success) { ApplyExactColorRemapPixels(source, dest, sourceStart, destStart, copyWidth, copyHeight); return(MagitekResult.SuccessResult); } } else if (operation == PixelRemapOperation.RemapByExactPaletteColors) { if (CanRemapByExactPaletteColors(source, dest, sourceStart, destStart, copyWidth, copyHeight).Value is MagitekResult.Success) { ApplyRemapByExactPaletteColors(source, dest, sourceStart, destStart, copyWidth, copyHeight); return(MagitekResult.SuccessResult); } } else if (operation == PixelRemapOperation.RemapByAnyIndex) { } } return(new MagitekResult.Failed($"Image cannot be copied as no suitable copy method was found")); }
public static bool ExportArranger(ProjectTree projectTree, string arrangerKey, string projectRoot, bool forceOverwrite) { if (!projectTree.TryGetNode(arrangerKey, out var node)) { Console.WriteLine($"Exporting '{arrangerKey}'...Resource key not found in project"); return(false); } var relativeFile = Path.Combine(projectTree.CreatePaths(node).ToArray()); var exportFileName = Path.Combine(projectRoot, $"{relativeFile}.png"); var arranger = node.Item as ScatteredArranger; Console.Write($"Exporting '{arrangerKey}' to '{exportFileName}'..."); if (!Directory.Exists(Path.GetDirectoryName(exportFileName))) { Directory.CreateDirectory(Path.GetDirectoryName(exportFileName)); } if (File.Exists(exportFileName) && forceOverwrite == false) { Console.WriteLine($"File already exists and was skipped to not overwrite it"); return(false); } if (arranger.ColorType == PixelColorType.Indexed) { var image = new IndexedImage(arranger); image.ExportImage(exportFileName, new ImageSharpFileAdapter()); } else if (arranger.ColorType == PixelColorType.Direct) { var image = new DirectImage(arranger); image.ExportImage(exportFileName, new ImageSharpFileAdapter()); } Console.WriteLine("Completed successfully"); return(true); }
/// <summary> /// Creates a new IndexedImage from a DirectImage /// </summary> /// <param name="direct">The source DirectImage</param> /// <param name="arranger">The arranger containing palettes for color conversion</param> /// <returns></returns> public static IndexedImage ToIndexed(DirectImage direct, Arranger arranger) { throw new NotImplementedException(); //if (direct.Width != arranger.ArrangerPixelSize.Width || direct.Height != arranger.ArrangerPixelSize.Height) // throw new ArgumentException($"{nameof(ToIndexed)} must have matched image dimensions. " + // $"{nameof(DirectImage)}: ({direct.Width}, {direct.Height})" + // $"{arranger.Name}: ({arranger.ArrangerPixelSize.Width}, {arranger.ArrangerPixelSize.Height})"); //var indexed = new IndexedImage(arranger); //for (int y = 0; y < direct.Height; y++) //{ // for (int x = 0; x < direct.Width; x++) // { // var pal = arranger.GetElement(x, y).Palette; // var color = pal.GetIndexByNativeColor(direct.GetPixel(x, y), true); // indexed.SetPixel(x, y, color); // } //} //return indexed; }