Jump to content

Zagna

Members
  • Posts

    510
  • Joined

  • Last visited

  • Days Won

    2

Posts posted by Zagna

  1. So.... I wanted to try and add blend modes but stumbled on a problem.

    In GetLayerXmlData, if I use layer.BlendOp.ToString() it returns the localized string instead of a generic english version.

    So.... somebody help? What am I doing wrong?

  2. I just thought up a complex way of doing something a little like that...

    1. Create a new layer
    2. Draw a line on that new layer, thick or thin
    3. Select the line with either a magic wand or whatever you want
    4. Hide the new layer
    5. Select the original layer
    6. Now your operation is limited in the selected area

    That could be one way of going around it?

  3. I just noticed there's a lil bug somewhere in the code...

    stack.xml has the right dimensions, but for some reason the lowest and rightmost strips of pixels are discarded completely.

    so layer0.png is 1 pixel shorter and thinner....

    null54 to the rescue?

    Edit: the culprit seems the be bounds in OnSave and the unsafe bit...

    Edit2: +1 addition to the rescue! :P .exe in the first post has been updated

    // bounds = new Rectangle(left, top, (right - left), (bottom - top)); // clip it to the visible rectangle
    
    bounds = new Rectangle(left, top, (right - left)+1, (bottom - top)+1); // clip it to the visible rectangle

  4. The .exe doesn't magically update itself :)

    When null54 saves the plugin by giving updated code, I gotta copy that code into VS 2010, compile it, test it quickly, wrap it in the NSIS installer and then copy it to the download location.

    And right now the installer has been updated with null54's latest version so it should work once again :D

  5. Ok, here goes nothing  :Xemote:

    So after finding Pinta's OraFormat.cs and pitching it at others here, null54 came to the rescue and fixed everything. And shrike asking to publish it, here's my attempt.

    Thanks go to Maia Kozheva and null54. :mtdew:
    New 4.1.5 version for 2019 with blend mode change
    So there it is, hope it works and.... something.
    • Upvote 1
  6. According to Wikipedia, at least 6 programs have support for it. So maybe it might reach some level of usage. And it seems to have potential for growth.

    With null54's code, I got it to work :D

    
    // myLayer.Opacity = ((byte)(255.0 * double.Parse(GetAttribute(layerElement, "opacity", "1"))));
    
    myLayer.Opacity = ((byte)(255.0 * double.Parse(GetAttribute(layerElement, "opacity", "1"), CultureInfo.InvariantCulture)));
    
    

    and

    
    // 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("opacity", ((double)(layers.GetAt(i).Opacity / 255.0)).Clamp(0.0, 1.0).ToString("N2", CultureInfo.InvariantCulture)); // this is even more bizarre 
    
    

    were the only changes required. The first fix made loading a file possible and the second change (it looks insane :D) fixed saving because it was doing '1,00' on my computer instead of 1.00

    So thanks goes to null54 :D:mtdew: and :pizza: for you :D

  7. So I tried using Pinta's OraFormat.cs to make it use Paint.NET's datatypes and ways... lots of copy paste.

    onload atleast is without errors what VS seems to think but ofcourse it doesn't work. OnSave is hopeless. All the commented stuff in OnSave is from OraFormat.cs

    So to those who are better at C#, help? I used Simon's template.

    // Author of OraFormat.cs: 2010 Maia Kozheva <sikon@ubuntu.com>
    
    using System;
    using System.IO;
    using System.Drawing;
    using System.Xml;
    using PaintDotNet;
    using PaintDotNet.Data;
    using ICSharpCode.SharpZipLib.Zip;
    
    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" })
    		{
    		}
    
    	protected override Document OnLoad(Stream input)
    		{
    		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 XmlException("No layers found in OpenRaster file");
    
    		for (int i = 0; i < layerElements.Count; i++)
    			{
    			XmlElement layerElement = (XmlElement)layerElements[i];
    			int x = int.Parse(GetAttribute(layerElement, "x", "0"));
    			int y = int.Parse(GetAttribute(layerElement, "y", "0"));
    			string name = GetAttribute(layerElement, "name", string.Format("Layer {0}", i));
    
    			ZipEntry zf = file.GetEntry(layerElement.GetAttribute("src"));
    			Stream s = file.GetInputStream(zf);
    
    			// var myLayer = new BitmapLayer(x, y); // is this right?
    			var myLayer = Layer.CreateBackgroundLayer(x, y); // or is this better?
    			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 = bool.Parse(GetAttribute(layerElement, "opacity", "1"));
    
    			myLayer.Surface.CopyFromGdipBitmap(new Bitmap(s)); // does this make sense?
    
    			doc.Layers.Insert(0, myLayer);
    			}
    
    		return doc;
    		}
    
    	protected override void OnSave(Document input, Stream output, SaveConfigToken token, Surface scratchSurface, ProgressEventHandler callback)
    		{
    		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++)
    			{
    
    
    			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);
    
    		/* // 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();
    		*/
    
    		stream.Close();
    		}
    
    	private byte[] GetLayerXmlData(LayerList layers) // OraFormat.cs - minor changes, no idea if still works
    		{
    		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--)
    			{
    			writer.WriteStartElement("layer");
    			writer.WriteAttributeString("opacity", layers.GetAt(i).Visible ? "0" : 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.WriteEndElement();
    			}
    
    		writer.WriteEndElement(); // stack
    		writer.WriteEndElement(); // image
    
    		writer.Close();
    		return ms.ToArray();
    		}
    
    	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() };
    		}
    	}
    }
    
    

  8. Maybe it could be possible for some of our more experienced developers here to try and translate the Pinta implementation of OpenRaster?

    https://github.com/j...ts/OraFormat.cs

    With an external plugin, any licensing would be free choice to the dev?

    I gave it an attempt myself... but with no PDN experience(and equally little C# experience) all I could hope is get no errors from Visual Studio with regards to proper datatypes and stuff with OnLoad, OnSave was way more complicated. And even then it didn't work :D

    Maybe I could put my miserable attempt in the plugin dev central and someone(s) could fix it?

  9. Your problem is that you're using a tool for Valve Hammer, which is used for creating game mods for Half-Life.

    You need ResGen.exe from Microsoft which is from the .NET Framework, which you can get simply by downloading any of the Windows/.NET SDKs.

    I attached both resgen and a compiled version of your strings. 

  10. *blush* :red: me, an experienced translator?   :red:

    From my point of view, it would be best for something like this:

    • Plugin authors would use the internal localization in some way, such as when setting the dialog texts, use whatever method is used to get a string from PdN and supply the method with a default string if the string isn't found in Strings.xx.resources.

    • That way even if the xml entries don't exist in the resources it would use the default english that's in the code?
    • Then the plugin author would list a set of strings in a <code> bit at the end of the topic posting the plugin. Stuff like Madjik.Effect1.VarA or BoltBait.EffectC.VarX and so on.
    • Then I could just copy paste the xml into my own Strings.xx.resx and translate there.

    The plugin author would just have to use the internal resource manager and all the translators are left to choose which plugins to translate.

    Having to work with the plugin author to translate and creating multiple versions sounds insane and prone to errors and any changes to translations would create a logistics nightmare.

    Leaving the translation to me and my own Strings.xx.resx is in my opinion the best solution. 

  11. So, as far as I can see, each string contain in average 3 words, which makes us approximately 3,5K words.

    Quick check of the english resx, Notepad++ counted 5987 words. After stripping the xml tags away.

    Now can I ask you where I can find the help files? I suppose they are in .html format?

    One easy way to get the help files is to get WinHTTrack and have it spider through http://www.getpaint.net/doc/latest/en/ to some folder. It'll get all the html files and images easily.

    The word count on the help files is a whole matter on its own.

    Edit: Quick check of my .fi help files and I got about 14k words there. No idea on the english ones.

  12. Odd rounding when there shouldn't be any rounding?

    I was updating some of the help images and just doing misc stuff, then I chose rectangle select, fixed size and switched the inches to pixels and got weird results.

    The resolution was the standard 96px/inch and somehow the default 4 and 3 inches measurement ended up being 383.9976 pixels and 287.9972 pixels.

    Can't repro it now, but I'll try to keep a look out for it if it happens again.

    Edit: This is on Windows 7 Pro x64.

    Edit2: Opened those pics again and this time the result was 383.944 and 287.958.

    It's not that big of a problem but still odd?

  13. If anyone wants to use this, here's something little for plugin makers. I use this for finnish language pack install.

    Hidden Content:
    ; Paint.nsi
    ; NSIS Paint.NET Effect/Language Pack Installer template
    ;---------------------------------------
    SetCompressor /SOLID lzma
    
    ; http://nsis.sourceforge.net/NsProcess_plugin
    ; Not mandatory but useful
    !include "nsProcess.nsh"
    
    Name "Installer name"
    OutFile "Filename.exe"
    XPStyle on
    ShowInstDetails nevershow
    CRCCheck on
    Icon "Icon.ico"
    ; Choose your own from %ProgramFiles(x86)%\NSIS\Contrib\Language files
    LoadLanguageFile "${NSISDIR}\Contrib\Language files\English.nlf" 
    AutoCloseWindow true ; Closes at the end of install
    SetOverwrite ifnewer
    RequestExecutionLevel admin ; Required so that you won't get 'Did this program install correctly' prompt after install.
    
    ; Pages
    
    Caption "Installer name"
    PageEx directory
    DirText "This install will copy files in the Paint.NET folder." ; Choose your own words
    Caption " "
    PageExEnd
    PageEx instfiles ; Most often people wont see this since it can take less than a second.
    Caption " "
    PageExEnd
    
    Section "" ; All files here, set directory first and then each file separately.
    SetOutPath $INSTDIR
    File Filename.resx
    SetOutPath $INSTDIR\Effects
    File Filename.dll
    SectionEnd
    
    Function .onInit ; Loaded first when installer is started.
    ; Can be removed if nsProcess plugin is not used.
    ${nsProcess::FindProcess} "PaintDotNet.exe" $R1
    ${nsProcess::Unload}
    StrCmp $R1 "0" 0 +3
    	MessageBox MB_ICONSTOP|MB_OK "Paint.NET is running. Close it and try again."
    	Abort
    ; Remove until here.
    SetRegView 64 ; Required for 64 bit OS support.
    ReadRegStr $R0 HKLM "Software\Paint.NET" "TARGETDIR"
    IfErrors 0 +3 ; If Abort is omitted, change the last number to +2
    	MessageBox MB_ICONSTOP|MB_OK "Paint.NET install not found. This file requires Paint.NET."
    	Abort ; This line can be omitted so that the user can input a directory even though the registry key was not found.
    StrCpy $INSTDIR $R0
    FunctionEnd

×
×
  • Create New...