HTML

Az élet kódjai

Csináld maga. Senki nem csinálja meg helyetted.

Friss topikok

Vonalat akarok rajzolni

2011.09.29. 11:48 Travis.CG

Nem nehéz vonalat rajzolni. Vagy mégis? Mennyi kódot kell írni, hogy az ember kirakjon a képernyőre egy vonalat?

Mikor még csak C64-em volt, nem okozott gondot, hogy kirajzoljak egy vonalat. Igaz, ehhez a Simon's Basic nevű segédalkalmazás kellett, de gond nélkül meg tudtam jeleníteni, amit szerettem volna. Nem kellett hozzá voodoo mágia:

10 HIRES 0,1
20 LINE 0,0,320,200,1
Ahogy fejlődött a számítástechnika, a vonal rajzolása is egyre bonyolultabb lett. A 486-oson Turbó Pascallal már nem volt olyan egyszerű, de még belefért a keretbe. Be kellett tölteni valami meghajtót és már rajzolhatott is az ember.

Uses graph;
var grDriver: Integer;
    grMode: Integer;

Begin
  grDrive := Detect;
  InitGraph(grDriver, grMode, 'C:\BP\BGI');
  MoveTo(0,0);
  LineTo(320,200);
End.
De aki lemondott az önállóan futtatható állományok kiváltságáról, az még QBasicben is rajzolhatott.

SCREEN 13
LINE (0,0) - (320,200), 1
Utána történt valami. Megjelentek a grafikus felhasználói felületek. Ez a megállapítás természetesen történelmileg cáfolható, de az én személyes életemben így történt. Nem tudtam még akkor semmit Mac-ről, Amigáról, sem Xeroxról. Tehát megjelentek a grafikus felhasználói felületek, én pedig örültem, hogy végre talán egyszerűsödik a grafika használata, hiszen már eleve ott van.

Igaz, már nem kellett az ocsmány karakteres képernyőről átváltani a megváltást hozó grafikára, viszont kellett ablakot nyitni! Az ablak nyitása pedig nem volt olyan egyszerű. Én továbbra is csak vonalat akartam húzni, de ehhez meg kellett érteni az üzenetküldö rendszert, callback függvényeket, Windows osztályokat. Ha ezen átverekedtük magunkat, akkor lehetett vonalat rajzolni.

#include <windows.h>

LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM);

int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){

   static char szNev[]="Proba";
   HWND      hwnd;
   MSG       msg;
   WNDCLASS  wndclass;

   if (!hPrevInstance) {
       wndclass.style=CS_HREDRAW | CS_VREDRAW;
       wndclass.cbClsExtra=0;
       wndclass.cbWndExtra=0;
       wndclass.hInstance=hInstance;
       wndclass.hIcon=0;
       wndclass.hCursor= LoadCursor(0,IDC_ARROW);
       wndclass.hbrBackground=GetStockObject(LTGRAY_BRUSH);
       wndclass.lpszMenuName=0;
       wndclass.lpszClassName=szNev;
       wndclass.lpfnWndProc=WindowProc;
       RegisterClass(&wndclass);
   };

   hwnd=CreateWindow(szNev,
    "Proba Ablak",
    WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    0,
    0,
    hInstance,
    NULL);

   ShowWindow(hwnd,nCmdShow);
   UpdateWindow(hwnd);

   while (GetMessage(&msg,0,0,0)){
      TranslateMessage(&msg);
      DispatchMessage(&msg);
   }

   return msg.wParam;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){
   HDC hdc;
   PAINTSTRUCT ps;

   switch (message){
      case WM_PAINT:
        hdc=BeginPaint(hwnd, &ps);
        MoveTo(hdc, 0, 0);
        LineTo(hdc, 320, 200);
        EndPaint(hwnd, &ps);
      return 0;
      case WM_DESTROY:
        PostQuitMessage(0);
      return 0;
   }
   return DefWindowProc(hwnd, message, wParam, lParam);
}
Mikor először használtam Visual Basicet (4.0), akkor egy pillanatra hatalmas kő esett le a szívemről. Először tudtam úgy rajzolni, hogy nem kellett a Windows lelki világával foglalkozni. Csak húztam egy ablakot és még a print üzenetek is megjelentek rajta! Felemelő érzést volt, még akkor is, ha a végleges futtatható fájlok mellé vb40016.dll-t kellett csomagolni (A példaprogram csak az ablak aktiválásánál használt szubrutint tartalmazza, valójában kicsit több sorból áll a forráskód).

Private Sub Form_Activate()
Line (0,0) - (320,200), 1
End Sub
A Delphi már normális exe-t készített. Adott Canvas objektumot. Azzal is lehetett rajzolni, de már nem volt az az egyszerű eset, mint a Visual Basic (a kód itt is csak egy részletet tartalmaz).

procedure TForm1.FormActivate(Sender: TObject);
begin
  Canvas.MoveTo(0,0);
  Canvas.LineTo(320, 200);
end;
Utána ismerkedtem meg a Linux-szal. Mintha visszafordult volna az idő! Az svgalib segítségével konzolból tudtam vonalakat feszíteni két pont közé, akár csak Turbo Pascalban. Cserébe root-nak kellett lennem, ami tudjuk mit jelent Linux alatt. A későbbi svgalib helper modul igyekezett javítani a helyzeten.

#include <vga.h>
int main(int argc, char **argv){
  vga_init();
  vga_setmode(G320x200x16);
  vga_setcolor(4);
  vga_drawline(0,0,320,200);
  vga_setmode(TEXT);
}

Pusztán az X-et használni rajzolásra, őrültség. Ha a Windows 3.1 modelljét feleslegesnek ítéltem, akkor a puszta X használata maga a tömény mazochizmus. Ha pedig GTK-t vagy QT-t használ az ember, akkor csökkenti a hordozhatóságot.

Néha az is megesett velem, hogy nem is a képernyőre kellett rajzolni, hanem egy képállományba (mondjuk mert egy weboldalhoz dinamikusan generáltam a képet). Ilyenkor a GD nevű könyvtárat használtam. A változatosság kedvéért PHP-ból:

<?php
   $p = imagecreatetruecolor(320,200);
   imagecolorallocate($p, 0, 0, 0);
   $c = imagecolorallocate($p, 255, 255, 255);
   imageline($p, 0, 0, 320, 200, $c);
   header("Content-type: image/png");
   imagepng($p);
   imagedestroy($p);
?>
Általában viszont a képernyőn akarjuk látni az eredményt, nem egy fájlban.

Az OpenGL Gluttal már egészen jó alternatíva. Legalábbis a régi glBegin-glEnd páros. Hangsúlyozom, vonal rajzolásról beszélek. Amikor a több millió poligon megjelenítésének oltárán feláldozták a gyors prototipizálás lehetőségét, ismét új alternatíva után kellett néznem.

#include <GL/glut.h>

void Display(){
   glBegin(GL_LINES);
   glVertex2f(0,0);
   glVertex2f(320,200);
   glEnd();
   glutSwapBuffers();
}

void keyfunc(unsigned char key, int x, int y){
   switch(key){
      case 27: exit(0);
   }
}

int main(int argc, char *argv[]){
   glutInit(&argc, argv);
   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
   glutInitWindowSize(1024,768);
   glutCreateWindow("Vonal");

   glutDisplayFunc(Display);
   glutKeyboardFunc(keyfunc);
   glutIdleFunc(Display);
   glutMainLoop();

   return(0);
}
Az egyik lehetőség a Java volt. Ez a nyelv azt ígérte, hogy az egy vonalas rajzprogramom platformfüggetlen lesz. Sajnos a grafika kifejezetten platformfüggő. A példaprogram egy vonal rajzoló applet, hogy minél kevesebbet kelljen írni:

import java.awt.*;
import java.applet.*;

public class Line extends Applet {
  public void init(){
  }

  public void stop(){
  }

  public void paint(Graphics g){
    g.drawLine(0,0,320,200);
  }
}
A másik lehetőség, hogy maradok Windows alatt és áttérek a C#-ra. Amit azt illeti, az Etch-a-sketch című demónkhoz C#-ban kezdtem el írni egy szerkesztőprogramot, ami a demó grafikáit készítette volna el. Érdekes módon ez a demó is főleg vonalakból áll.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace drawing
{
    public partial class Form1 : Form
    {
        Graphics Canvas;
        Pen drawpen;

        public Form1()
        {
           InitializeComponent();
           Canvas = this.CreateGraphics();
           drawpen = new Pen(Color.Black);
        }

        private void Form1_Activated(object sender, System.EventArgs e)
        {
           Canvas.DrawLine(drawpen, 0,0, 320, 200);
        }
    }
}

A példa itt is csak egy részletet mutat be abból, ami a vonal rajzoláshoz kell. Lehet látni, hogy a példák legtöbbje nem is a grafikáról szól, hanem egyéb járulékos elemekről, amelyek nélkül a grafikus felületen nem tudunk pixeleket színezni.

Mit is akarok? Vonalat húzni, gyorsan, eszközfüggetlenül. Ahogyan Perl alatt villám sebességgel feldolgozom a szöveges állományokat, úgy akarom egy ablakban megjeleníteni a vonalaimat. Szeretném, ha ez platform független lenne. Van remény? Igen van. Úgy hívják Processing. Végre tudok vonalat rajzolni.

void setup(){
   size(320,200);
}

void draw(){
   line(0,0,320,200);

Frissítés:

Persze a Python is tartalmaz ügyes modulokat:

import Image
import ImageDraw

image = Image.new('RGB', (1024, 768)) # width and height
draw  = ImageDraw.Draw(image)
draw.line((0,0,1024,768), fill = (0,255,0)) # coordinates and color

 

Szólj hozzá!

Címkék: programozás filozofálás

A bejegyzés trackback címe:

https://cybernetic.blog.hu/api/trackback/id/tr313264772

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

Nincsenek hozzászólások.
süti beállítások módosítása