Greyscale bars/Display: Difference between revisions

From Rosetta Code
Content added Content deleted
(Add Seed7 example)
(→‎{{header|C}}: C solve)
Line 81: Line 81:
NEXT b%
NEXT b%
NEXT row%</lang>
NEXT row%</lang>

=={{header|C}}==
Using GTK+2, cairo
<lang c>#include <gtk/gtk.h>
/* do some greyscale plotting */
void gsplot (cairo_t *cr,int x,int y,double s) {
cairo_set_source_rgb (cr,s,s,s);
cairo_rectangle (cr,x,y,1,1);
cairo_fill (cr);
}
/* make a shaded pixbuf */
void expose_event (GtkWidget *widget,GdkEventExpose *event,gpointer data) {
int r,c,x=0;
double f,divs[]={8,16,32,64},adj[]={9,4.2,2.03,1},sh;
cairo_t *cr;
cr = gdk_cairo_create (widget->window);
cairo_scale (cr,5,50);
cairo_set_line_width (cr,0);
for (r=0;r<4;r++) {
c = (r&1)*64-(r%2);
do { /* some dyslexic maths */
f=64.0/divs[r];
sh=(c/(int)(f))*adj[r]/63;
gsplot (cr,x++%64,r,sh);
c+=2*!(r%2)-1;
} while (c != (!(r%2))*64-(r%2));
} cairo_destroy (cr);
return FALSE;
}
/* boilerplate window creation */
int main (int argc, char *argv[]) {
GtkWidget *window;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (window, "expose-event",G_CALLBACK (expose_event), NULL);
g_signal_connect (window, "delete-event", G_CALLBACK(gtk_main_quit), NULL);
gtk_window_set_default_size (GTK_WINDOW(window), 320, 200);
gtk_widget_set_app_paintable (window, TRUE);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}</lang>


=={{header|C++}}==
=={{header|C++}}==

Revision as of 05:10, 10 March 2012

Task
Greyscale bars/Display
You are encouraged to solve this task according to the task description, using any language you may know.

The task is to display a series of vertical greyscale bars (contrast bars) with a sufficient number of bars to span the entire width of the display.

For the top quarter of the display, the left hand bar should be black, and we then incrementally step through six shades of grey until we have a white bar on the right hand side of the display. (This gives a total of 8 bars)

For the second quarter down, we start with white and step down through 14 shades of gray, getting darker until we have black on the right hand side of the display. (This gives a total of 16 bars).

Halfway down the display, we start with black, and produce 32 bars, ending in white, and for the last quarter, we start with white and step through 62 shades of grey, before finally arriving at black in the bottom right hand corner, producing a total of 64 bars for the bottom quarter.

AutoHotkey

Requires the GDI+ Standard Library by tic: http://www.autohotkey.com/forum/viewtopic.php?t=32238 <lang AHK>h := A_ScreenHeight w := A_ScreenWidth pToken := gdip_Startup() hdc := CreateCompatibleDC() hbm := CreateDIBSection(w, h) obm := SelectObject(hdc, hbm) G := Gdip_GraphicsFromHDC(hdc)

OnExit, Exit

Gui +E0x80000 +LastFound +OwnDialogs +Owner +AlwaysOnTop hwnd := WinExist() Gui Show, NA

columnHeight := h/4

Loop 4 { columnY := (A_Index-1) * columnHeight columnCount := 2**(A_Index+2) colorgap := 255 / (columnCount-1) columnWidth := w/ColumnCount If (A_Index & 1) colorComp := 0 else colorComp := 255 ,colorgap *= -1 MsgBox % colorGap * columnCount Loop % columnCount { columnX := (A_Index-1) * columnWidth pBrush := Gdip_BrushCreateSolid(QColor(colorComp, colorComp, colorComp)) Gdip_FillRectangle(G, pBrush, columnX, columnY, columnWidth, columnHeight) Gdip_DeleteBrush(pBrush) colorComp += colorgap } SetFormat, IntegerFast, hex SetFormat, IntegerFast, D }

UpdateLayeredWindow(hwnd, hdc, 0, 0, W, H)

SelectObject(hdc, obm) DeleteObject(hbm) DeleteDC(hdc) Gdip_DeleteGraphics(G) Return

Esc:: Exit: Gdip_Shutdown(pToken) ExitApp

QColor(r, g, b){ return 0xFF000000 | (r << 16) | (g << 8) | (b) }</lang>

BBC BASIC

<lang bbcbasic>MODE 8:REM 640 x 512 pixel display mode: BBC BASIC gives 2 graphics points per pixel REM (0,0) is the bottom left of the display GCOL 1 :REM Select colour one for drawing FOR row%=1 TO 4

 n%=2^(row%+2)
 w%=1280/n%
 py%=256*(4-row%)
 FOR b%=0 TO n%-1
   g%=255*b%/(n%-1)
   IF n%=16 OR n%=64 THEN g%=255-g%
   COLOUR 1,g%,g%,g%  : REM Reprogram colour 1 to the grey we want
   RECTANGLE FILL w%*b%,py%,w%,256
 NEXT b%

NEXT row%</lang>

C

Using GTK+2, cairo <lang c>#include <gtk/gtk.h> /* do some greyscale plotting */ void gsplot (cairo_t *cr,int x,int y,double s) {

   cairo_set_source_rgb (cr,s,s,s);
   cairo_rectangle (cr,x,y,1,1);
   cairo_fill (cr);

} /* make a shaded pixbuf */ void expose_event (GtkWidget *widget,GdkEventExpose *event,gpointer data) {

   int r,c,x=0;
   double f,divs[]={8,16,32,64},adj[]={9,4.2,2.03,1},sh;
   cairo_t *cr;
   cr = gdk_cairo_create (widget->window);
   cairo_scale (cr,5,50);
   cairo_set_line_width (cr,0);
   for (r=0;r<4;r++) {
       c = (r&1)*64-(r%2);
       do { /* some dyslexic maths */
           f=64.0/divs[r];
           sh=(c/(int)(f))*adj[r]/63;
           gsplot (cr,x++%64,r,sh);
           c+=2*!(r%2)-1;
       } while (c != (!(r%2))*64-(r%2));
   } cairo_destroy (cr);
   return FALSE;

} /* boilerplate window creation */ int main (int argc, char *argv[]) {

   GtkWidget *window;
   gtk_init (&argc, &argv);
   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
   g_signal_connect (window, "expose-event",G_CALLBACK (expose_event), NULL);
   g_signal_connect (window, "delete-event", G_CALLBACK(gtk_main_quit), NULL);
   gtk_window_set_default_size (GTK_WINDOW(window), 320, 200);
   gtk_widget_set_app_paintable (window, TRUE);
   gtk_widget_show_all (window);
   gtk_main ();
   return 0;

}</lang>

C++

using Qt 4.6

file greytones.h

<lang cpp>#ifndef MYWIDGET_H

  1. define MYWIDGET_H
  2. include <QWidget>

class QPaintEvent ;

class MyWidget : public QWidget { public :

  MyWidget( ) ;

protected :

  void paintEvent( QPaintEvent * ) ;

} ;

  1. endif</lang>
file greytones.cpp

<lang cpp>#include <QtGui>

  1. include "greytones.h"

MyWidget::MyWidget( ) {

  setGeometry( 0, 0 , 640 , 480 ) ;

}

void MyWidget::paintEvent ( QPaintEvent * ) {

  QBrush myBrush( Qt::SolidPattern ) ;
  QPainter myPaint( this ) ;
  int run = 0 ; //how often have we run through the loop ?
  int colorcomp = 0 ;
  for ( int columncount = 8 ; columncount < 128 ; columncount *= 2 ) {
     int colorgap = 255 / columncount ;
     int columnwidth = 640 / columncount ; // 640 being the window width
     int columnheight = 480 / 4 ; //we're looking at quarters
     if ( run % 2 == 0 ) { //we start with black columns 

colorcomp = 0 ;

     }
     else { //we start with white columns 

colorcomp = 255 ; colorgap *= -1 ; //we keep subtracting color values

     }
     int ystart = 0 + columnheight * run ; //determines the y coordinate of the first column per row
     int xstart = 0 ;
     for ( int i = 0 ; i < columncount ; i++ ) {

myBrush.setColor( QColor( colorcomp, colorcomp , colorcomp ) ) ; myPaint.fillRect( xstart , ystart , columnwidth , columnheight , myBrush ) ; xstart += columnwidth ; colorcomp += colorgap ; //we choose the next color

     }
     run++ ;
  }

}</lang>

file main.cpp

<lang cpp>#include <QApplication>

  1. include "greytones.h"

int main( int argc, char * argv[ ] ) {

  QApplication app( argc , argv ) ;
  MyWidget window ;
  window.setWindowTitle( QApplication::translate( "greyScales" , "grey scales demonstration" ) ) ;
  window.show( ) ;
  return app.exec( ) ;

}</lang>

Icon and Unicon

This procedure uses code from the Colour bars/Display task, specifically the: DrawTestCard procedure and testcard, band, and bar records which are used to build structures that can be easily transcribed into independent bands and bars.

<lang Icon>link graphics,printf,numbers

procedure main()

  DrawTestCard(GreyScale_TestCard())
  WDone()

end

procedure greyscale(l,h,s) #: generate s greys over range l:h every i := round(l to h+1 by ((h-l)/(s-1.))) do suspend sprintf("%d,%d,%d",i,i,i) # return rgb black-grey-white end

procedure GreyScale_TestCard() #: return greyscale testcard

  TC := testcard(,"GreyScale Test Card",
                 width := 800, height := 600, 
                 list(numbands := 4) )
  maxv := 2^16-1                                      # largest colour value
  every (iv := [], i := 1 to numbands) do {           # for each band       
     every put(v := [], greyscale(0,maxv,2^(2+i)))    # compute greyscale

put(iv, if i%2 = 0 then v else reverse(v)) # switch directions }

  every r := height/numbands * ((i := 1 to numbands)-1) + 1 do {
     TC.bands[i] := band(r,[])
     every c := width/(*iv[i]) * ((j := 1 to *iv[i])-1) + 1 do 
        put(TC.bands[i].bars, bar( c, iv[i,j]))
     put((TC.bands[i]).bars, bar(width))              # right sentinal 
     }
  put(TC.bands,band(height))                          # bottom sentinal
  return TC

end</lang>

graphics.icn supports graphics printf.icn provides sprintf, etc. numbers.icn provides round

J

Solution: <lang j> load 'viewmat'

  size=. 2{.".wd'qm' NB. J6
  size=. getscreenwh_jgtk_  NB. J7
  rows=. (2^3+i.4),._1^i.4
  bars=. ((64%{.)#[:(<:@|%~i.)*/)"1 rows
  togreyscale=. (256#. [:<.255 255 255&*)"0
  'rgb' viewmat (4<.@%~{:size)# (64<.@%~{.size)#"1 togreyscale bars</lang>

Note that this solution is not posted directly to the screen but to a viewmat window, which may not be centered.

Java

using basically the same code as in the C++ example <lang Java>import javax.swing.* ; import java.awt.* ;

public class Greybars extends JFrame {

  private int width ;
  private int height ;
  public Greybars( )  {
     super( "grey bars example!" ) ;
     width = 640 ;
     height = 320 ;
     setSize( width , height ) ;
     setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ) ;
     setVisible( true ) ;
   }
   public void paint ( Graphics g ) {
     int run = 0 ;
     int colorcomp = 0 ; //component of the color
     for ( int columncount = 8 ; columncount < 128 ; columncount *= 2 ) {

int colorgap = 255 / columncount ; //by this gap we change the background color int columnwidth = width / columncount ; int columnheight = height / 4 ; if ( run % 2 == 0 ) //switches color directions with every for loop colorcomp = 0 ; else { colorcomp = 255 ; colorgap *= -1 ; } int ystart = 0 + columnheight * run ; int xstart = 0 ; for ( int i = 0 ; i < columncount ; i++ ) { Color nextColor = new Color( colorcomp, colorcomp, colorcomp ) ; g.setColor( nextColor ) ; g.fillRect( xstart , ystart , columnwidth , columnheight ) ; xstart += columnwidth ; colorcomp += colorgap ; } run++ ;

     }
   }
   public static void main( String[ ] args ) {
      Greybars gb = new Greybars( ) ;
   }

}</lang>

JavaScript

Live Demo: http://jsfiddle.net/gcN9g/embedded/result/ <lang JavaScript><html><body> <script type="text/javascript"> var width = 640; var height = 400; var c = document.createElement("canvas"); c.setAttribute('id', 'myCanvas'); c.setAttribute('style', 'border:1px solid black;'); c.setAttribute('width', width); c.setAttribute('height', height); document.body.appendChild(c); var ctx = document.getElementById('myCanvas').getContext("2d");

var columnCount = 8; // number of columns var rowCount = 4; // number of rows var direction = 1; // 1 = from left to right, 0 = from right to left var blackLeft = 1; // black is left: 1 = true, 0 = false for(var j = 0; j < rowCount; j++){

   for(var i = 0; i < columnCount; i++){
       ctx.fillStyle = 'rgba(0,0,0,'+ (blackLeft-(1/(columnCount-1)*i))*direction +')';  
       ctx.fillRect(
           (width/columnCount)*i,(height/rowCount)*j,
           (width/columnCount),(height/rowCount)
           ); 
       }
   columnCount *= 2; 
   direction *= -1; 
   blackLeft = blackLeft ? 0 : 1;
   }

</script> </body></html> </lang>

Liberty BASIC

Black boxes were added around each color for ease of counting the boxes. <lang lb> nomainwin

WindowWidth =DisplayWidth WindowHeight =DisplayHeight

open "Grey bars" for graphics_fs_nsb as #w

  1. w "trapclose [quit]"
  2. w "down"

bars =4 ' alter for more, finer bars.

for group =0 to bars -1

   for i = 0 to 2^( 3 +group) -1
       #w "place "; WindowWidth *i /( 2^( 3 +group)); " "; WindowHeight *group /bars
       if ( group =0) or ( group =2) then
           g$ =str$( int( 255 *i /(2^( 3 +group)-1)))
       else
           g$ =str$( 255 -int( 255 *i /(2^( 3 +group)-1)))
       end if
       grey$ =g$ +" " +g$ +" " +g$
       #w "backcolor "; grey$
       '#w "color ";     grey$ 'rem out for outlined areas..
       #w "boxfilled "; WindowWidth *( i +1) /8 ; " "; WindowHeight *( group +1) /bars
   next i

next group

wait [quit] close #w end

</lang> Resulting GreyScale image without the outlines.

OCaml

<lang ocaml>open Graphics

let round x = truncate (floor (x +. 0.5))

let () =

 open_graph "";
 let width = size_x ()
 and height = size_y () in
 let bars = [| 8; 16; 32; 64 |] in
 let n = Array.length bars in
 Array.iteri (fun i bar ->
   let part = float width /. float bar in
   let y = (height / n) * (n - i - 1) in
   for j = 0 to pred bar do
     let x = round (float j *. part) in
     let v = round (float j *. 255. /. float (bar - 1)) in
     let v = if (i mod 2) = 0 then v else 255 - v in
     set_color (rgb v v v);
     fill_rect x y (round part) (height / n)
   done
 ) bars;
 ignore(read_key())</lang>

Run with:

$ ocaml graphics.cma greyscale_bars.ml

PureBasic

<lang PureBasic>If Not InitKeyboard(): End: EndIf ;can't init keyboard If Not InitSprite(): End: EndIf ;can't init sprite/screen library If Not ExamineDesktops(): End: EndIf ;can't retrieve information about desktop

Define height.f, width.f, depth height.f = DesktopHeight(0) width.f = DesktopWidth(0) depth = DesktopDepth(0)

If OpenScreen(width, height, depth, "Press ENTER to exit")

 Define vsCount, v, h, columns, columnWidth, endColor, shade
 StartDrawing(ScreenOutput())
   vsCount = 4
   For v = 0 To 3
     columns = (v + 1) * 8
     columnWidth = Round(width / columns, #PB_Round_Up)
     endColor = $FFFFFF * (v % 2)     ;alternate between black and white for first and last bar
     Box(0, (height * v) / vsCount, columnWidth, height / vsCount, endColor)
     For h = 1 To columns - 2
       If v % 2 = 0
         shade = 256 / columns * (h + 1)
       Else
         shade = 256 / columns * (columns - (h + 1))
       EndIf 
       Box((width * h) / columns, (height * v) / vsCount, columnWidth, height / vsCount, RGB(shade, shade, shade))
     Next
     
     Box((width * (columns - 1)) / columns, (height * v) / vsCount, columnWidth, height / vsCount, $FFFFFF - endColor)
   Next 
 StopDrawing()
 FlipBuffers()
 Repeat
   Delay(10)
   ExamineKeyboard()
 Until KeyboardPushed(#PB_Key_Escape) Or KeyboardPushed(#PB_Key_Return)
 CloseScreen()

EndIf</lang> Press Enter or Escape to exit the programs's display.

Scala

<lang scala>import scala.swing._

class GreyscaleBars extends Component {

 override def paintComponent(g:Graphics2D)={
   val barHeight=size.height>>2
   for(run <- 0 to 3; colCount=8<<run){
     val deltaX=size.width.toDouble/colCount
     val colBase=if (run%2==0) -255 else 0
     for(x <- 0 until colCount){
       val col=(colBase+(255.0/(colCount-1)*x).toInt).abs
       g.setColor(new Color(col,col,col))
       val startX=(deltaX*x).toInt
       val endX=(deltaX*(x+1)).toInt
       g.fillRect(startX, barHeight*run, endX-startX, barHeight)
     }
   }
 }  

}</lang> Open window:

<lang scala>new MainFrame(){

 title="Greyscale bars"
 visible=true
 preferredSize=new Dimension(640, 320)
 contents=new GreyscaleBars()

}</lang>

Seed7

<lang seed7>$ include "seed7_05.s7i";

 include "draw.s7i";
 include "keybd.s7i";

const proc: main is func

 local
   var integer: barHeight is 0;
   var integer: barNumber is 0;
   var integer: colCount is 0;
   var integer: deltaX is 0;
   var integer: x is 0;
   var integer: col is 0;
 begin
   screen(640, 480);
   KEYBOARD := GRAPH_KEYBOARD;
   barHeight := height(curr_win) div 4;
   for barNumber range 0 to 3 do
     colCount := 8 << barNumber;
     deltaX := width(curr_win) div colCount;
     for x range 0 to pred(colCount) do
       if barNumber rem 2 = 0 then
         col := 65535 - 65535 div pred(colCount) * x;
       else
         col := 65535 div pred(colCount) * x;
       end if;
       rect(deltaX * x, barHeight * barNumber, deltaX, barHeight,
           color(col, col, col));
     end for;
   end for;
   ignore(getc(KEYBOARD));
 end func;</lang>

Tcl

Library: Tk

<lang tcl>package require Tcl 8.5 package require Tk 8.5

wm attributes . -fullscreen 1 pack [canvas .c -highlightthick 0] -fill both -expand 1

  1. Add more values into this to do more greyscale bar variations

set splits {8 16 32 64} set dy [expr {[winfo screenheight .c] / [llength $splits]}] set y 0 foreach s $splits {

   set dx [expr {double([winfo screenwidth .c]) / $s}]
   set dc [expr {double(0xFF) / ($s-1)}]
   for {set i 0} {$i < $s} {incr i} {

set c [expr {int($i * $dc)}] set x [expr {int($i * $dx)}] .c create rectangle $x $y [expr {$x+$dx+1}] [expr {$y+$dy+1}] \

           -fill [format "#%02x%02x%02x" $c $c $c] -outline {}
   }
   incr y $dy

}</lang>

ZX Spectrum Basic

ZX Spectrum Basic cannot natively produce greyscale. However, the colours have been cleverly arranged, so that the native colours give monochrome signals in sequential order of brightness. Wind the colour down, or use a black and white television and we have a set of 8 bars:

<lang basic>10 REM wind the colour down or use a black and white television to see greyscale bars 20 REM The ZX Spectrum display is 32 columns wide, so we have 8 columns of 4 spaces 30 FOR r=0 TO 20: REM There are 21 rows 40 FOR c=0 TO 7: REM We use the native colour sequence here 50 PRINT " ";: REM four spaces, the semicolon prevents newline 60 NEXT c 70 REM at this point the cursor has wrapped, so we don't need a newline 80 NEXT r</lang>