From
Stanislav Yudin
→
To
All
26 July 2006
Hello, All
Although my question concerns both the Spectrum itself and programming issues,
but still it does not quite fit the topic of this section. Let it be
a little bit here, and then I'll move it somewhere :) Okay?
So I'm asking for advice. There is a task to reduce the standard Spectrum color screen to
twice, i.e. get a color 8-bit image with a size of 96*128 pixels. The essence
The algorithm is clear - we take four adjacent points, look at their color and then
in a huge table we find the desired resulting color, which we put in
the resulting image. Take the next 4 points, etc.
But, firstly, I have too little memory at my disposal - there is no room for large
tables, the most I can afford is a small table in
256-512 bytes. Secondly, there is no time to make complex calculations - you need
get by with just a few lines of assembler.
It would be ideal to come up with a very short algorithm that would take 4 points,
which have 4-bit color information R+G+B+BRIGHT), and the output received
was an 8-bit number - the resulting color, or the color number in the table. Task
It’s a little simplified by the fact that:
1. There can only be 2 colors in a 2x2 block.
1. A 2x2 block can have only one BRIGHT value, that is, essentially information
about the color of each point 3-bit.
2. You don’t need to take into account the location of the points - only their ratio matters
in a 2x2 block.The task is simple. But I haven't come up with anything yet. Maybe someone has some
any good thoughts on this?
From
Golubtsov Alexey
→
To
All
26 July 2006
Hello, CityAceE
the first thing that comes to mind is to look at the hermite filter algorithm (which
is listed as fastest in the resample operation in irfan view) for the case of reduction in
2 times.
So Google dug up the source code right away
File: bitmap_resample_filters.rar
http://zx.pk.ru/attachment.php?attachmentid=3493
From
Kirill Frolov
→
To
All
26 July 2006
Hello, CityAceE
Cit> So I'm asking for advice. There is a task to reduce the standard color screen
Cit> Spectrum twice, i.e. get a color 8-bit image
Cit> size 96*128 pixels. The essence of the algorithm is clear - we take four standing
Cit> next to the dots, look at their color and then find them using a huge table
Cit> the desired resulting color, which we put in the resulting image.
Cit> Take the next 4 points, etc.
Cit>
Nonsense. Typical resampling problem. A good result will be like this
non-optimal algorithm like: first increase several times (by setting
"extra" pixels to zero, i.e. the appearing zero pixels alternate with
non-zero initial ones), then a filter is applied to the resulting large image
low frequencies, then arbitrary pixels are selected in the picture with the desired step,
to get a picture of the required size. The algorithm is not fast. Therefore usually
prefer interpolation.
> Ideally it would be to come up with a very short algorithm that would take 4
> points that have 4-bit color information R+G+B+BRIGHT), a
> the output was an 8-bit number - the resulting color, or> color number in the table.
>
Average. The result is truly obscene. Because the need to filter high
frequencies that do not fit into the spectrum of your picture have not been canceled. Honor
some DSP FAQ. It won’t give you much knowledge, but it will give you an idea of the subject.
> The task is a little simplified by the fact that:
> 1. There can only be 2 colors in a 2x2 block.
> 1. A 2x2 block can have only one BRIGHT value, that is, essentially
> information about the color of each point is 3-bit.
> 2. You don’t need to take into account the location of the points - only them matters
> the ratio in the block is 2x2.
>
These are all uninteresting technical details, nothing to the essence of the algorithm
having no relationship.
From
Max Kuleshov
→
To
All
26 July 2006
Hello, CityAceE
For color, linear interpolation is suitable, but you need to interpolate every
channel separately, R, G, B and convert the result to a palette of 256 colors
From
Stanislav Yudin
→
To
All
26 July 2006
Hello, CityAceE
key-jee suggested an interesting and simple method. I'll try to check it tomorrow
practice. I just can’t believe that everything is so simple and that, most importantly,
this method will work. But the question remains, what if someone else has
thoughts.
From
Stanislav Yudin
→
To
All
26 July 2006
Hello, key-jee
In general, either I did not fully convey the point, or I was simply misunderstood.
Apparently it is necessary to explain why this is needed at all. You need to display Palm
having a resolution of 160x160 Spectrum screen. Ideally, you need to do this 50 times per
second, so the proposed options are not suitable at all. Need something
simple, short and fast. The simplest option, which immediately comes to
head is an 8 kilobyte plate: 1 bit of brightness + 4 dots * 3 bits = 13 bits =
8192 bytes. But a table of 8 kilobytes is not acceptable!
For example, I display a picture in 16 shades of gray simply by summing the brightness of 4
points and dividing the sum by 4. See the result in the attached (average)
picture.
This option is certainly not suitable for a color picture, but for the sake of sport
interest, I implemented it. The result is unsatisfactory. (See third picture)
The first picture is just for illustration. This is the output of a monochrome picture
halved in 4 gradations of brightness.
What I'm asking is a simple math problem. I'll try
formulate it in more detail. Given 4 numbers from 0 to 15, you need to use them
perform some actions to get a number from 0 to 255. This number is on
The output should clearly make it clear what numbers and how many were at the input.
Additional terms:
1. Of the four numbers, only 2 can be different.2. In a quadruple of numbers, only numbers from 0 to 7 can be found at a time,
or from 8 to 15.
3. The sequence of numbers in four has no meaning, that is, from the point
From the point of view of the aglorythm, the sequences 0111, 1011, 1101 and 1110 must be equal.
That's why I cited these "uninteresting technical details." All points
which I cited from my point of view play an important role in
implementation of the algorithm.
Is that more clear?
File: Dizzy2bpp.png http://zx.pk.ru/attachment.php?attachmentid=3497
File: Dizzy4bpp.png http://zx.pk.ru/attachment.php?attachmentid=3498
File: Dizzy8bpp.png http://zx.pk.ru/attachment.php?attachmentid=3499
From
Ivan Petukhov
→
To
All
26 July 2006
Hello, CityAceE
Hit ICQ (otherwise I’m not sure you show up on ICQ anymore) - I’ll try
express your thoughts on this matter there..
From
Alexey Goncharov
→
To
All
26 July 2006
Hello, CityAceE
I think fk0 is right about the "uninteresting technical details". After all
in fact, to get a normal (well...=)) picture you need to take into account not 2x2
points. After all, you don’t have RGBI bits on Palm, but just a piece of the palette.
So IMHO - interpolation. If you don’t have enough resources, you can try
play around with larger block sizes or weighting coefficients.
From
SMT
→
To
All
26 July 2006
Hello fk0
Considering only 2x2 we will get “jerks” on frame effects. filters for
speeds are applied first to each row, then column by column. for example,
reduce each line by 2 times (256->128), taking into account pairs of neighboring pixels
(or even threes or fours). and then compress 192 lines into 96. Of course, store
The whole screen 128x192 is not necessary. you can try this trick: to compress by
x use many (3-4) neighboring pixels, and y - only 2 lines. not
quite good, but better than fixed 2x2 blocks
fk0> Nonsense. Typical resampling problem. This will give a good result
fk0> non-optimal algorithm as: first increase several times (by
fk0> setting "extra" pixels to zero, i.e. appearing zero pixels
fk0> alternate with non-zero initial ones), then to the resulting large one
fk0> a low-pass filter is applied to the picture, then with the required step in
fk0> arbitrary pixels are selected from the picture to get the picture
fk0> of the required size
fk0, without reading to the end, rushed to quote the textbook... in this particular
case (decrease by 2 times), the step “increase several times first” is not needed
CityAceE, what interests me most is how you choose a palette for color
regime?
From
Max Kuleshov
→
To
All
27 July 2006
Hello SMT
Taking into account 3s and 4s is already nonlinear interpolation and will require
floating point arithmetic or, in extreme cases, exact multiplication/division. B
bilinear interpolation for this specific case (when the chunk is averaged
2x2) is only addition and division by 2 (4).
From
SMT
→
To
All
27 July 2006
Hello, CityAceE
> Taking into account 3s and 4s is already nonlinear interpolation and will require
> floating point arithmetic or, in extreme cases, multiplication/division
> exactly
for b/w - multiplication according to tables
From
Stanislav Yudin
→
To
All
27 July 2006
Hello, maximk
max> In short, I tested it for fun. I think it's normal.
max> Result (with additional reduction to 2 bits per color channel)
The result is quite satisfying! Please explain to me the essence of the method.
SMT> considering only 2x2 we will get “jerks” on frame effects.
On Palm, for which the emulator is written, we are not talking about any frame effects
goes in general - the processor is too weak and the emulation is simplified to the point of impossibility.
SMT> what interests me most is how you choose a palette for color
SMT> mode?
I don’t choose at all. I use the one that is offered by default. And from it
I choose the most similar colors. I'm not aiming for maximum accuracy.
From
Stanislav Yudin
→
To
All
27 July 2006
Hello, CityAceE
There is another question within the same topic. The attached file contains a standard palette
Palma. One color occupies an 8x8 square. The colors go from left to right, top to bottom.
The color in the upper left cell is numbered 0 and then in ascending order.
I’ve never encountered this before, so it’s a little unclear to me how
These colors are obtained... I can’t understand the pattern. Which bit of the color number is behind
what does it answer?
File: Palm_palette.png http://zx.pk.ru/attachment.php?attachmentid=3506
From
Max Kuleshov
→
To
All
27 July 2006
Hello, CityAceE
Initial data. A two-dimensional array of points in the image you want
scale - image[][]. Array element - a number that determines the color of the point (in
any form).
There are auxiliary functions (macros) that can be used to extract
each component from this number - getRed/getGreen/getBlue
We go through the points of the resulting image:
┌─- code ───
for (int x=0; x<128; ++x) {
for (int y=0; y<96; ++y) {
// interpolate each channel separately
int red = (getRed(image[x*2][y*2]) +
getRed(image[x*2+1][y*2]) +
getRed(image[x*2][y*2+1]) +
getRed(image[x*2+1][y*2+1])) / 4;
int green = (getGreen(image[x*2][y*2]) +
getGreen(image[x*2+1][y*2]) +
getGreen(image[x*2][y*2+1]) +
getGreen(image[x*2+1][y*2+1])) / 4;
int blue = (getBlue(image[x*2][y*2]) +
getBlue(image[x*2+1][y*2]) +
getBlue(image[x*2][y*2+1]) +
getRed(image[x*2+1][y*2+1])) / 4;
// has the color of the point in the form R,G,B
int paletteIndex = convertToPalette(red, green, blue);
newImage[x][y] = paletteIndex;
}
}
└── code ───
The code itself can be optimized. I wrote this for clarity.
From
Max Kuleshov
→
To
All
27 July 2006
Hello, CityAceE
% is the remainder of the division. Those. for example 5% 3 = 2 (quotient = 1, in case
integer division)
From
Max Kuleshov
→
To
All
27 July 2006
Hello, CityAceE
Well, they use so-called web-safe colors.
Each component can take a value from the set 0x00, 0x33, 0x66, 0x99,
0xCC, and 0xFF and in addition we have 6^3=216 colors + additional shades for gray
(all components 0x22, 0x44, 0x55, 0x77, 0x88, 0xAA, 0xBB, 0xDD, 0xEE) and if
look at the presented palette for a few more colors, where the component is either
0x88 or 0x00
This means that if we take a number in the palette from 0 to 215, then we can expand it
this way:
index %6 = green index in array [0xFF, 0xCC, 0x99, 0x66, 0x33, 0x00]
(index / 18) % 6 = index of red in the array
(((index / 6) % 3) * 2) + (index / 108) * 3 = blue index. Those. the point is
that the first part of the blue palette decreases horizontally in groups from 0xff to 0x99,
and the second half from 0x66 to 0x00
Color number 215 is not black, but dark dark gray (0x111111)
If I'm not mistaken of course...
I wrote the conversion of the number to RGB, but I think the reverse operation is also possible
it won't be much work. You can make a table(s) to speed things up. 512 bytes each
it will work out.
In general, is there really no such function in the PalmOS API for working with color?
component by component? I really can't even believe it...
From
Stanislav Yudin
→
To
All
27 July 2006
Hello, maximk
Thanks for your help!
max> Well, so-called web-safe colors are used there.
max> ...
max> Color number 215 is not black, but dark dark gray (0x111111)
max> If I'm not mistaken of course...
No, I was not mistaken, everything is correct. I have already verified this experimentally :)
Just remind me, please, what action is indicated by the percent sign (%).
Integer division?
max> In general, is there really no such function in the PalmOS API for working with color
max> component-wise? I can’t even believe it...
Surely there is! But everything I write, I write in pure assembler. Of course you can
and call all these APIs from assembler, but there’s no desire to understand it at all, and
The program does not have time to use cumbersome and slow API procedures.
From
Stanislav Yudin
→
To
All
27 July 2006
Hello, maximk
Great, everything seems to be working out thanks to the advice from the forum. Thanks again
to everyone who responded. The vacation is short and while I'm doing other things I still
I would like not to waste time on solving this problem, but to see in this thread already
a ready-made formula for converting a color in RGB format to INDEXED COLOR format, i.e. in
standard Palm palette.
From
Max Kuleshov
→
To
All
27 July 2006
Hello, CityAceE
If the RGB of the resulting picture, where there may be mixed colors (not
Spectrum) to smooth out the scaling results, then something like this:
┌─- code ───
index = (green / 0x33) + ((red / 0x33) * 18) + ((blue / 0x33) % 3) * 6
if (blue < 0x80) {
index = index + 108
}
└── code ───
I’m just thinking that it wouldn’t be better to rearrange the palette to suit yourself so that it doesn’t
was that uncomfortable? (no clear division by bits). Then it would be possible
abandon multiplication/division and make do with only shifts. (I don't know
really, how fast Motorola multiplies and divides :) )
For example, allocate 2 bits for color and we get 64 colors, but this is enough for real
in fact.
Those. Let's say the index in the palette will be broken down into bits like this: 00RRGGBB
From
van Yu Shinn
→
To
All
27 July 2006
Hello, CityAceE
In terms of data volume, it is better to convert from screen 6912 to final
result. That is, (2 bytes of screen + 1 byte of attributes) -> 4 pixels. Perhaps
attribute bytes are first converted and then applied to all 4 lines.
Are there 32-bit registers? Integer multiplication? What is the palette?
[Added]
The answers were found here [http://palmz.in/board/index.php?showtopic=32976] and here
[http://palmz.in/board/index.php?showtopic=17326]. :)
From
van Yu Shinn
→
To
All
28 July 2006
Hello, CityAceE
Here's my solution.
Analytical, needs to be tested in practice.
A small table and no multiplication or division. ;)
Let's create a table:
t=[281,19,263,1,280,18,262,0];
Let p1, p2, p3, p4 be three-bit colors of the colors of four pixels.
Let bright be the same brightness for all.
The color of the resulting pixel can be calculated like this:
┌─- code ───
color=256+t[p1]+t[p2]+t[p3]+t[p4];
if (!bright) color+=281;
if (color & 0x0400) color+=90; //blue from the second half
color&=0xff; //take the low byte
└── code ───
Result: color - color from the above palette.
The color variable and table elements t require a minimum of 2 bytes (one
not enough bytes).
From
Stanislav Yudin
→
To
All
31 July 2006
Hello, CityAceE
Well, everything worked out for me (the result is attached). Thank you so much everyone
those who responded and took part in the discussion! But first of all I want
thank key-jee, who actually shared the algorithm and maximk,
who shared information about Palm flowers.
I don't know the reason why key-jee shared his algorithm in private, but
not in this thread, so if he deems it necessary, he himself will talk about it here
the essence of his method.
File: Dizzy8bpp2.png http://zx.pk.ru/attachment.php?attachmentid=3526
From
SMT
→
To
All
31 July 2006
Hello, CityAceE
the quality is good. how fast?
From
Stanislav Yudin
→
To
All
1 August 2006
Hello SMT
SMT> how fast?
Very quickly! The method uses two tablets of 125 bytes each. A
If you rearrange the palette in your own way, you can do without tables altogether.
From
van Yu Shinn
→
To
All
2 August 2006
Hello, CityAceE
Cit> At the same time, you also forgot to mention that division occurs everywhere without a remainder.
This is a property of the C language. Integer division returns integer
result.
Cit> if he considers it necessary, he himself will tell you here about the essence of his
Cit> method.
Interesting.
Cit> Very fast!
So it can be done faster.
Cit> 125 byte plates
Apparently, 5 gradations [0..4] per component (R,G,B) to the power of 3 (number
component).
Not a very good decision. More than half of the table elements are not used.
Apparently the resulting pixel can only accept 40 colors and its
components R, G, B cannot be all pairwise different.
How is an index in a table calculated?
Two times 5? Adding the constants 5 and 25?
From
Stanislav Yudin
→
To
All
2 August 2006
Hello, captain cobalt
cap> So it can be done faster.
I think it's definitely possible! But not for my case.
cap> Apparently, 5 gradations [0..4] per component (R,G,B) to the power of 3
cap> (number of components). Not a very good solution.
Yes, that's about it. But in my case, this particular solution was ideal.
cap> More than half of the table elements are not used.
A total of 92 color combinations are possible in a 2x2 area. Moreover, some of the combinations
They end up with the same color. For example, I would never have thought that if
mix two black and two yellow pixels, the output will be the same color,
which will result from mixing two red and two green dots. In total it turns out to be 83
unique colors at the output. This is the number of colors used in one plate
of 125 elements. There are two plates, according to the number of gradations of brightness.
cap> How is the index in the table calculated?
These are already the details of the algorithm. We are waiting for key-jee himself to answer this.