Spectrum screen scaling

ZXNet echo conference «code.zx»

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.