• Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by null54

  1. That bug was a channel processing order issue, I was processing the color channels in BGRA order instead of the RGBA order that The Gimp and Photoshop use. File version updated to
  2. This plug-in hosts Adobe® Photoshop®-compatible filter plug-ins under Paint.NET. Many filters should run although some may have issues, both Flaming Pear's LunarCell as well as their Free Plugins work correctly. For instructions on installing 8bf filters see Installing 8bf filters. This plugin is compatible with Paint.NET 3.5.11 and 4.0.x. Download Place both PSFilterPdn.dll and PSFilterShim.exe in your Effects folder. Effects->8bf Filter... Source Code
  3. That seems to be a bug in the parser, although the same code runs perfectly on Gimp 1.2.5 which uses the same parser so I have no idea what is going on. The values it takes in are correct but it outputs red where the result should be white. The guf files seem to mostly be converted Filter Factory filters, and the filter source language used in the native guf filters is not backwards compatible with Filter Factory. The afs files will now enable the slider if the slider value is greater than 0 and the save txt function has been fixed again (the filter source code was never being saved I don't know how I missed that). File version updated to
  4. It will only run Photoshop plugins built with Filter Factory, it will just ignore the other Photoshop filters.
  5. The afs format only saves the slider values and source code, this is because it only asks for that information when the filter is built. It should now create the User data directory of it does not find it. The save txt function has been fixed and the syntax check now runs as you type. File version updated to
  6. // Author of OraFormat.cs: 2010 Maia Kozheva <> // // Copyright (c) 2010 Maia Kozheva <> // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. using System; using System.IO; using System.Drawing; using System.Xml; using PaintDotNet; using PaintDotNet.Data; using ICSharpCode.SharpZipLib.Zip; using System.Drawing.Imaging; namespace OpenRaster_Filetype { public class OraFileType : FileType { private const int ThumbMaxSize = 256; public OraFileType() : base("OpenRaster Image", FileTypeFlags.SupportsLoading | FileTypeFlags.SupportsSaving | FileTypeFlags.SupportsLayers, new String[] { ".ora" }) { } /// <summary> /// Gets the bitmap from the ora layer. /// </summary> /// <param name="xofs">The x offset of the layer image.</param> /// <param name="yofs">The y offset of the layer image.</param> /// <param name="inStream">The input stream containing the layer image.</param> /// <param name="baseWidth">The width of the base document.</param> /// <param name="baseHeight">The height of the base document.</param> private unsafe Bitmap GetBitmapFromOraLayer(int xofs, int yofs, Stream inStream, int baseWidth, int baseHeight) { Bitmap image = null; using (Bitmap layer = new Bitmap(baseWidth, baseHeight)) { using (Bitmap bmp = new Bitmap(inStream)) { BitmapData layerData = layer.LockBits(new Rectangle(xofs, yofs, bmp.Width , bmp.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat); int bpp = Bitmap.GetPixelFormatSize(bmp.PixelFormat) / 8; for (int y = 0; y < bmp.Height; y++) { for (int x = 0; x < bmp.Width; x++) { byte *dst = (byte*)layerData.Scan0.ToPointer() + (y * layerData.Stride) + (x * 4); byte* src = (byte*)bmpData.Scan0.ToPointer() + (y * bmpData.Stride) + (x * bpp); dst[0] = src[0]; // B dst[1] = src[1]; // G dst[2] = src[2]; // R if (bpp == 4) { dst[3] = src[3]; // A } } } bmp.UnlockBits(bmpData); layer.UnlockBits(layerData); } image = (Bitmap)layer.Clone(); } return image; } protected override Document OnLoad(Stream input) { using (ZipFile file = new ZipFile(input)) { XmlDocument stackXml = new XmlDocument(); stackXml.Load(file.GetInputStream(file.GetEntry("stack.xml"))); XmlElement imageElement = stackXml.DocumentElement; int width = int.Parse(imageElement.GetAttribute("w")); int height = int.Parse(imageElement.GetAttribute("h")); Document doc = new Document(width, height); XmlElement stackElement = (XmlElement)stackXml.GetElementsByTagName("stack")[0]; XmlNodeList layerElements = stackElement.GetElementsByTagName("layer"); if (layerElements.Count == 0) throw new FormatException("No layers found in OpenRaster file"); int layerCount = layerElements.Count - 1; for (int i = layerCount; i >= 0; i--) // The last layer in the list is the background so load in reverse { XmlElement layerElement = (XmlElement)layerElements[i]; int x = int.Parse(GetAttribute(layerElement, "x", "0")); // the x offset within the layer int y = int.Parse(GetAttribute(layerElement, "y", "0")); // the y offset within the layer int layerNum = layerCount - i; string name = GetAttribute(layerElement, "name", string.Format("Layer {0}", layerNum)); ZipEntry zf = file.GetEntry(layerElement.GetAttribute("src")); using (Stream s = file.GetInputStream(zf)) { using (Bitmap bmp = GetBitmapFromOraLayer(x, y, s, width, height)) { BitmapLayer myLayer = null; if (i == layerCount) // load the background layer first { myLayer = Layer.CreateBackgroundLayer(width, height); } else { myLayer = new BitmapLayer(width, height); } myLayer.Name = name; myLayer.Opacity = (byte)(255.0 * double.Parse(GetAttribute(layerElement, "opacity", "1"))); // double to byte? wtf am I doing... O_o there is a better way... right? >_> myLayer.Visible = (GetAttribute(layerElement, "visibility", "visible") == "visible"); // newer ora files have this myLayer.Surface.CopyFromGdipBitmap(bmp, false); // does this make sense? myLayer.Metadata.SetUserValue("oraPos", string.Format("{0},{1}", x, y)); doc.Layers.Insert(layerNum, myLayer); } } } return doc; } } protected override void OnSave(Document input, Stream output, SaveConfigToken token, Surface scratchSurface, ProgressEventHandler callback) { using (ZipOutputStream stream = new ZipOutputStream(output)) { ZipEntry mimetype = new ZipEntry("mimetype"); mimetype.CompressionMethod = CompressionMethod.Stored; stream.PutNextEntry(mimetype); byte[] databytes = System.Text.Encoding.ASCII.GetBytes("image/openraster"); stream.Write(databytes, 0, databytes.Length); for (int i = 0; i < input.Layers.Count; i++) { BitmapLayer layer = (BitmapLayer)input.Layers[i]; byte[] buf = null; using (MemoryStream ms = new MemoryStream()) { layer.Surface.CreateAliasedBitmap().Save(ms, ImageFormat.Png); buf = ms.ToArray(); } stream.PutNextEntry(new ZipEntry("data/layer" + i.ToString() + ".png")); stream.Write(buf, 0, buf.Length); } /*// OraFormat.cs for (int i = 0; i < document.Layers.Count; i++) { Pixbuf pb = document.Layers[i].Surface.ToPixbuf(); byte[] buf = pb.SaveToBuffer("png"); (pb as IDisposable).Dispose(); stream.PutNextEntry(new ZipEntry("data/layer" + i.ToString() + ".png")); stream.Write(buf, 0, buf.Length); } */ stream.PutNextEntry(new ZipEntry("stack.xml")); databytes = GetLayerXmlData(input.Layers); stream.Write(databytes, 0, databytes.Length); using (Surface flat = new Surface(input.Width, input.Height)) { input.Flatten(flat); Size thumbSize = GetThumbDimensions(input.Width, input.Height); Surface scale = new Surface(thumbSize); scale.FitSurface(ResamplingAlgorithm.SuperSampling, flat); using (MemoryStream ms = new MemoryStream()) { scale.CreateAliasedBitmap().Save(ms, ImageFormat.Png); databytes = ms.ToArray(); } scale.Dispose(); } stream.PutNextEntry(new ZipEntry("Thumbnails/thumbnail.png")); stream.Write(databytes, 0, databytes.Length); /* // OraFormat.cs ImageSurface flattened = document.GetFlattenedImage(); Pixbuf flattenedPb = flattened.ToPixbuf(); Size newSize = GetThumbDimensions(flattenedPb.Width, flattenedPb.Height); Pixbuf thumb = flattenedPb.ScaleSimple(newSize.Width, newSize.Height, InterpType.Bilinear); stream.PutNextEntry(new ZipEntry("Thumbnails/thumbnail.png")); databytes = thumb.SaveToBuffer("png"); stream.Write(databytes, 0, databytes.Length); (flattened as IDisposable).Dispose(); (flattenedPb as IDisposable).Dispose(); (thumb as IDisposable).Dispose(); */ } } private byte[] GetLayerXmlData(LayerList layers) // OraFormat.cs - minor changes, no idea if still works { byte[] buf = null; using(MemoryStream ms = new MemoryStream()) { XmlTextWriter writer = new XmlTextWriter(ms, System.Text.Encoding.UTF8); writer.Formatting = Formatting.Indented; writer.WriteStartElement("image"); writer.WriteAttributeString("w", layers.GetAt(0).Width.ToString()); writer.WriteAttributeString("h", layers.GetAt(0).Height.ToString()); writer.WriteStartElement("stack"); writer.WriteAttributeString("opacity", "1"); writer.WriteAttributeString("name", "root"); // ORA stores layers top to bottom for (int i = layers.Count - 1; i >= 0; i--) { string[] xyPos = null; string val = ((BitmapLayer)layers[i]).Metadata.GetUserValue("oraPos"); if (!string.IsNullOrEmpty(val)) { xyPos = new string[2]; xyPos = val.Split(new char[] { ',' }); } writer.WriteStartElement("layer"); writer.WriteAttributeString("opacity", string.Format("{0:0.00}", (double)(layers.GetAt(i).Opacity) / 255.0)); // byte to double? wtf am I doing... O_o writer.WriteAttributeString("name", layers.GetAt(i).Name); writer.WriteAttributeString("src", "data/layer" + i.ToString() + ".png"); writer.WriteAttributeString("visible", layers.GetAt(i).Visible ? "visible" : "hidden"); if (xyPos != null) { writer.WriteAttributeString("x", xyPos[0]); writer.WriteAttributeString("y", xyPos[1]); } writer.WriteEndElement(); } writer.WriteEndElement(); // stack writer.WriteEndElement(); // image writer.Close(); buf = ms.ToArray(); } return buf; } private Size GetThumbDimensions(int width, int height) // OraFormat.cs { if (width <= ThumbMaxSize && height <= ThumbMaxSize) return new Size(width, height); if (width > height) return new Size(ThumbMaxSize, (int)((double)height / width * ThumbMaxSize)); else return new Size((int)((double)width / height * ThumbMaxSize), ThumbMaxSize); } private static string GetAttribute(XmlElement element, string attribute, string defValue) // OraFormat.cs { string ret = element.GetAttribute(attribute); return string.IsNullOrEmpty(ret) ? defValue : ret; } } public class MyFileTypeFactory : IFileTypeFactory { public FileType[] GetFileTypeInstances() { return new FileType[] { new OraFileType() }; } } }
  7. A few more bugs in Build Filter fixed, File version updated to
  8. Build Filter should now be fixed.
  9. The samples have been changed to the ones from Filter Foundry so they should now work correctly.
  10. The cause of the banding was a thread collision issue, that is now fixed. That is what I get for not testing on a multi-core machine.
  11. My only guess is that it could be a bug in the parser.
  12. Do you have a screenshot of this? The output of the Filter Factory Example.afs filter should be: If not I am have no idea what the problem is.
  13. The zip has been updated with the official documentation and example code.
  14. This plugin allow some of the filters built with Adobe's Filter Factory plugin for Photoshop to be run in Paint.NET. The Filter Factory plugins use a C-style language to modify an image. If a Filter Factory filter does not work with this plugin you can use PSFilterPdn to run it. This plugin is compatible with Paint.NET 3.5.11 and 4.0.x. The Filter Manager will search the directories specified in the directory search list to for filters to display by category. The Build Filter button will build the loaded filter as a separate plugin for Paint.NET to use. A list of some of the Filter Factory filters is available at http://thepluginsite...rces/freeff.htm. The plugin icon is from the Silk icon set. Download: Source Code: The source code for the plugin and Filter Factory interpreter (ffparse). Both are licensed under the terms of the GNU General Public License.