LinuxQuestions.org
Review your favorite Linux distribution.
Go Back   LinuxQuestions.org > Blogs > rainbowsally
User Name
Password

Notices

Rate this Entry

Life In The Computer Mad Science Zone

Posted 06-20-2013 at 10:08 AM by rainbowsally
Updated 08-06-2014 at 07:17 AM by rainbowsally (bum code)

[Update: June 20, 2013 - corrected name in lqToPixel.]

Progress report.

We found a bug in the incremental backup program uploaded recently.

[Update June 24, 2013, see Gazi's bug fix below and here's a version that uses C/C++ to do it from a compiled executable.
http://rainbowsally.org/rainbowsally...staller.tar.gz. It has an uninstaller if you can find where it installs. :-) ~/bin/src/LQ_Projects Original post continues here... ]

Bash thinks "008" is an octal number. An illegal one. So the part of the backup program that does the incrementing of the build numbers had to be written in C/C++, and it was written without any lq/mc2 dependencies so it can be used by recidivists, and it is now being tested under real-world conditions.

We are not keeping these bug-infested code uploads updated at this time.

When things are finally all working together so that usage and testing are one combined process, we'll either update them or just remove them if the final versions are too different to be recognizable.

I apologize for this, but if we get into a process of having to update the blog as often as we are updating the code we're working with at this point in time there wouldn't be any time to work on the code.

Revisiting the pixel mixing algorithms.

[See recent color mixing toy]

The 'drawing' of graphical objects doesn't usually need to be super-fast in a gui because the images are cached and we usually only need to redraw them when something changes, like a button gettting pressed or a highlight showing when the mouse moves over something.

Except when the images may have to move.

It turns out the mixRgba algorithm worked well enough for pixels that were full blown AARRGGBB pixels but in QT the Qt::<color> things (e.g., Qt::red, Qt::green) were all interpreted as dark shades of blue because they are indexes into a table of colors with values (apparently) less than 0x80.

That is, they are indistinguishable from shades of blue (minus alpha).

We are making some headway with getting the qwt lib to play nice with designer (though it requires completely redefining the palette colors so every widget has it's own palette entry and so foreground/background pairs are adjacent to one another in the Designer) and in this process it became clear that for a useful pixel mixing algorithm that still runs fast, we need to determine whether the pixel is a color table index or not.

One straight forward way would be to require an alpha value. Another is to use C++ typing clues... which leads to this very round-about way of forcing QT to spit out the right value.

From working code...

lqToPixel appears to work for this. So we add it to the parallel mixing algorithm and get something like this. It uses a QColor object to decode the table index to a full AARRGGBB pixel.

Code:
// returns an AARRGGBB pixel for a pixel for a possible Qt::GlobalColor( index )
#define lqToPixel(x) QColor(Qt::GlobalColor(x)).rgb()

QRgb mixRgba(QRgb pixel1, QRgb pixel2, double frac, bool opaque /* true */)
{
  // if the color has no ALPHA set, then consider it a possible color index and
  // convert to AARRGGBB
  if((pixel1 < 0xFFFFFF) || (pixel2 < 0xFFFFFF)) // prescreen for slow code
  {
    if(pixel1 < 0xFFFFFF)
      pixel1 = lqToPixel(pixel1); // sets alpha to FF
      
    if(pixel2 < 0xFFFFFF)
      pixel2 = lqToPixel(pixel2); // sets alpha to FF
  }
  
  // now we're ready to go after ONE floating point operation.
  
  int a, b, c;
  uint res1, res2;
  
  // 8 bit fixed point multipliers
  b = 256 * frac;
  
  // these compare to 0 things where 0 and N are the possible returns run fast
  b = (b < 0 ? 0 : b); 
  
  // and add and sub are faster than a branch.
  c = b - 256;
  c = (c > 0) ? 0 : c;
  b = c + 256;
  
  a = 256 - b;
  
  // lo bits: mask, multiply, mask, shift
  res1 = (((pixel1 & 0x00FF00FF) * a) & 0xFF00FF00) >> 8;
  res1 += ((((pixel2 & 0x00FF00FF) * b) & 0xFF00FF00)) >> 8;
  
  // hi bits: mask, shift, multiply, mask
  res2 = (((pixel1 & 0xFF00FF00) >> 8) * a) & 0xFF00FF00; 
  res2 += (((pixel2 & 0xFF00FF00) >> 8) * b) & 0xFF00FF00; 
  
  return (res1 + res2) | ((-opaque) & 0xFF000000); // set alpha = 255 if opaque
}
The concept here, in case you didn't catch this in the previous test code, is to input two colors and a double float betweein 0 (left) and 1.0 (right) representing a color some distance between the two.
Code:
[pixel1] ---------------- [pixel2]
         0      |       1
             [frac]
For ultra-fast pixel mixing, not only should the indexed color NOT be part of the mixing algorithm but using floating point ratios should also be avoided (using 0-255 to represent 0% to 100%) and the code should be 'inlined' or written as a macro to avoid a call/return pair.

The lq version of the qwt lib is coming along, but slowly. We are indeed making headway, though.

The greatest challenge so far has been to get all the colors of the dials to be settable from Designer, including the analog clock, with one color for the hours and minutes hands and another for the second hand.

- The Computer Mad Science Team.

:-)
Posted in Uncategorized
Views 3538 Comments 3
« Prev     Main     Next »
Total Comments 3

Comments

  1. Old Comment
    The leading zeros being treated as octal thing in bash can be worked around quite easily. No need to rewrite in c/c++ just because of this.

    Code:
    next="$(printf '%04d' $(( 10#$last + 1 )))"
    Posted 06-21-2013 at 04:25 AM by GazL GazL is offline
    Updated 06-21-2013 at 04:36 AM by GazL
  2. Old Comment
    Thanks Gazi.

    I tried the "%.3d" format string and it didn't work.

    Bash is so full of quirks that regardless of the advantage of being able to see exactly what the program does, it's sometimes just not worth learning all the work-arounds.

    But there it is! With (it looks like) 4 digits for the build numbers. :-)
    Posted 06-24-2013 at 11:09 AM by rainbowsally rainbowsally is offline
  3. Old Comment
    Yep, the printf formatting won't work on its own. You need the "10#" prefix on the variable to tell bash, "Look, I know it starts with a zero, but take my word for it, it's decimal!"

    And yes, 4 digits in that example - I lifted it directly from my own incremental backup script and didn't think to change the number of digits.

    Shell syntax is definitely "quirky", I think you chose exactly the right word there.
    Posted 06-24-2013 at 12:18 PM by GazL GazL is offline
 

  



All times are GMT -5. The time now is 11:17 AM.

Main Menu
Advertisement

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.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration