guix Posted October 22, 2013 Posted October 22, 2013 (edited) Hello all, I need to make a FileExport plugin which export into a custom format, that is a binary file with 24 bits per pixel: 16 bits for RGB565 and 8bits for the alpha channel. No metadata, no header, just an array of bytes. The big problem is, I have absolutely no idea how to do this... I saw some sample plugins but they all look simple (even if I don't understand most of the code...), using things like: PixelFormat.Bgr565 or PixelFormats.Bgra32. Obviously my custom pixel format isn't in the list. For now, I just would like an example how to get pixels RGBA colors inside the OnSave(T?) callback. Then I can try myself to convert it to the format I need. And then I will probably come back here to ask other questions about how to actually write in the output file. You guessed, I am totally lost... Any help appreciated! Edited October 22, 2013 by guix Quote
midora Posted October 22, 2013 Posted October 22, 2013 (edited) Just flatten the input layers to the scratchsurface and write the pixels to the output stream. input.Flatten(scratchSurface); for (int row = 0; row < scratchSurface.Height; row++) { for (int column = 0; column < scratchSurface.Width; column++) { ColorBgra bgra = scratchSurface[column, row]; // write pixel to output stream } } Edited October 22, 2013 by midora 1 Quote
guix Posted October 22, 2013 Author Posted October 22, 2013 (edited) Hello midora, thank you for this. At least a start, let me try some things Edit: I only did that for now as a quick test: output.WriteByte(bgra.R); output.WriteByte(bgra.G); output.WriteByte(bgra.; output.WriteByte(bgra.A); And it worked... I can't believe how easy it was (but I couldn't have done it without your code) Edited October 22, 2013 by guix Quote
MJW Posted October 22, 2013 Posted October 22, 2013 Midora, could you please explain what Flatten does, or point me to something that does. It sounds like a function that might be useful for an idea I have. Quote
midora Posted October 22, 2013 Posted October 22, 2013 Flatten just merges all layers to one surface. If you need the data of all layers do: foreach (BitmapLayer layer in input.Layers) { for (int row = 0; row < layer.Height; row++) { for (int column = 0; column < layer.Width; column++) { ColorBgra bgra = layer.Surface[column, row]; } } } Maybe I should add some code to ExamplePropertyBasedFileType template. Quote
MJW Posted October 22, 2013 Posted October 22, 2013 Thank you very much Midora. I was under the impression that plugins don't have access to any layer except the selected layer. The ability to use the information from other layers surprises me, and seems to open some possibilities to do things with plugins I didn't know could be done. Quote
BoltBait Posted October 22, 2013 Posted October 22, 2013 This functionality is only available to filetype plugins, not effect plugins. Quote Download: BoltBait's Plugin Pack | CodeLab | and a Free Computer Dominos Game
MJW Posted October 22, 2013 Posted October 22, 2013 That's very disappointing. Is there a reason for that rule? Quote
BoltBait Posted October 23, 2013 Posted October 23, 2013 It is designed to prevent an effect from modifying pixels outside of the current selection. Quote Download: BoltBait's Plugin Pack | CodeLab | and a Free Computer Dominos Game
MJW Posted October 23, 2013 Posted October 23, 2013 (edited) I can see not allowing writing the other layers -- that shouldn't be allowed -- but I don't see why reading the other layers isn't allowed. It may well be that there's no way of enforcing no-writing if reading is allowed. But there are lots of things one could do in a plugin that aren't allowed, such a writing to pixels outside the passed slice of the current layer. I've seen a number of kludgy implementations of plugin functions using the clipboard that could be done much more elegantly and conveniently using another layer. Added: Actually, by using a C# property or indexer, reading could be allowed and writing prevented. Disregarding syntatic sugar, read access could be done through an old-fashioned function call. Edited October 23, 2013 by MJW Quote
guix Posted October 23, 2013 Author Posted October 23, 2013 (edited) Hello again, Nice to know that we can save layers separately, even if I don't need it actually So I managed to make a plugin that can save and load the custom format, which is great news (actually, just RGBA8888 but I don't have problem converting from/to my custom format "RGBA5658") Basically: protected override Document OnLoad(Stream input) { // The 4 first bytes of the file are the size of the image in pixels UInt16 sizeX = (UInt16)( (input.ReadByte() << 8) | input.ReadByte() ); UInt16 sizeY = (UInt16)( (input.ReadByte() << 8) | input.ReadByte() ); Bitmap bmp = new Bitmap(sizeX, sizeY, PixelFormat.Format32bppArgb); for (int column = 0; column < sizeY; column++) { for (int row = 0; row < sizeX; row++) { byte r = (byte)input.ReadByte(); byte g = (byte)input.ReadByte(); byte b = (byte)input.ReadByte(); byte a = (byte)input.ReadByte(); bmp.SetPixel(row, column, Color.FromArgb((int)((a << 24) | (r << 16) | (g << 8) | ); } } return Document.FromImage(bmp); } protected override void OnSave(Document input, Stream output, SaveConfigToken token, Surface scratchSurface, ProgressEventHandler callback) { //BinaryWriter binWriter = new BinaryWriter(output); input.Flatten(scratchSurface); UInt16 sizeX = (UInt16)input.Width; UInt16 sizeY = (UInt16)input.Height; output.WriteByte((byte)(sizeX >> 8)); output.WriteByte((byte)(sizeX & 0xFF)); output.WriteByte((byte)(sizeY >> 8)); output.WriteByte((byte)(sizeY & 0xFF)); for (int row = 0; row < scratchSurface.Height; row++) { for (int column = 0; column < scratchSurface.Width; column++) { ColorBgra bgra = scratchSurface[column, row]; output.WriteByte(bgra.R); output.WriteByte(bgra.G); output.WriteByte(bgra.; output.WriteByte(bgra.A); //binWriter.Write( packRGBA8888(bgra.R, bgra.G, bgra.B, bgra.A) ); } } //binWriter.Dispose(); } It works well enough for now, I'm just wondering if there is a better/faster way of doing the Load(). Any tips? Also another questions: What is the difference between OnSave and OnSaveT ? Does scratchSurface.Height and scratchSurface.Width always equals input.Height and input.Width ? Thanks. Edited October 23, 2013 by guix Quote
midora Posted October 23, 2013 Posted October 23, 2013 Because you are writing the size at the beginning of the file you are able to allocate memory and load all pixels in one block. Use unsafe pointers to convert to the bitmap if speed is important and your algorithm has been proven. Write a magic at the beginning of the file and check it on load. Quote
guix Posted October 26, 2013 Author Posted October 26, 2013 (edited) Sorry midora I don't understand what you said... But no problem, the code is still very fast, load/save speed isn't an issue at all. Meanwhile I have made a lot of progress, I have added an optional RLE-like algorithm (2 versions of it), this was easy to make and works quite well, sometimes produce a smaller file than equivalent 24bits PNG. Actually I'm making tests to see what is the best compromise filesize/code speed (these are images that will be loaded on a small TFT display controlled by an Arduino, I'm making a GUI library for it). But I would like to make an option "Autodetect" in the Save dialog, that will test some output modes (ex: with or without RLE v1, or v2...), and choose the one that makes a smaller file. Similar to the PNG Save dialog I guess. How can I do that, is it at least possible with plugins? Edit: auto detection done Edited October 29, 2013 by guix Quote
guix Posted October 30, 2013 Author Posted October 30, 2013 How can I change the extension of the file when saving? For ex if encoding method 1 is used, set extension to ".xg1", etc... Is it possible? Quote
null54 Posted October 30, 2013 Posted October 30, 2013 How can I change the extension of the file when saving? For ex if encoding method 1 is used, set extension to ".xg1", etc... Is it possible? It is not possible for a plugin to do this. Quote Plugin Pack | PSFilterPdn | Content Aware Fill | G'MIC | Paint Shop Pro Filetype | RAW Filetype | WebP Filetype The small increase in performance you get coding in C++ over C# is hardly enough to offset the headache of coding in the C++ language. ~BoltBait
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.