yaoshaojun / grafx2

Automatically exported from code.google.com/p/grafx2
0 stars 0 forks source link

Support for CPC graphics with rasters using layers... #342

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
I have made a tool to convert graphics for Amstrad CPC using rasters, now
the process consist in paint, convert, go back to the paint program to
retouch the picture for fix the "raster zones",... 

It would be great if the artist could draw using grafx2 and of course that
grafx2 encourage the limitations of the format.

Now, i have two formats:
1.- Mode 5: Is a cpc mode 1(320x200x4) using rasters, in this mode you have
one ink fixed for all the screen, two inks fixed for each line and the
fourth ink can change each 48 pixels, the screen size is 288 x 256 pixels.
The palette is storage in the next order: Fixed colour, the two colours
fixed for the first line, the six variable colours for the first line, the
two colours fixed for the second line, the six variable colours for the
second line,... 

2.- Mode 6: Is a cpc mode 2(640x200x2) using rasters, in this mode you have
one ink that is fixed for each line and the other ink can change each 96
pixels, the screen size is 672 x 256 pixels. The palette is storage in the
next order: Fixed colour for the first line, the seven variable colours for
the first line, the fixed colour for the second line, the seven variable
colours for the second line,... 

A few notes about this formats, the height of the picture can be changed
without problems; and the width needs to be multiply of 48 pixels in mode 1
or 96 pixels in mode 2. 

It would be a lot of more flexible and usefull for make new raster modes or
use a similar approach for other 8 bits computers, if you could define the
width in pixels and the maximum number of color that you can use in the
rasters zones, the number of colors fixed for the picture and the number of
colors that change each line.

The format for the files to load and save could be a raw dump of the
picture and the palette, but it's not necessary, it could use png perfectly
and i think that it's the best, because the really important it's that the
artist can use grafx2 to make this kind of pictures.

I have attached a few examples with pictures in mode 5.

PulkoMandy has told me that it could be possible to make using layers, one
for the picture and other for the rasters, and i think that it's very
logical. Would it be possible? Is it all clear or it's needed more
information, code examples,... ?

Original issue reported on code.google.com by real.mml on 27 Apr 2010 at 9:08

Attachments:

GoogleCodeExporter commented 9 years ago
Prior discussion is on Issue 202.

A small note : It is impossible to write a generic constraint solver. I am sure 
of 
it, because even a specific constraint format (C64 FLI) has never been solved. 
I 
wrote a checker, but there are some pictures it can't solve if the user doesn't 
give 
hints to override its auto-detection. Even brute-force is not viable as it 
would 
take years for some pictures.

Mode 6 seems to go well with the "Enforcer" way of drawing idea, because every 
pixel 
is using either the line ink or the raster ink. With an enforcer system, this 
is 
what would happen wen you paint one pixel with a color different from the 2:
If the target pixel uses the line ink:
  If the 96x1 block isn't using any raster ink:
    You draw pixels with your selected color, which becomes the raster ink for this 
block
  Else
    Replace the line ink for the whole line (recolor other pixels that use it)
  End
Else (the target pixel uses the raster ink)
  Replace the raster ink for the whole 96x1 block (recolor other pixels that use it)
End

Mode 5 can't be used with the Enforcer system, because the constraints are too 
fuzzy 
to be auto-detected from the current image.

For FLI, I made a prototype where the user interface was the following:

User sees his complete/final image in one layer. He draws directly and freely 
on it, 
with no constraints. He can break the limits.
When he wants to chek, he uses a keyboard shortcuts that solves the image (find 
a 
way to encode it). Some parts can't be be encoded if the limits are broken OR 
if the 
algorithm just didn't find a way, so these parts are modified into something 
that 
can be encoded (ie: some pixels change to a valid ink). The output is written 
on a 
opaque layer above the normal one, never directly on the user image. To find 
the 
problem areas, the user toggles this layer on and off. He fixes the areas by 
modifying his original, and running rhe checker again. If/when both layers are 
identical, it means the image is fully compliant.

Let me know if you think such a system would be viable. I didn't get much 
feedback 
from the C64 people so far (just a reminder guys... I don't know if I should 
proceed 
or try another approach)

Original comment by yrizoud on 28 Apr 2010 at 10:15

GoogleCodeExporter commented 9 years ago
Hi yrizoud, i have read your prior discussion about draw for retro systems.

Well, faced with the impossibility of a generic constraint solver, i think that 
your
"Checker" is a great solution for the case of mode 5, of course it will need a 
system
to define the constraints or permit to select from a list (hires bitmap, fli, 
mode 5,
zx, ... ) to make the more flexible possible. 

I am thinking now that it would be very helpful (i don't know if it's 
possible), if
you could see in the palette which are the colours of the actually "raster 
zone", at
the begining all the colours of all "raster zones" are the colour 0, and if you 
plot
with a new colour, this colour is selected for this zone,... What do you think? 

And of course, your "Enforcer" system is perfect for the mode 6.

Original comment by real.mml on 28 Apr 2010 at 2:13

GoogleCodeExporter commented 9 years ago
I would not use the palette to show raster boundaries, but instead use layers. 
For 
mode 2+rasters, it's easy : one layer is monochromatic (1 color per line or 
transparency), the other below has the splits rasters.

Ideally, I'd like to make this 3 layers : one for the split-ink, one for the 
raster 
ink, and one for the pixel data. This can't be done with the current layer code 
but 
I'd like to add it. This would extend much better to a mode 1+raster system. 
The 
"pixel" layer would act as a selector between the colors in the others layers. 
The 
raster layers could also be small ones (8x200 pixels or so) and stretched up to 
fit 
the picture. Or they could simply be RLE-packed, saving a LOT of memory, when 
not 
used.

This is for the technical part, using this directly for drawing may or may not 
be 
practical. On one side it enforces the constraint, but on the other it makes it 
painful to draw and not efficient. Drawing freely+running a check from time to 
time 
looks better. As the raster area are quite small (1 line * 96 pixels at most), 
it's 
easy to see which colors are used in each zone and build up the pixel+raster 
data 
from this. I'll try to think about a clever algorithm/data structure to do it 
efficiently.

Original comment by pulkoma...@gmail.com on 28 Apr 2010 at 5:10

GoogleCodeExporter commented 9 years ago
How i said, your explanation using layers is perfectly logical, Adrien. Is 
there 
anything that i can make to help?

Original comment by real.mml on 28 Apr 2010 at 8:48

GoogleCodeExporter commented 9 years ago
Adrien, in the "memory repesentation", don't forget that mode 5 also has a 
global
screen color. We could fill a complete layer to represent it. It sounds ugly, 
but
shouldn't be a big problem after all, since it's a color you normally choose 
early,
and then never modify anymore. Or we can store it as entry #27 of the palette : 
If
colors 0-26 contain the totality of the CPC palette, Grafx2 can find which one 
of
them has the same RGB values.

About the idea of "pixel layer that acts as a layer selector": I'm really 
doubtful...
It changes a big fundamental of Grafx2, it's not helpful for the program (If 
the C64
data must be maintained in memory, I prefer having two clean arrays line[200] 
and
block[40][25]),it doesn't help you draw: Drawing in color 0 exposes layer 0, 
drawing
in layer 1 expose layer 1 instead ? Argh!
When using pixels, at least we hide from the user the complexity of choosing if 
a
raster line uses Red and Blue or Blue and Red.

Note that in many cases, the pictures don't use all colors. This makes encoding
difficult, because the algorithm should delay a choice until it becomes 
necessary:
For example with FLI, in addition to the 16 colors, I use a 17th number to mean
"any". An encoder for "Mode 5" should use same system: After the global "BG" 
color is
selected, if a given 96-pixel segment uses only 2 other colors, one should be 
picked
 as this segment's color, the remaining color should be set as the first line-color.
The second line-color, unused, should not be set to 0, it should stay 
"available"
until one of the others 96-pixel segment requires it.

After a bit of thoughts on Mode 5, it doesn't seem difficult to auto-detect 
encoding:
Choose BG (Usually, user chooses. In worst case, we can try with all 27 of 
them.)
For each line
  Enumerate colors used by each 96-pixel segment
  For each segment that uses more > 2 colors in addition to BG
    Count color usage
  If none was found, repeat search with segment that uses > 1 color in addition to BG
  Most used color becomes line color 1 (LC1[y])
  For each segment that uses more than 1 colors in addition to BG and LC1[y]
    Count color usage
  Most used color becomes line color 2 (LC2[y])
  For each segment
    Current segment color (CSG) is initially marked 'unused'
    Scan all pixels
      If pixel color is BG, then this pixel uses BG
      Else if pixel color is LC1[y], then this pixel uses LC1
      Else if pixel color is LC2[y], then this pixel uses LC2
      Else if CSG is unused, then CSG is this colr, and this pixel uses CSG
      Else it's impossible to encode this perfectly, so choose between BG/LC1/LC2/CSG

Original comment by yrizoud on 28 Apr 2010 at 11:24

GoogleCodeExporter commented 9 years ago
>> Else it's impossible to encode this perfectly, so choose between 
BG/LC1/LC2/CSG
Actually in my converter i choose from BG/LC1/LC2/CSG the color more similar,
calculating the Euclidean distance between the RGB values and taking the minor.

Original comment by real.mml on 29 Apr 2010 at 8:13

GoogleCodeExporter commented 9 years ago
We're not working with RGB that much. The goal for us is not to convert any 
picture, 
but drawings done with the computer in mind.

Yves, thrust me, that's how CPC graphists are working when they do raster 
things. 
The raster system in the CPC really adds an extra layer between the fixed 
27-color 
palette and the data you use for pixels. So it's all about picking 2, 4, or 16 
colors for each screen area and see how you can make it fit all the 
constraints. So 
it makes sense to have this represented in some way in the program, and using a 
layer is the more fitting way, I think.

Original comment by pulkoma...@gmail.com on 29 Apr 2010 at 10:42

GoogleCodeExporter commented 9 years ago
I have a hard time understanding what it would result for end-user, so if you 
allow 
me some questions :
As I understand it:
Layer 1: Completely filled with "the background color"
Layer 2: Horizontal lines (288x1) that represent Line color 1
Layer 3: Horizontal lines (288x1) that represent Line color 2
Layer 4: 96x1 segments that represent the "horizontal raster" color
Layer 5: Now this layer records the data that determines which of layer 1,2,3 
or 4 
is visible.

1) What does the user see on this layer? the final image, or a jumble of pixels 
with 
only values 1,2,3,4 ?
2) When the user picks a color from this layer, what "color" does it report? A 
CPC 
color, or 1 2 3 4 ?
3) When the user is pointing at a pixel with value 1 (BG color), and the BG 
color is 
0 (black) and he writes with color "2" what happens?
3A - 2 is the layer of "Line color 1", so this pixel is switched to Line Color 1
3B - 2 is light blue, the BG color becomes light blue
3C - 2 is light blue, grafx2 tries to make this pixel light blue but only if 
doesn't 
break any constraint and doesn't alter other pixels.
3D - 2 is light blue, grafx2 makes this pixel light blue, even if it causes a 
change 
on other pixels (at most, this can break the current 96x1 segment)

These questions are for the topmost layer. For the others, I assume that you 
can 
edit them only when the image is valid, and then:
- The drawing automatically "flood-fills" the relevant area : Layer 1: all 
image, 
Layer 2 and 3: current line, layer 4: current 96x1 block
- The final "image" is visually modified accordingly : Altering the BG will 
recolor 
all pixels that were using it.

Original comment by yrizoud on 29 Apr 2010 at 2:09

GoogleCodeExporter commented 9 years ago
The way I see it :
1) User sees the final image.
2) 1,2,3,4 (or actually 0,1,2,3)
3) A

This is how the CPC hardware is done :
a) There is a fixed 27 color choice
b) Depending on the mode, you can select 2, 4, or 16 colors from this. This is 
done 
by mapping an "ink" (0..26) to a "pen" (0..15)
c) to do rasters, you change this mapping in realtime while the CRTC is drawing 
the 
screen

So, it's "natural" to work with this in mind. The 5th layer would be the actual 
pixel data of the CPC, with the rasters acting as something below it.

Usually a cpc graphist will work on the pixels in a classical drawing program, 
and 
build the rasters tables by hand. And then switch between the drawing and 
running 
the code to see the result. We could do the same, let's say, when hiding one of 
the 
raster layers, it would display as only one color and allow the graphist to see 
the 
pixel data, if he's lost in what he's doing.

Original comment by pulkoma...@gmail.com on 29 Apr 2010 at 2:23

GoogleCodeExporter commented 9 years ago
Then this can be done easily at the location as "Effects". This is where it's 
easy 
in Grafx2 to plug some code on each "putpixel" attempt. It's even possible to 
use 
the best of both worlds:
- When user paints with colors 0-26 : method C or D, WYSIWYG : paint blue, you 
get 
blue.
- When user paints with color 27-30 : method A. 27 means "Use global BG", 28 
means "use Line color 1", etc.

Original comment by yrizoud on 29 Apr 2010 at 4:12

GoogleCodeExporter commented 9 years ago
Alternate idea of representation:
We could handle 2 separate layers for the "bitmap" (which selects pens 0-3) and 
the "final result layer", which contains the image as the user will see it.
In the example of CPC mode 5:
Layer 1 : general BG (pen 0)
Layer 2 : horizontal raster (pen 1)
Layer 3 : horizontal raster (pen 2)
Layer 4 : split raster (pen 3)
Layer 5 : bitmap, contains only indices 0-3
Layer 6 : visual result

When you paint on layer 1: it fills the screen, and also alters layer 6, 
depending 
on the content of Layer 5.
When you paint on layer 2 or 3: it fills the line, and also alters layer 6, 
depending on the content of Layer 5.
When you paint on layer 4: it fills the 96x1 segment (or somesuch), and also 
alters 
layer 6, depending on the content of Layer 5.
When you paint on layer 5: only pens 0-3 are accepted, and the result is 
reported on 
Layer 6
When you paint on layer 6: Only colors that are available on Layers 1 to 4 are 
accepted. The Layers 5 and 6 are modified accordingly.

This system would have the smallest impact on the complexity of grafx2.
It allows free drawing (draw in Layer 6 in WYSIWIG, you can use the colorpicker 
etc.)
The layer 5 can be viewed and edited individually - it alters the layer 6 
instantly, 
even if it's hidden. This layer 5 can be exported easily.

It also has the advantage that aside from the presets for specifics modes, we 
can 
allow a preset "free raster mode", where Grafx2 automatically adjusts to the 
current 
number of layers: Top layer is visual, top-1 is the bitmap, 0 to top-2 are the 
raster. The user can "draw" all the rasters as he wants, it's his job to ensure 
the 
limitations are respected - and since he draws them on their own layer, it 
should be 
quite "visual" and easy.

Original comment by yrizoud on 4 May 2010 at 1:01

GoogleCodeExporter commented 9 years ago
Sounds nice, except the fact that altering 2 layers at once will make the 
operation
quite heavy (we have to update 2 layers + the depth buffer + the undo pages). 
Remember
an Amstrad CPC picture can be up to 730x256 pixels in mode 2, so a lot of 
pixels to
move around.

Original comment by pulkoma...@gmail.com on 4 May 2010 at 4:14

GoogleCodeExporter commented 9 years ago
This extra cost happens once, on first click. Indeed in this case it's +50%. It 
will
be as slow as when you click to draw on a 730x384 picture... IMO, not a problem.

I'm more concerned by the case where you draw on one of the raster layers, and 
try to
enforce the "blocky" constraint (ex: fill a 8*8 block, fill a width*1 line, fill
everything...) The performance hit is unavoidable due to many pixels affected, 
so it
can be excused, however the programming challenge is in the drawing limits: 
Normally
grafx2 wouldn't let you draw on areas that are not displayed in the viewport. 
This
makes display feedback easier, because every modified pixel can be sent to 
screen
without risk of crashing. This mode requires an exception that requires a 
rethinking
of that rule. (can we maintain the rule in normal cases without causing a 
slowdown)

For simplicity's sake with this drawing in raster layers, I'm very tempted to
implement a new CURSOR that automatically appears as a filled rectangle that 
matches
the current layer's restriction (and behaves as such when you click to draw).

Original comment by yrizoud on 4 May 2010 at 7:02

GoogleCodeExporter commented 9 years ago
I just uploaded a working experiment : 
http://code.google.com/p/grafx2/downloads/detail?name=grafx2-2.3wip1476-win32.zi
p
It has hard-coded CPC mode 5 restrictions, so it's only for testing the drawing 
model.
You can check with the attached image: when used in this version of grafx2, the 
top
layer is not just 4-color, it uses the gradients used in layers 1-4.
You can draw in layers 1-4, it both follows the raster restriction (ie: fill the
relevant block/line/segment) and visually updates the pixels that were using 
this color.
So layer 5 is internally a 4-color image, as you can see if you use the pipette 
or
grab a brush.

Original comment by yrizoud on 14 May 2010 at 7:30

Attachments:

GoogleCodeExporter commented 9 years ago

Original comment by pulkoma...@gmail.com on 9 Aug 2010 at 9:43

GoogleCodeExporter commented 9 years ago

Original comment by pulkoma...@gmail.com on 22 Aug 2010 at 1:40

GoogleCodeExporter commented 9 years ago

Original comment by pulkoma...@gmail.com on 13 Feb 2011 at 9:12

GoogleCodeExporter commented 9 years ago
Updated the experiment : 
http://code.google.com/p/grafx2/downloads/detail?name=grafx2-2.3wip1721_cpcmode5
-win32.zip

It is now possible to enable/disable the Mode5 mode in the effects screen. 
There is some trouble when switching it on or off, as the picture needs to be 
redrawn. If you switch to this mode before drawing anything it's fine, if you 
swich with some things already drawn, bad things will happen. We'll need some 
kind of converter, even if it is very basic and simple.

Other things I'm planning :
 * More configurable settings ('mode 6', maybe Spectrum or MO5-like modes)
 * Better display of what will happen when drawing on layer 5 (actual color in statusbar for example)
 * Use of a special "palette" for 5th layer (do not show actual colors, but only 4 buttons to select ink 0 1 2 3).

Waiting for comments and sample pictures :)

Original comment by pulkoma...@gmail.com on 14 Feb 2011 at 5:39

GoogleCodeExporter commented 9 years ago
Ok, now merged in trunk !

Original comment by pulkoma...@gmail.com on 19 Jun 2011 at 8:36