LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Thread Tools Search this Thread
Old 09-20-2008, 10:46 AM   #1
tanoatlq
Member
 
Registered: Mar 2007
Posts: 155
Thanked: 0
fill screen in a pseudo random way


[Log in to get rid of this advertisement]
Hello,
I have a black screen and I have to fill with color pixel by pixel.
I would like to do in a pseudo random way, painting pixel after pixel
in a more or less uniform way. What algorithm or sort of code I could
use to get an index that could be from 0 to width * heigth and
that does not repeat (like dodecaphonic music) until it reaches all
values?
I hope I speak clearly :-),
Thanks,
tano
tanoatlq is offline     Reply With Quote
Old 09-20-2008, 11:49 AM   #2
ErV
Senior Member
 
Registered: Mar 2007
Location: Russia
Distribution: Slackware 12.2
Posts: 1,268
Blog Entries: 3
Thanked: 29
Quote:
Originally Posted by tanoatlq View Post
Hello,
I have a black screen and I have to fill with color pixel by pixel.
I would like to do in a pseudo random way, painting pixel after pixel
in a more or less uniform way. What algorithm or sort of code I could
use to get an index that could be from 0 to width * heigth and
that does not repeat (like dodecaphonic music) until it reaches all
values?
I hope I speak clearly :-),
Thanks,
tano
If you want function that takes x and y coordinates, and then returns you random color for pixel (so same pixel will have same color every time), then take a look at "Perlin Noise" or "Simplex noise".

If you want to fill screen in random order, so no pixel gets painted twice, it depends on how big your screen is. You can do this using following methods:
Method 1 (takes hour):
1) store ALL screen coordinates in linear array. Store array size. This will take at least screen_width*screen_height*4 additional bytes of RAM. Which isn't that much.
2) Until array_size is 0
2.1) For every pixel pick random element within 0..array_size-1 range, remeber index.
2.2) Paint this pixel
2.3) Replace element you've picked in 2.1 with last element of array.
2.4) Decrease array size.
2.5) go to 2).

Method 2 (might take day or two to implement):
Recursively partition screen in squares. Screen is divided in squares, where each square contains 4 squares, and for every square information available if square is empty, has empty pixels, or full. This takes 2 bits per square. Or use binary paritions. This will most likely take less additional RAM, but it'll be more difficult to implement, and might require more CPU time. When this tree is ready, keep filling it up using those rules:
1) if square is empty, fill any pixel, and update "fill/empty" information.
2) if square is partially filed, fill any empty pixel, update "fill/empty" information.
3) If square is filled, do not touch it.

Last edited by ErV; 09-20-2008 at 12:02 PM..
ErV is offline     Reply With Quote
Old 09-20-2008, 06:49 PM   #3
graemef
Senior Member
 
Registered: Nov 2005
Location: Hanoi
Distribution: Fedora 11
Posts: 1,899
Thanked: 31
create an array of colours (256*256*256 = 16,777,216)
create an array of screen pixels (width * height)
shuffle the array
assign the shuffled colours in order to the screen pixel array or until the pixel array is full
repeat from the shuffle until the screen pixel array is full

Shuffle
repeat for up to the number of elements selecting two at random and swapping them
graemef is offline     Reply With Quote
Old 09-20-2008, 08:23 PM   #4
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD amd64 8.0-RELEASE, Slackware64 13.0, Slackware 12.1, Ubuntu Server 8.04, Kubuntu 9.04
Posts: 2,222
Thanked: 45
- create a one-dimensional list of size 'W x H'
- sequence the list from 0 through 'W x H - 1'
- randomize the order of the list (several options, but my lib will do it for you very quickly)
- iterate through the list with 'x = i % W' and 'y = i / W'
- use rand() to come up with a random value each iteration for the color (might need rand() * rand() to get a large enough value)

ta0kira

PS Here's how easily it can be done with my lib (-O3 makes a huge difference with a screen-sized list):
Code:
#include <ta0kira/clist.hpp>


void random_fill(unsigned int W, unsigned int H)
{
    if (!W || !H) return;

    data::clist <unsigned int> pixels(W * H);
    data::clist_sequence(pixels);
    pixels.random_order();

    for (unsigned int I = 0; I < W * H; I++)
    {
    unsigned int x = pixels[I] % W;
    unsigned int y = pixels[I] / W;

    //set pixel at '(x, y)' ...
    }
}

Last edited by ta0kira; 09-20-2008 at 08:54 PM..
ta0kira is offline     Reply With Quote
Old 09-20-2008, 09:31 PM   #5
ErV
Senior Member
 
Registered: Mar 2007
Location: Russia
Distribution: Slackware 12.2
Posts: 1,268
Blog Entries: 3
Thanked: 29
Quote:
Originally Posted by ta0kira View Post
- create a one-dimensional list of size 'W x H'
- sequence the list from 0 through 'W x H - 1'
- randomize the order of the list (several options, but my lib will do it for you very quickly)
- iterate through the list with 'x = i % W' and 'y = i / W'
- use rand() to come up with a random value each iteration for the color (might need rand() * rand() to get a large enough value)
This is exactly what I meant, but randomizing order of elements will take more time than picking one random element every time.
ErV is offline     Reply With Quote
Old 09-20-2008, 10:00 PM   #6
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD amd64 8.0-RELEASE, Slackware64 13.0, Slackware 12.1, Ubuntu Server 8.04, Kubuntu 9.04
Posts: 2,222
Thanked: 45
Quote:
Originally Posted by ErV View Post
This is exactly what I meant, but randomizing order of elements will take more time than picking one random element every time.
How do you expect to keep from picking the same one twice? Removal isn't an option unless you use a linked list, but then random access isn't an option. My lib will randomize with about O(N log N) complexity (i.e. merge sort,) which is the same as sorting. I tried it on my computer for a 1280x800 size compiled with -O3 and it took about 0.7s. Sure, some methods of randomizing will take a long time, but sorting-equivalency is pretty good, especially when compared to the complexity of either non-constant-time removal or non-constant-time access.
ta0kira

PS Picking random elements one at a time is randomizing the order, but without a target structure and much less efficient. Sure, it might work to do something like {get random} while (not used); set pixel; (O(N^2)? can't decide*) for the first half, but how long do you think it will take to get the last 10 or so pixels of a 1280x800 screen? 10 pixels is a 1 in 102,400 chance.

P3S I keep going between N log N and N^2 for statistically-likely case of *. For iteration x, I think it must take N/(N-x) + 1 tries, N/x + 1 when reversed (for simplicity,) making the total tries ∫[N/x + 1] dx, or N + N log N tries if statistics dictate truth. Because they don't, this isn't comparable to the O(N log N) complexity of sorting-equivalency, though it might be much better or might be much worse.

Last edited by ta0kira; 09-20-2008 at 10:59 PM..
ta0kira is offline     Reply With Quote
Old 09-20-2008, 10:45 PM   #7
ErV
Senior Member
 
Registered: Mar 2007
Location: Russia
Distribution: Slackware 12.2
Posts: 1,268
Blog Entries: 3
Thanked: 29
Quote:
Originally Posted by ta0kira View Post
How do you expect to keep from picking the same one twice?
Easily. See below.

Quote:
Originally Posted by ta0kira View Post
Removal isn't an option unless you use a linked list, but then random access isn't an option.
No linked lists. I've explained how elements can be removed in 1D array, you should read more carefully, before making assumptions about "trying to hit empty pixel randomly" and etc. Or you could think a bit about problem, because this stuff is really easy. Next time try to understand what people offer before posting reply, ok?

Here is 1D example. Store structs like "struct PixelCoord{int x; int y;};" instead of ints, and you'll make it 2D.
Code:
#include <stdio.h>
#include <stdlib.h>

int randRange(int range){
    return rand() % range;
}

int main(int argc, char** argv){
    const int initialSize = 256*256;
    int *array = new int [initialSize];
    int arraySize = initialSize;
    
    for (int i = 0; i < initialSize; i++)
	array[i] = i;
    
    while(arraySize){
	int index = randRange(arraySize);
	printf("%d\n", array[index]);
	arraySize--;
	array[index] = array[arraySize];	
    }
    
    delete[] array;
}
I used similar approach for generating labyrinths.
Notice that MAX_RAND might be something around 65536 on some systems (this won't break algorithm, but pixels won't be distributed uniformly), so it makes sense to use better random number generator. Like this one.


Quote:
Originally Posted by ta0kira View Post
My lib will randomize with about O(N log N) complexity (i.e. merge sort,) which is the same as sorting. I tried it on my computer for a 1280x800 size compiled with -O3 and it took about 0.7s. Sure, some methods of randomizing will take a long time, but sorting-equivalency is pretty good, especially when compared to the complexity of either non-constant-time removal or non-constant-time access.
Method I offered required as many iterations, as there are pixels. O(N) complexity. The only thing that will eat time is "rand" function. This problem DOES NOT require advanced techniques like merge sort. By the way, if your lib was supposed only to randomize order of elements, you could do it the same way as I suggested here. Just remember to use better random number generator.

Quote:
Originally Posted by ta0kira View Post
but how long do you think it will take to get the last 10 or so pixels of a 1280x800 screen?
As I said before, you should read more carefully. There are no random factors. Number of operations is fixed. Also I recommend to search for easy/elegant solution before actually trying to solve problem. Shuffling array is slow. Using merge sort to optimize shuffling might be better, but it is still wrong way to do things, because it is optimization of unelegant solution. It's like using handgrenade to kill a fly - it works, but there is another way.

Last edited by ErV; 09-20-2008 at 10:58 PM..
ErV is offline     Reply With Quote
Old 09-20-2008, 11:07 PM   #8
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD amd64 8.0-RELEASE, Slackware64 13.0, Slackware 12.1, Ubuntu Server 8.04, Kubuntu 9.04
Posts: 2,222
Thanked: 45
Quote:
Originally Posted by ErV View Post
Here is 1D example. Store structs like "struct PixelCoord{int x; int y;};" instead of ints, and you'll make it 2D.
Yes, so it seems you're correct. Nice code!
ta0kira
ta0kira is offline     Reply With Quote
Old 09-21-2008, 05:07 AM   #9
tanoatlq
Member
 
Registered: Mar 2007
Posts: 155
Thanked: 0

Original Poster
But does not exists a mathematical function that loops through all indexes without repeating
until it walks all the elements? My purpose was that to avoid the construction of a large
array..
tanoatlq is offline     Reply With Quote
Old 09-21-2008, 06:26 AM   #10
graemef
Senior Member
 
Registered: Nov 2005
Location: Hanoi
Distribution: Fedora 11
Posts: 1,899
Thanked: 31
Since you wish to have a random allocation of data you'll need to reserve some memory to keep track of either the pixels or the colours that have been allocated.
graemef is offline     Reply With Quote
Old 09-21-2008, 07:53 AM   #11
ErV
Senior Member
 
Registered: Mar 2007
Location: Russia
Distribution: Slackware 12.2
Posts: 1,268
Blog Entries: 3
Thanked: 29
Post

Quote:
Originally Posted by ta0kira View Post
Nice code!
Thanks.

Quote:
Originally Posted by tanoatlq View Post
But does not exists a mathematical function that loops through all indexes without repeating
until it walks all the elements? My purpose was that to avoid the construction of a large
array..
I don't know such function.
In any way, you'll have to construct array - one or another.
Notice that on modern machines memory is not a problem. Array of coordinates (in the way I offered) for 1280x1024 will take 5242880 bytes of ram (x and y coordinates are stored as 16-bit integers). On modern hardware this is small amount of memory. Screen itself takes similar amount of memory (in 32bit mode). If you really want to conserve memory, then you can use "bitset" - i.e. store bit array where each bit is empty if element wasn't returned and is set, and is set if such elements was returned. For 1280x1024 simplest implementation will take 163840 bytes of memory, but searching for empty pixel will be very slow (you'll have to iterate through all elements to find first that wasn't returned, so it'll be simply unusable). To make approach much faster (with somewhat constant time for finding empty pixel), you can add more bitsets which will form binary tree - i.e. top leaf node would indicate if array has bits set, is empty, or all elements we returned, so every leaf will take 2 bits. With "tree approach" all helper structures will take 327680 bytes for 1280*1024 screen, but writing/debugging this might take day or two (I could do it, but I wouldn't do it for free, since I don't need such function now and have no finished stuff with similar functionality). Or you can go further and partition screen as quad tree. This will save more memory (roughly 218453 bytes in simplest case for 1280x1024, or 174297 if quad covers 16 child nodes, not just 4), but will be a bit slower than binary tree and a bit more complicated. Notice that required CPU time increases as memory requirements decrease. So if you want to implement your effect quickly, without spending too much time on it, just use "make array of all coordinates, pull random elements" approach. If you have free time, and strict memory requirements, try partitioning and binary/quad trees.

--EDIT--
You can also lower memory requirements a bit if you'll store pixel index (x + y*screen_width) instead of plain coordinates, and array of initial values is stored as compressed stream of bits. I.e. "pixel index" for 1280*1024 takes 21 bits at most, so if you'll store initial array of screen coordinates as stream of 21-bit integers, not as array of 32bit integers, the whole thing will take only 3440640 bytes of ram, so you'll save 1802240 bytes. This will require writing your custom class/routines for "compressed bit array", because (AFAIK) c++ doesn't provide something like this in STL or standard library.

Last edited by ErV; 09-21-2008 at 08:16 AM..
ErV is offline     Reply With Quote
Old 09-23-2008, 10:34 PM   #12
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD amd64 8.0-RELEASE, Slackware64 13.0, Slackware 12.1, Ubuntu Server 8.04, Kubuntu 9.04
Posts: 2,222
Thanked: 45
You could also mmap a file.
ta0kira
ta0kira is offline     Reply With Quote
Old 10-23-2008, 02:27 AM   #13
piotrl
LQ Newbie
 
Registered: Oct 2008
Posts: 1
Thanked: 0
Instead of incrementing by 1, increment by a prime number.
Clip by taking a modulo of the total size.
piotrl is offline     Reply With Quote

Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
web pages do not fill my screen Mintme Linux - Newbie 6 05-29-2008 04:44 PM
Ubuntu 5.10 doesn't fill laptop screen Nateonwheels Linux - Laptop and Netbook 2 05-30-2007 04:01 PM
X display won't fill screen - old laptop zekthedeadcow Slackware 7 09-27-2005 04:41 PM
How to get tvtime to fill my screen biscristi Linux - Software 1 03-06-2005 09:27 AM
Bootloaders fill the screen with garbage dharms Linux - General 4 03-15-2004 05:43 PM


All times are GMT -5. The time now is 05:31 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Advertisement
Oracle Magazine contains technology strategy articles, sample code, tips, Oracle and partner news, how to articles for developers and DBAs, and more. Click Here to receive a complimentary subscription courtesy of LQ.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
RSS2  LQ Podcast
RSS2  LQ Radio
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: @linuxquestions
Open Source Consulting | Domain Registration