Bounty proposal: Paint
Pages: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ... 27
Rick Murray (539) 13806 posts |
Indeed, for the simple dialogue, one could throw away a fair few options – do we really need more colours than 16, 256, 16M there? Given a palette/transparency can be added from the menu, we don’t need ask about those either. Here’s something I cobbled together in a couple of minutes in TemplEd to illustrate what I mean: |
Jeffrey Lee (213) 6048 posts |
Controversial question: should ‘legacy’ sprites be supported in terms of being saved? That would almost certainly require more effort than simply supporting the use of old formats throughout Paint. Paint mainly uses OS SWIs to interact with the sprites, and the OS SWIs contain full support for the old formats. So to remove support for old formats all you’d really be doing is adding an extra bit of code to the file loading in order to perform the conversion. If the issue is that the UI is overcomplicated, the solution is to fix the UI (e.g. have “Simple” and “Advanced” versions of the new sprite dialogue as suggested by RIck). Throwing out or limiting support for old sprite formats will just lead to new problems in other areas. |
Chris (121) 472 posts |
Although I can see the reasoning for it, I don’t think two versions of the dialogue would be an improvement – it’s another click through to get to the options that’ll be needed fairly often. |
Andy S (2979) 504 posts |
I do like Rick’s layout, but yeah, any changes like this I will probably leave until the end or for someone else to attempt. |
Jeffrey Lee (213) 6048 posts |
A solution to that would be to have the dialogue remember the last state it was in (simple vs. advanced), at least until you quit the app. Perhaps it could also remember the settings that had been made (less clicking if you want to create lots of sprites with similar settings). |
Andy S (2979) 504 posts |
Quick question, for Jeffrey mainly. Yes, some kind of airbrush functionality could be nice, and shouldn’t tread on the toes of commercial image editors too much. It’s also something that could be made to work on older OS versions (alpha-masked brush sprites probably wouldn’t work on older OS’s due to the kernel not understanding them, but a simple brush opacity value would work as translucent sprite rendering can be handled by SpriteExtend+BlendTable+InverseTable softloads) I still need to do a bit more reading up on exactly how the palettes and colour translations work, but are we saying the Opacity functionality can work acceptably in low colour modes? I know a lot of modern graphics applications demand you convert to 16M colours before allowing certain tools. I can see how opacity could probably work in 256 colours by looking up the closest match in the palette but is there any point in even trying to support it in <= 16 colour sprites? |
Rick Murray (539) 13806 posts |
Plural? Is there one other than PhotoDesk these days? |
Jeffrey Lee (213) 6048 posts |
Limiting it to >=256 colour (or maybe just true colour) sprites sounds fine to me. The quality does definitely drop off at lower colour depths, and if it’s an airbrush where the effect is being applied over and over again to the low-quality destination then that’s just going to compound the issue. |
Rick Murray (539) 13806 posts |
What might be a nice extension is to have Paint able to convert from one sprite type to another? Never lose track of the fact that Paint is really really good for pixel level editing. I’ve tried a few programs in my life (Imagery, ProArtisan, PhotoDesk, etc) and while they offered lots of options for fancy colour channel work, they utterly sucked when it came to simple pixel level retouching. This is something Paint does well because the default tool is a simple “change pixel”, not a powerful tool bring bludgeoned into use like that (but with side effects like slightly tinting a dozen pixels either side of the one you want to change). |
Colin Ferris (399) 1809 posts |
Rick – DA’s Picture! |
Chris Hall (132) 3554 posts |
One facility not present in !Paint (but available in !DPlgScan or !ImgMaster and externally via !ChangeFSI) is to change colour depth (using interpolation where reducing) so that an 8bit sprite can be made into the equivalent 24bit sprite so that it can be edited in !PhotoDesk (which can’t edit colour spritres except 16M colours). |
Andy S (2979) 504 posts |
Hi, time for a quick progress update :). I’ve got the minimal functionality working for editing the alpha channel. It lets you edit it as a separate greyscale image which is then applied to the main colour image. It’s nowhere near ready for anyone else to test yet and right now it only works with a 32 bit sprite, but it’s a start. Here’s a teaser of it in action (sorry for the dodgy doodle – seems quite appropriate for Paint though ;) ): It’s nice to see how the existing Paint code blends the colour into the striped transparent background – I’ve been thinking this gives us a good way to allow editing of alpha in place as well. I’d quite like to add an Increase/Decrease Alpha tool to Paint that would work well with that. Of course when I get an Opacity slider working you could maybe use that with the transparent colour to decrease alpha values, but you’d still need the other tool to increase them again! |
Chris (121) 472 posts |
Great stuff! |
Jeffrey Lee (213) 6048 posts |
Looks good!
Yeah, I guess that’s the only real option for alpha channels at the moment. In-place editing of alpha masks should be pretty straightforward – you can redirect screen output to them and they’ll be treated as a 256 grey image. However for alpha channels we currently don’t have any support for that (essentially we’d have to teach the OS about a whole set of new pixel formats, and all the rendering operations for those pixel formats would have to read-modify-write for each pixel… ouch) I don’t think we have a builtin way of directly rendering an alpha channel or alpha mask to the screen (there are the “plot sprite mask” ops, but they haven’t been extended to work sensibly with alpha). But if you clear the screen to black and then plot the sprite using a colour mapping function which just returns white then it should have the desired effect (the colourmap function isn’t supplied the alpha of the pixel, but it is called before the alpha is applied – so by returning white and plotting on a black background you’ll get the desired gradient from black-white). Or for <=256 colour sprites you could supply a palette which maps everything to white. |
Andy S (2979) 504 posts |
Thanks guys! In-place editing of alpha masks should be pretty straightforward – you can redirect screen output to them and they’ll be treated as a 256 grey image.Excellent, thanks, I didn’t know you could do that. Could you point me to the SWI / function call please? for alpha channels we currently don’t have any support for that (essentially we’d have to teach the OS about a whole set of new pixel formats, and all the rendering operations for those pixel formats would have to read-modify-write for each pixel… ouch)Yeah I couldn’t find anything so I’ve started rolling my own C function to write the sprite’s alpha values for each of the different formats. I needed it to apply the greyscale image to the colour sprite when the user is done editing. In theory this code could be reused for in place edits but I guess that approach breaks down where Paint is (I think) using OS functions for drawing things like lines and circles – I don’t want to end up rewriting every tool! Maybe they could render twice, once to the colour sprite, once to the greyscale image and then the images could be merged but the code would get very messy and this would also be pretty slow on very old machines I think. At the moment on RPCEmu my merge of the greyscale image into the alpha channel seems to run almost instantaneously but I’m sure it wouldn’t on old Archies. At some point it might be worth converting it to optimized assembler, if it’s not replaced with an OS function. But if you clear the screen to black and then plot the sprite using a colour mapping function which just returns white then it should have the desired effect Cunning, thanks! |
Jeffrey Lee (213) 6048 posts |
In-place editing of alpha masks should be pretty straightforward – you can redirect screen output to them and they’ll be treated as a 256 grey image. sprwindow_swap_output_to_mask in SprWindow.c (which calls OS_SpriteOp 61), and sprwindow_swap_output_to_screen to restore screen output. It looks like the ‘statesaved’ parameter to sprwindow_swap_output_to_mask should be set to 1 if the output has already been switched to the sprite image, in order to prevent the global savedVDUstate register block from being overwritten (since the OS_SpriteOp call will update it with the values you need to use to restore the previous redirection state). Also while looking at the functions (sprwindow_swap_output_to_sprite and sprwindow_swap_output_to_screen) it doesn’t look like they’re using VDU save areas – that may have to change in order for painting of outline fonts to work reliably if/when you tackle the Text tool improvements task.
I expect C will be fine. There are only three different alpha channel formats to deal with, and all the machines that Paint is expected to run on include a data cache, so as long as you keep the inner loop nice and simple (i.e. have different variants of the routine/loop for each alpha format) there shouldn’t be any performance issues. It looks like Paint uses OS_ChangedBox to track which areas of the sprite are being affected by tools (so it can then redraw the corresponding part of the screen), so if you wanted to update the sprite’s alpha channel in real time you could also use that change information to limit how much of the greyscale sprite is copied back into the alpha channel. |
Andy S (2979) 504 posts |
It looks like Paint uses OS_ChangedBox to track which areas of the sprite are being affected by tools (so it can then redraw the corresponding part of the screen), so if you wanted to update the sprite’s alpha channel in real time you could also use that change information to limit how much of the greyscale sprite is copied back into the alpha channel. That’s useful, thanks. That may also come in handy for an Undo / Redo function, as I’ve been thinking saving the rectangles that changed might be a simple way of achieving that. Another option that occurred to me for direct editing of alpha channels, although it’s an awful cheat, might be to just always use alpha masks internally and only convert to an alpha channel at the point the sprite is saved (since currently any system that supports alpha channels should support alpha masks too, shouldn’t it?). There’s a sense that this would be misrepresenting to the user the sprite that Paint created in memory and I can see how it might break if support for alpha masks changed in a future OS but I can’t see any other issues with it. Well, saving would be slower. A slightly uglier but more honest compromise might be when the user attempts an in place edit of the alpha channel, a dialogue could pop up saying they needed to convert it to an alpha mask first and did they want to do this. I don’t really like this approach much either though as even the opacity sliders should arguably support the alpha channel if it is present. |
Jeffrey Lee (213) 6048 posts |
Actually the big problem with undo/redo is that you need to make a copy of the sprite before you start editing it – it’s no good having a box that tells you what’s changed if you don’t have a copy of the original data. So you’d probably want to make it so that before a sprite is edited for the first time it will make a copy of the sprite so that it can use it as a reference for building the undo buffer entries. (And after each edit, once the undo entry has been created, it will update the copy of the sprite to keep it in sync with the real version). Possibly this could all be done with sprite areas – e.g. the undo buffer for each sprite is actually a sprite area containing the backup copy of the sprite and a series of smaller sprites, each one representing an undo action. You’d also have a separate “undo index” which tells you e.g. what coordinates each of the small undo sprites should be restored to. By doing it this way you might be able to implement it all using standard OS SWIs, avoiding the need to copy pixels or manipulate sprites directly. Or maybe it would be easiest to just do a binary diff of the old and new sprite and use a basic compression algorithm like RLE to add the changed bytes to a buffer, I’m not really sure :-)
Yeah, I did consider suggesting that as an option. The only problem I can see is that for 4K colour sprites it would end up misrepresenting how much information the alpha channel can store – while you’re editing it would look like it’s got 8 bit alpha but then when you save it would get reduced to 4 bit alpha. (32K colour sprites would have a similar issue, but they can be catered for by converting the alpha to a regular transparency mask rather than an alpha mask) |
Andy S (2979) 504 posts |
@ Chris (121) I think it would be great to see some changes to Paint, and would be very happy to test out changes if that’s helpful. Hi Chris, if you’d be interested in testing the feature to make the spray tool take into account CPU speed, can you give me an e-mail address to send you a build please? Thanks! |
Andy S (2979) 504 posts |
If anyone else would like to help out with a quick test of what I’ve been doing for this bounty, here’s my code for a couple of features that need testing, including a debug build (Disc environment). I’ve only tested on RPCEmu so far with RISC OS 5 so would quite like to know how it runs on other machines and OS versions. The features in this build are: -Make spray rate take into account CPU speed – hard to perform a light spray on modern machines I don’t have a PS/2 wheelmouse and RPCEmu won’t support my USB mouse wheel (had to hack Madness to send scroll requests to test!) so please I really need someone to test the zoom functionality. It should zoom in with Ctrl+Wheel Up, zoom out with Ctrl+Wheel Down. Without Ctrl pressed it should scroll the scroll bars. The easiest way to test the spray rate is to run my build of Paint alongside the existing Paint version. On a fast machine, the spray can should apply more slowly for a given density with my build and because it’s linked to time it should be more consistent across different machines. It may even apply a bit faster on an old machine than the standard Paint but I’ve not been able to test this myself so would be interested to hear. The file’s an ArcFS archive. Many thanks! |
Chris (121) 472 posts |
Oops – completely missed this post! Sorry about that. I’ll download the test archive and give it a play later this weekend. That’ll be on a Pi, and I can test out on RPCEmu too. Looking forward to it! By all means drop future builds to cdwraight at yahoo dot co dot uk and I’d love to test them out :) |
David Pitt (102) 743 posts |
Some tests on a Titanium.
It zooms, but in rather large steps. One step at a time of the scroll wheel goes 1:6, 1:1, 6:1, 11:1, 16:1.
The new version is certainly a lot slower, too slow perhaps. The current version is almost an instant circle on pressing select. HTH. |
Andy S (2979) 504 posts |
I’ll download the test archive and give it a play later this weekend. That’ll be on a Pi, and I can test out on RPCEmu too. Excellent, thanks very much Chris! It’ll be interesting to see how the Pi compares as well. |
Andy S (2979) 504 posts |
Some tests on a Titanium. Thanks David! It zooms, but in rather large steps. One step at a time of the scroll wheel goes 1:6, 1:1, 6:1, 11:1, 16:1. Hmm, that’s odd. One scroll event should bump the zoom ratio by one step (e.g. from 1:1 to 2:1 or 2:1 to 3:1 or 1:3 to 1:2), so maybe the driver is generating multiple subsequent events per step of the wheel. I’ll have to wait and see how it behaves on the other hardware I guess or code a speed limit on the zoom. The new version is certainly a lot slower, too slow perhaps. The current version is almost an instant circle on pressing select. Slow is good, as you can increase the density to 999 and for me on RPCEmu that gives an almost instant circle with my build. There is a speed constant that can be tweaked (hard coded at the moment), so it could be sped up a little bit, or we could change Paint’s default spray density value. Again, I think we need to see how it performs on the other systems. Thanks again. |
Steve Fryatt (216) 2103 posts |
It zooms, but in rather large steps. One step at a time of the scroll wheel goes 1:6, 1:1, 6:1, 11:1, 16:1. That sounds suspiciously like a comment in the NetSurf source1, which notes that [some versions of] RISC OS 5 can send five copies of scroll events to applications under some circumstances. It’s not something that I’ve ever knowingly coded for myself in my own applications, but the multiples of five zoom steps made me think of it. It might well be an intentional and documented feature of the Wimp, of course… 1 See http://source.netsurf-browser.org/netsurf.git/tree/frontends/riscos/window.c?id=release/3.6#n3030 |
Pages: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ... 27