Closed GoogleCodeExporter closed 8 years ago
Here is a proof-of concept patch that uses an SDL_Thread to change the palette.
It just changes color 0 from black to red slowly. Seems to work well.
Original comment by pulkoma...@gmail.com
on 2 Aug 2010 at 8:36
Attachments:
I used your POC to make a test where Grafx2 cycles all the ranges defined as
Gradients (with a fixed speed). It looks very sweet to be able to dynamically
change these, and see the result instantly. I watched all the Defender of the
Crown pictures, and the old "Waterfall" picture of Deluxe Paint.The speed is
impressive, in idle mode the program eats barely more CPU time than usual. (And
this is still on my Pentium3 600MHz)
I tested DP2E, the MS-DOS version. It is able to handle 16 gradients/cycles per
image, speed is set by a 1-63 slider again, and the direction of the shift can
be chosen (not in the ILBM spec).
One annoying thing we'll have to do is to attach all this cycling data to
history steps, for Undo/Redo for example. This is necessary so old cycle
settings are not inherited when you Load another image, or when you undo the
Load, swap to the spare, etc. This will make the cycling data more difficult to
reach from the other thread, as it will need to be cleanly protected from
concurrent access (Reading from Main_backups->Pages->things is not safe at all
times).
Some windows must freeze the cycling while they're open, and resume it
afterwards, for ex. the Palette.
The window where you design the cycling colors, on the contrary, must keep it
going - Changing the speed, especially, must activate the cycling so the user
sees the result.
So all in all, lots of small details but I don't see any serious roadblocks.
About file formats, we can always import IFF/ILBM. We must decide which formats
to save the cycling information.
IFF is possible if the cycles are within DeluxePaint limits (ie: continuous, no
more than 16...)
GIF is possible with a custom-made extension block
PNG is possible with a custom data block.
Original comment by yrizoud
on 2 Aug 2010 at 10:55
The function I used for my test:
http://pastebin.com/miSxSew3
Original comment by yrizoud
on 2 Aug 2010 at 10:58
Found a better IFF/ILBM specification here, that describes which bit performs
reverse cycling: http://netghost.narod.ru/gff/vendspec/iff/iff.txt
The formula for rate is : freq = rate * 60 / 1384
The DP2E speed slider is very weird, slider is rate/78, with some rounding
errors between loading and saving that I can't really explain (its 64, save,
re-load, it's 63). Anyway, DP2E allows speeds between 0.2856Hz and 18.28Hz, in
0.2856Hz increments. We should only find files with this range of speeds and
this granularity, even though the standard would allow rates between 0.00366Hz
and 240Hz, in 0.00366Hz increments.
Original comment by yrizoud
on 4 Aug 2010 at 12:26
Original comment by pulkoma...@gmail.com
on 9 Aug 2010 at 9:46
I think it's a good idea to add a link to the sumary of the IFF format on the
GFF (Encyclopedia of graphics file formats). There are links for the Spec
Yrizoud posted before and sample images too.
http://netghost.narod.ru/gff/graphics/summary/iff.htm
Although, I opened some of these samples on an hex editor and they look like
very basic ILBM files with no color cycling. They have a CAMG chunk too.
All the amiga .IFF files I have seen have an ILBM chunk on offset 0x8, right
before BMHD. The .LBM files saved by GrafX2 have an PBM chunk instead, that I
think is the same as Deluxe Paint. I don't know if it makes any difference or
point that the image uses a different standard or version or something. Joseph
Huckaby's lbm2json tool completely ignores what is writen on this offset,
jumping right to BMHD. Anyway, I think what Deluxe Paint do is the right think
to do for most uses anyway.
Original comment by jntesteves
on 9 Aug 2010 at 6:27
This summary is incomplete for my purpose, so I linked the other resources
instead.
I had tested all those samples: Venus is 8bit and loads correctly in Grafx2,
but the image looks very weird (same in XnView), others are 24bit RGB files and
don't load correctly in Grafx2.
About the chunk "ILBM" vs "PBM ", Grafx2 accepts only those two values, and has
different loading code for the two formats. It saves with "PBM ", the comment
saying "Planar BitMap".
Deluxe Paint 2E on MS-DOS can read both ILBM and PBM variants, but saves PBM
with 256 colors - just like Grafx2.
I can't easily test with files on Deluxe Paint 3 :/ I thought Grafx2 produced
compatible files (as long as less than 32 colors were used), but now I doubt
DP3 will read a PBM file.
Original comment by yrizoud
on 9 Aug 2010 at 7:39
I realize that my answer sounded harsh, it was not my intention. I was rather
bitter because many things are undocumented, old documents are false, and it's
very difficult to understand why Deluxe Paint sets some of the reserved bytes.
To recapitulate:
Images like those of the Amiga era were made on Deluxe Paint III. They are
ILBM, almost always 16 or 32 colors, but they could also be 64-color with some
palette restriction (EHB) or full 4096-color with severe pixel restrictions
(HAM). About color cycling, I'm using images from "Defender of the Crown" as
samples, since I already know how they work.
I also found the Waterfall from DP3 sample disk.
All the files I found had 4 ranges, with a maximum of 2 of them cycling.
(non-cycling ranges are only useful during drawing, they indicate the available
gradients)
Most old specifications of IFF / ILBM refer to the above format.
Mark Ferrari's incredible landscapes were made on DP2E. There is only one
format there: 256-color, PBM files. Such files (cycling or not) are the ones
made on the PC platform; I expect we can find more in the archives of the
demoscene. No real specification exists, but we can study how DP2E writes
files, it still runs perfectly on Windows (well, on 98).
Grafx2 loads all these formats, though I have some serious doubts about HAM.
When you save as "lbm" it saves in PBM format with 256-color palette, just like
DP2E.
I've checked, and DP2E can load ILBM files as well, but the saving is always
PBM. It also always saves 16 ranges, even if many of them are unused.
--> We can only find a maximum of 16 cycling ranges in an image. No need to
support more in Grafx2
Original comment by yrizoud
on 10 Aug 2010 at 1:09
It's all logical. Both versions of DP save the pixel data as it is in memory.
The amiga use planes, while the PC has a linear video ram format.
As for the ranges, I'm not sure what one could do with more than 16 ranges
anyway. I think it's rare that the whole palette gets cycled, and you need
multiple colors in the shade so that the effect works.
Note : it also works for Amstrad CPC's pictures, here we have 16 ranges of 16
colors each. But no one uses them anyway :)
Original comment by pulkoma...@gmail.com
on 10 Aug 2010 at 8:11
Implemented and working in r1574. It behaves identically to Deluxe paint III
(Amiga) and 2E (PC) : In the settings for gradients, there is a slider for
cycle speed. Every color range that has a non-zero speed will cycle.
Saving as ILBM saves only the cycling ranges: those with more than one color,
and a non-zero speed. Similarly, loading an ILBM file skips those that don't
follow these rules; (Deluxe paint would save even non-cycling ranges as
settings.)
I know it looks not-very-ambitious compared to all complicated things we could
think of, but I preferred getting something out while the HTML5 experiment is
still fresh - and we're compatible with Deluxe Paint files as input and output,
so this looks very functional.
The classic usage for cycling is a scrolling, but I realized there's more: If
all colors of a range are unused except one, the range will describe the color
changes of a single ink. So you can do any pulsating effect. A more complicated
usage: With 256 colors split in 16 ranges, you can make a 16-color picture that
passes through 16 different palettes over time.
I disabled cycling while a window is open, because it's almost impossible to
edit the palette, for example. Like in Deluxe Paint, the cycling temporarily
resumes while you hold the speed slider, so you get immediate feedback when you
change the speed.
Note that you can have several cycles that share some colors. When this
happens, the colors from range #1 that are not overwritten by range #2 cycle on
the whole range, while the colors of range #2 cycle over range #2. I'm having
difficulty checking if Deluxe Paint behaves this way, but honestly I don't see
how they could do any other way.
TODO:
The gradient screen needs to be made better-looking. I think I may need to
implement a horizontal slider for it. A "Cycle on/off" button must be added
anyway. Mouse wheel should browse the 16 ranges.
A shortcut for this button must be added. And the cycling must be off by
default, I think.
Save the cycling in GIF too (?)
Save the cycling in PNG too (?)
The system is a bit hackish, because the loaded cycles overwrite (some of) the
gradient settings; the gradient settings are saved without speed so the colors
don't cycle when you start grafx2 later; (not necessarily a bad thing); and if
you 'reload' the config it overwrites the current image's cycles. Need to think
about this.
Original comment by yrizoud
on 16 Aug 2010 at 4:09
Re: saving cycling info in PNG:
I think we could just save an ancillary 'cCYC' chunk (I'm suggesting cCYC to
follow the lead of http://r0k.us/graphics/png16Tech.html#colorCycling) in
exactly the same format as the ILBM color cycling saving.
GIF seems to require a bit more care, but we might be able to do the same thing.
Original comment by 00a...@gmail.com
on 17 Aug 2010 at 12:16
Ok about cCYC.
After some testing, I realize I also need to make separate cycling data for the
Main page and the Spare page.
Original comment by yrizoud
on 17 Aug 2010 at 12:18
Sample image to test various ways to use the effects: glowing goo, various
blinking lights, rotating gear, conveyor belt, and my favorite, the flowing
water.
Original comment by yrizoud
on 17 Aug 2010 at 4:32
Attachments:
I load the above file. It does one step of color cycling and then immediately
crashes:
grafx2: xcb_io.c:140: dequeue_pending_request: Assertion `req ==
dpy->xcb->pending_requests' failed.
fish: Job 1, './bin/grafx2 ' terminated by signal SIGABRT (Abort)
making a color cycling range using the gradients dialog and then adjusting the
speed to be >0 , results in a similar crash (again, after some cycling has
already shown up).
OS+package details:
Arch Linux
SDL 1.2.14
libxcb 1.6
xorg-server 1.8.1
Original comment by 00a...@gmail.com
on 18 Aug 2010 at 2:37
Looks like a threading problem, xlib doesn't seem to accept the way we update
the screen from 2 threads without any mutual exclusion.
On Windows, once every 5 minutes I get some display problems when opening
screens (missing refresh or palette that isn't completely reset), but they
never cause any crash.
I have an idea of how to change the cycling system so it no longer requires
threading.
Original comment by yrizoud
on 18 Aug 2010 at 8:59
00ai99 : Please try r1581, I attach a tgz to this post. It's incomplete, for
example the colors are not visually put back in the right slots when you open
the palette, otherwise it should totally eliminate the unstability. I'll
continue tomorrow.
Original comment by yrizoud
on 19 Aug 2010 at 12:38
Attachments:
oh thanks yrizoud (though I just updated from SVN, since it was quicker.). That
works perfectly OK for me, no crashes :)
I did notice though that perhaps the code that finds a best-matching color
should prefer colors that are not being cycled.. as with the lbm you provided,
some area of the palette surrounds flashes red every so often :)
Original comment by 00a...@gmail.com
on 19 Aug 2010 at 2:47
btw, isn't it possible to have the cycling thread only flag which gradients
need to be cycled, rather than doing the cycling? Then in the main loop,you'd
have to wake up MAX_HZ times per second, do any pending cycling and unflag
those gradients.
This is AFAIK the 'standard' way to do such things. We only really want cycling
on the main editing screen, right? Not any subordinate dialogs.
Original comment by 00a...@gmail.com
on 19 Aug 2010 at 2:56
00ai99: About best-matching colors, you mean the colors chosen for menu? Indeed
I must try to avoid it, even if I know that in many cases, there won't be
enough colors remaining.
About the implementation of timing, the 16 cycling ranges can have different
speeds that are not multiples of each others, so I couldn't rely on a fixed
frequency. Instead, I opted for a "delta time" system: Get current time,
compute which positions the gradients should be according to this time, and if
any of them is not the same as the last screen update, an update of the palette
and screen is required. This whole system must be called frequently enough to
get smooth movement, but not too often in order to limit CPU cost.
We can even easily add the interpolation system described by J Huckaby - but
it's optional, because it will force a full screen update at least 50 times per
second.
Original comment by yrizoud
on 19 Aug 2010 at 10:00
I'd add a thread for each cycling gradient, updating a struct with the info,
and let main actually set the palette when there is time for that.
The struct would of course need locking with a mutex, because of all those
threads writiing to it.
Original comment by pulkoma...@gmail.com
on 19 Aug 2010 at 12:35
...seriously? You'd make 16 extra threads increment counters, instead of the
single line of code:
new_offset=(now-start)/(int)(1000.0/(Gradient_array[i].Speed*0.2856)) % len;
(input.c:943)
Original comment by yrizoud
on 19 Aug 2010 at 1:35
Depends on what we want. Threads that sleep don't cost anything. If we start to
add colorblending and such stuff it may be good to have separate threads when
we use very slow cycling.
On the other hand, maybe I just spent too much time coding for HAiku and start
seeing threads everywhere :)
Original comment by pulkoma...@gmail.com
on 19 Aug 2010 at 8:20
If you just HAVE to use a thread somewhere, you can make Grafx2 still
responsive while color reduction is under way: Delegate worker thread to
perform the conversion, while main thread receives all events and can redraw
mouse cursor.
Original comment by yrizoud
on 19 Aug 2010 at 9:38
Yes, I was thinking about that too. Once I get some free time to dig into it
and do it properly (you don't want to fix all the bugs, do you ?)
Original comment by pulkoma...@gmail.com
on 20 Aug 2010 at 12:02
[deleted comment]
Original comment by pulkoma...@gmail.com
on 22 Aug 2010 at 1:39
By r1598, gradient screen is much improved. "Cycle on/off" button is there,
mouse wheel browses the 16 ranges, keyboard shortcut is there (default:
Control+Tilde), helpfile is up-to-date, cycling is off by default.
Cycling data is not saved in GIF or PNG, but I'm not sure if I should do it.
Still need to separate cycling data so the Main and spare images have their
own. Functions of "Copy to spare" should transfer cycling data when you choose
to copy palette.
Original comment by yrizoud
on 30 Aug 2010 at 12:09
I need cycling in gif/png :)
It's the only way to have cycling+layers...
Original comment by pulkoma...@gmail.com
on 30 Aug 2010 at 9:03
GIF was done (some time ago)
PNG will need to use some black magic formulas like:
For read: png_set_read_user_chunk_fn(),
For write: png_set_unknown_chunks()
Original comment by yrizoud
on 18 Jan 2011 at 8:11
TODO:
- save/load cycling data in PNG format
- on program startup, when loading default palette from skin: load cycling data
from skin too. Then update all skins so that they have good ranges according to
their palettes.
Original comment by yrizoud
on 8 Feb 2011 at 10:52
Almost done in r1715.
Works veeery well on startup, it picks up the gradient settings from your
selected skin, and puts it in the "noname" pictures that you're editing by
default.
Still has problem when loading an image from command-line, gradient is black
until you open the grad settings window. Anyway, issue is probably larger than
that, because now there are many causes for changing gradient settings (load,
undo, redo, swap) and yet the Load_gradient_data() is only called by the
settings window.
Original comment by yrizoud
on 9 Feb 2011 at 1:11
Solved now.
Original comment by yrizoud
on 16 Feb 2011 at 5:39
A technical reminder, since I had to search this information today :
Internally, Grafx2 stores Speed as the "speed slider" value, same as Deluxe
Paint.
0 = stopped
1 = IFF 78 = 0.2856 Hz freq = 3501 ms delay
64 = IFF 4991 = 18.28 Hz freq = 55 ms delay
70 = IFF 5461 = 20 Hz freq = 50 ms delay
Above is not usable in Deluxe Paint 3 (?)
105 = IFF 8192 = 30 Hz freq = 33.3 ms delay
Above is not usable in Grafx2, slider only goes up to 105
210 = IFF 16384 = 60 Hz freq = 16.6 ms delay
Original comment by yrizoud
on 30 Aug 2013 at 5:40
Original issue reported on code.google.com by
yrizoud
on 1 Aug 2010 at 10:14