Click here to go to the forum index Click here for the home page
 
Author Message

<  TAP and patch development  ~  Graphical varying colour progress bar code.

Page 1 of 1
kidhazy
Posted: Thu Aug 18, 2005 7:38 am Reply with quote
Frequent contributor Joined: 29 May 2005 Posts: 372 Location: Melbourne, Australia
Does anyone have a code snipet for displaying a graphical progress bar on the screen?

I think it would be easy enough using the TAP_Osd_Fillbox API call for solid colours, but I was looking to do something that would display a varying coloured bar. eg. green at the start, yellow in the middle, and red at the end.

I'm looking to use this as a channel even progress bar indicator, but I'm not sure how to use the varying colours.

Any examples would be appreciated.

_________________
Thanks,
kidhazy.
View user's profile Send private message
kidhazy
Posted: Thu Aug 18, 2005 7:54 am Reply with quote
Frequent contributor Joined: 29 May 2005 Posts: 372 Location: Melbourne, Australia
Just found the sample myosd...this is a good starting point, though it doesn't appear to give the gradient fill of the bar, just gives solid changing colours.

_________________
Thanks,
kidhazy.
View user's profile Send private message
simonc
Posted: Thu Aug 18, 2005 9:44 am Reply with quote
Frequent contributor Joined: 12 Apr 2005 Posts: 5639 Location: Cheltenham
How about doing a series calls to TAP_Osd_Fillbox with a width of 1, incrementing the x parameter and color parameter?
View user's profile Send private message Visit poster's website
sunstealer
Posted: Thu Aug 18, 2005 9:46 am Reply with quote
Forum moderator Joined: 31 Mar 2005 Posts: 325
I wrote code to do graduated fills on the Toppy for my EPG effort which is currently stalled. If you PM me with your contact details, I will send you the relevant bits. The main issue with making a good graduated fill is doing the colour interpolation in the right colourspace - I do this by converting from RGB representations of colour to CIElab colourspace. In this space, equally spaced points along a straight line between any two points on the colourmap give equal jumps in perceived brightness (it is a human perception weighted colourspace) and colour. So interpolation is a simple linear one and then the interpolated colours can be converted back to RGB. Many people just convert to HSB colourspace which doesn't give as nice a result - some even linearly interpolate in RGB which looks awful but you see it alot.

Regards
View user's profile Send private message
sunstealer
Posted: Thu Aug 18, 2005 9:48 am Reply with quote
Forum moderator Joined: 31 Mar 2005 Posts: 325
simonc wrote:
How about doing a series calls to TAP_Osd_Fillbox with a width of 1, incrementing the x parameter and color parameter?


That would be computationally expensive and unnecessary. What I did was to build the graduated rectangle using a pair of loops - build the object in memory and then blit it to the screen in one go. This works fine and is quick.
View user's profile Send private message
simonc
Posted: Thu Aug 18, 2005 10:25 am Reply with quote
Frequent contributor Joined: 12 Apr 2005 Posts: 5639 Location: Cheltenham
Yes, I thought it might be and by the sounds of things it'd look pretty awful as well Wink

Perhaps a Toppy graphics library would be in order? I wonder if Kjetil Nęss would consider having his library http://home.online.no/~kjetnaes/gfxlib.html extended with routines like an efficient gradient fill[/url]
View user's profile Send private message Visit poster's website
kidhazy
Posted: Fri Aug 19, 2005 1:38 am Reply with quote
Frequent contributor Joined: 29 May 2005 Posts: 372 Location: Melbourne, Australia
One of the routines that one of the Oz guys has shared with me uses a process of building up the bar line by line with varying colours for each vertical line.

Each line is built up pixel-by-pixel.

This drawing is all done in a memory based region and then copied to the main region when complete.

I'll try and package it up as a generic routine that we can all use.

_________________
Thanks,
kidhazy.
View user's profile Send private message
sunstealer
Posted: Fri Aug 19, 2005 10:15 am Reply with quote
Forum moderator Joined: 31 Mar 2005 Posts: 325
Hi kidhazy,

I have emailed you with my code. There are a number of routines - let me explain what they do. Before that, let me say that the colour interpolation routines rely on floating point math which is obviously slower than integer maths. I haven't changed this as it was never my intention to use these routines in real time but rather to use them at the start of the program to initialise a set of colour arrays. If you want to use them dynamically, you could still take this approach but it might be costly in terms of memory or you could rewrite them to be precise to a few dp's in integer maths. Also, having looked at the library you mention - I really like what he did with using Duff's devices to speed up blitting versus OSD_DrawPixmap. I have used the API for drawing the pixmap to the OSD and Duff's devices are probably much faster as they tend to translate to better machine code. When I start coding again, I am going to use his graphics library - nice bit of coding and maybe he will incorporate my colour conversion code.

Anyway the routines:

On init, use Interp_Col to build an array of colour values between two RGB values. I have coded it to accept the R / G / B as separate bytes for convenience. It could be modified to accept the RGB as a word. ngrad specifies how many bands of colour you want - set it to the width of the rectangle to have a continous grad fill and less if you want a more "pixellated" effect. gradBuf is a pointer to a word array which needs to be initialised with a size of ngrad by the calling function. This is where the output colours are stored.

For a grad fill you input the OSD rgn number, the position and dimensions of the rectangle, ngrad, gradBuf with your colours in, and vert which determines the direction of the fill (a boolean) to the Graduated_Rect function. I notice two things about this in retrospect - the memset to clear memory before writing the gradrect pixmap is probably unnecessary and also, this function creates and destroys the pixmap that is blitted - you might want to put the blitting in a separate function so that you can keep the pixmap between blits if you need to plot the same gradrect more than once.

The other functions handle the colourspace conversions and should be fairly easy to follow. Please let me know if you find these snippets useful or have any problems with them. It would be nice to be acknowledged in the resulting source code and to be sent any improvements you make to my code. I will send them to the author of that graphics library as well.

Regards.
View user's profile Send private message
kidhazy
Posted: Fri Aug 19, 2005 12:09 pm Reply with quote
Frequent contributor Joined: 29 May 2005 Posts: 372 Location: Melbourne, Australia
FYI,

Here's a sample of what I've just completed using the LineBar TAP code from damo and the myOSD demo code as a starting point.

I've made the code generic enough and handles 3 styles.
1 - traditional colour gradient
2 - fills the graph to a percentage with the final colour
3 - fills the entire graph with the colour that matches the percentage.





As you can see from the code it is all parameter driven. I hope someone finds it useful.

sunstealer - thanks for the email, though I think the floating point is a bit over the top for my needs here Very Happy

Code:


     word rgn;
     word PBrgnMem;

void exitTap()
{
    _exitFlag = TRUE;
   TAP_Exit();
}

dword TAP_EventHandler( word Event, dword param1, dword param2 )
{
   if (Event == EVT_KEY)
   { 
      switch (param1)
      {
             
      case RKEY_Exit :    exitTap();
                       return 0;
      }
}
   return param1;
}

//------------------------------ DrawLine --------------------------------------
//
// Draw a single vertical line of one colour.
//
void DrawLine(word scrrgn, int X, int Y, int lineheight, int lineColor)
{
    int tempY;
    for (tempY=0; tempY<lineheight;  tempY++)
    {
        TAP_Osd_PutPixel( scrrgn, X, Y+tempY, lineColor);
    }
}

//------------------------------ DrawLineColour --------------------------------------
//
// Determines the colour of the line to be drawn, based on style of bar and percentage.
//
int DrawLineColour(int percent, int style)
{
    int red;    int green;    int blue;
    int GradientFill = 0; int SolidColourBar = 1; int FullSolidBar = 2; 
    int LineDrawcolour;
   
    // Determine the appropriate RGB value for the line.
    if (percent >= 50)        red = 31;
    else                      red = percent * 31 /50;

    if (percent <= 50)        green = 31;
    else                      green = 31 - ( (percent -50) * 31 /50 );

    blue = 0;

    LineDrawcolour = RGB( red, green, blue);
    return LineDrawcolour;
}

//------------------------------ DisplayProgressBar --------------------------------------
//
// Displays a graphical progress bar.
//
// scrrgn   - region of screen bar is to be copied to.
// amount   - the amount to be graphed.
// max_amount - the maximum amount that can be graphed.
// x_pos      - x coord of the graph
// y_pos      - y coord of the graph
// linewidth  - width of the graph
// lineheight - height of the graph
// freeSpaceColour - colour of the background of the graph
// BoxLineWidth    - width of the black line surrounding around the graph
// style           - style of bar to draw.
//                   0 = colour gradient fill
//                   1 = solid colour partial fill
//                   2 = solid colour full bar
//
void DisplayProgressBar(word scrrgn, int amount, int max_amount, int x_pos, int y_pos, int linewidth, int lineheight, int freeSpaceColour, int BoxLineWidth, int style)
{
    int amount_percent;  int line_percent;  int percent;
    int wf;
    int LineDrawcolour;
    int tempX;
    int GradientFill = 0; int SolidColourBar = 1; int FullSolidBar = 2; 

    if (amount > max_amount) amount=max_amount;  // Check we're not out of bounds.
    if (amount < 0)   amount=0;                  // Check we're not out of bounds.

    amount_percent = amount * 100 / max_amount;

    if (style != FullSolidBar)
    {    // Make the graph a percentage of the line width.
         wf = linewidth * amount / max_amount;      // calculate relative position for red/green transition
    }
    else
    {   //Style #3 fills up the entire line with 1 colour.
        wf = linewidth;
    }
   
    // draw full graph using free space colour
    TAP_Osd_FillBox(scrrgn, x_pos, y_pos, linewidth, lineheight, freeSpaceColour);

    // Loop through to draw the lines that make up the graph.
    for (tempX=0; tempX<wf;  tempX++)
    {
        line_percent = (tempX * 100) / linewidth;    // Determine what percentage of graph are we up to.
        switch (style == GradientFill)               // Determine which percentage variable to use to determine colour.
        {
           case TRUE : percent = line_percent;
                              break;
           default : percent = amount_percent;
        }
        LineDrawcolour = DrawLineColour( percent, style);    // Determine colour of line
        DrawLine(scrrgn, x_pos+tempX, y_pos, lineheight, LineDrawcolour);         // Draw one single line
    }
    // Draw Box around Bar
    TAP_Osd_DrawRectangle(scrrgn, x_pos, y_pos , linewidth, lineheight, BoxLineWidth, 0);

    // Copy graph from memory region to screen display region.
    TAP_Osd_Copy( PBrgnMem, scrrgn, x_pos, y_pos, linewidth, lineheight, x_pos, y_pos, FALSE );
   
}


int TAP_Main(void)
{
   int rgn = TAP_Osd_Create(0, 0, 720,576, 0, 0);
   int PBrgnMem = TAP_Osd_Create(0, 0, 720,576, 0, OSD_Flag_MemRgn);

   TAP_Osd_FillBox(rgn, 0, 100, 700, 400, COLOR_Cyan);

//  Display 3 samples graphs
   DisplayProgressBar( rgn, 50, 60, 20, 200, 600, 50, 0,  2, 0);
   DisplayProgressBar( rgn, 50, 60, 20, 300, 600, 50, 0,  2, 1);
   DisplayProgressBar( rgn, 50, 60, 20, 400, 600, 50, 0,  2, 2);
       

   return 1;
}

_________________
Thanks,
kidhazy.
View user's profile Send private message
sunstealer
Posted: Fri Aug 19, 2005 1:39 pm Reply with quote
Forum moderator Joined: 31 Mar 2005 Posts: 325
Yr welcome.

I would point out that although it is floating point maths - it is still quite quick and you only call it once to make the colour gradient array. I note from your pic that your fills are calculated in RGB colourspace which gives a false colour transition. Why don't you add my colour interpolation to your bar drawing code. You may find the result more appealing and I doubt you will see a change in execution speed. In addition, the routine I use for drawing the bar should execute faster than yours especially if you use the blitting routines from that graphics library to transfer the result to the OSD. Repeatedly calling a function like drawLine will add quite a bit of overhead with pushing to the stack for each call. It would be trivial to add a "draw black" bit to my code to give you a "percent" fill.

Regards
View user's profile Send private message

Display posts from previous:  

All times are GMT + 1 Hour
Page 1 of 1

Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum