venerdì 28 settembre 2012

Creare grafici in C++

Su Debian la libreria e' presente in forma pacchettizzata ma solo nella versione 1 (almeno nella versione Stable), ho quindi preferito installare la libreria 2.0 scaricando il file tgz da qui, scompattandolo e quindi digitando i comandi
cmake
make 
make install

la libreria si installa in /usr/local per cui in fase di compilazione il file make deve contenere questa informazione
---------------------------------------
main: main.cpp
    g++ -Wall -O3 -o mathgl_demo main.cpp -I/usr/local/include -L/usr/local/lib -lmgl
---------------------------------------

Nel file di esempio vengono creato un grafico definito come funzione y=f(x) ed un grafico XY per plottare eventuali dati sperimentali ricavati dalla lettura di un file testo

----------------------------------------
#include <mgl2/mgl.h>

int main()
{
mglGraph gr,gr2;

gr.FPlot("sin(pi*x)");
gr.Axis();
gr.Grid();
gr.Box();
gr.Title("Seno");
gr.WriteFrame("Funzione.png");

mglData y("file.txt");
mglData xdat=y.SubData(0),ydat=y.SubData(1);
gr2.SetRanges(xdat,ydat);
gr2.Axis();
gr2.Grid();
gr2.Box();
gr2.Title("XY");
gr2.Plot(xdat,ydat,"r#.");
gr2.WriteFrame("XY.png");
}

----------------------------------------
Di seguito il risultato del programma



Come al solito si puo' scaricare il file del progetto completo da qui

Creare Pdf via C

Un esempio semplice per la creazione da programma di file PDF. Per questo esempio e' stata usata la libreria Haru che si trova gia' pacchettizza in Debian

apt-get install libhpdf-2.1.0 libhpdf-dev

per la compilazione e' sufficiente il seguente comando
gcc -Wall -O3 -lhpdf test.c test 

Nell'esempio vengono uniti comandi per la creazione di testo e gestione di immagini
---------------------------------------------------
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <setjmp.h>
#include "hpdf.h"

jmp_buf env;

#ifdef HPDF_DLL
void __stdcall
#else
void
#endif
error_handler  (HPDF_STATUS   error_no,
                HPDF_STATUS   detail_no,
                void         *user_data)
{
    printf ("ERROR: error_no=%04X, detail_no=%u\n", (HPDF_UINT)error_no,
                (HPDF_UINT)detail_no);
    longjmp(env, 1);
}

int no = 0;

void PrintText(HPDF_Page page)
{
    char buf[512];
    HPDF_Point pos = HPDF_Page_GetCurrentTextPos (page);

    no++;
    snprintf (buf, 512, ".[%d]%0.2f %0.2f", no, pos.x, pos.y);
    HPDF_Page_ShowText(page, buf);
}



int
main (int argc, char **argv)
{
    HPDF_Doc  pdf;
    HPDF_Page page;
    HPDF_Font font;
    HPDF_REAL page_height;
    HPDF_Rect rect;
    HPDF_Image image;

    const char* SAMP_TXT = "Nel mezzo del cammin di nostra vita. ";
    const char* fname = "prova_pdf.pdf";

    pdf = HPDF_New (error_handler, NULL);
    if (!pdf) {
        printf ("error: cannot create PdfDoc object\n");
        return 1;
    }

    if (setjmp(env)) {
        HPDF_Free (pdf);
        return 1;
    }

    /* add a new page object. */
    page = HPDF_AddPage (pdf);
    HPDF_Page_SetSize (page, HPDF_PAGE_SIZE_A5, HPDF_PAGE_PORTRAIT);

    page_height = HPDF_Page_GetHeight (page);

    font = HPDF_GetFont (pdf, "Helvetica", NULL);
    HPDF_Page_SetTextLeading (page, 20);

    rect.left = 25;
    rect.top = 545;
    rect.right = 200;
    rect.bottom = rect.top - 40;

    HPDF_Page_Rectangle (page, rect.left, rect.bottom, rect.right - rect.left,rect.top - rect.bottom);
    HPDF_Page_Stroke (page);

    HPDF_Page_BeginText (page);
    HPDF_Page_SetFontAndSize (page, font, 10);
    HPDF_Page_TextOut (page, rect.left, rect.top + 3, "Titolo del Box");

    HPDF_Page_SetFontAndSize (page, font, 13);
    HPDF_Page_TextRect (page, rect.left, rect.top, rect.right, rect.bottom,SAMP_TXT, HPDF_TALIGN_LEFT, NULL);

    HPDF_Page_EndText (page);

    /* Draw image to the canvas. */
    image = HPDF_LoadJpegImageFromFile (pdf, "gattino.jpg");
    HPDF_Page_DrawImage (page, image, 100, 200, HPDF_Image_GetWidth (image),HPDF_Image_GetHeight (image));


    /* salva sul file*/
    HPDF_SaveToFile (pdf, fname);

    HPDF_Free (pdf);

    return 0;
}

---------------------------------------------------




Link al progetto

Primi passi (brutti) con GoLang

Per curiosita' ho voluto provare ad usare il linguaggio Go di Google per creare l'insieme di Mandelbrot e dovendo partire da zero ho cercato un tutorial su Internet andando a cadere qui dove c'e' un esempio completo che riporto



---------------------------------------
import (
 "fmt"
 "os"
 "math"
 "image"
 "image/png"
 "bufio"
 "flag"
)

var pointX = flag.Float64("x", -2.0, "X coordinate of starting point of Mandelbrot or fix point for Julia (range: 2.0 to 2.0)")
var pointY = flag.Float64("y", -2.0, "Y coordinate of starting point of Mandelbrot or fix point for Julia (range: 2.0 to 2.0)")
var zoom = flag.Float64("z", 1.0, "Zoom level (only working properly for Mandelbrot)")
var julia = flag.Bool("julia", false, "Turn on Julia calculation")
var maxIter = flag.Int("maxIter", 51, "Max number of point iterations")
var imgSize = flag.Int("imgSize", 1000, "Size of the image")

func main() {
 flag.Parse()

 fmt.Printf("X: %f\n", *pointX)
 fmt.Printf("Y: %f\n", *pointY)
 fmt.Printf("Zoom: %f\n", *zoom)
 fmt.Printf("Julia: %t\n", *julia)
 fmt.Printf("MaxIter: %d\n", *maxIter)
 fmt.Printf("ImgSize: %d\n", *imgSize)

 start := time.Nanoseconds()
 img := CalculateImage(*imgSize, *imgSize)
 end := time.Nanoseconds()
 fmt.Printf("Time: %d ms\n", (end - start) / 1000 / 1000) // ms
 WriteImage(img)
}

func CalculateImage(imgWidth int, imgHeight int) *image.NRGBA {
 img := image.NewNRGBA(imgWidth, imgHeight)
 minCx := -2.0
 minCy := -2.0
 if !*julia {
 minCx = *pointX
 minCy = *pointY
 }
 maxSquAbs := 4.0 // maximum square of the absolute value
 // calculate step widths
 stepX := math.Abs(minCx - 2.0) / float64(imgWidth) / *zoom
 stepY := math.Abs(minCy - 2.0) / float64(imgHeight) / *zoom
 cx := 0.0
 cy := 0.0
 for px := 0; px < imgWidth; px++ {
 cx = minCx + float64(px) * stepX

 for py := 0; py < imgHeight; py++ {
 cy = minCy + float64(py) * stepY

 iterValue := PointIteration(cx, cy, maxSquAbs, *maxIter)

 color := ChooseColor(iterValue, *maxIter)
 img.Set(px, py, color)
 }
 }
 return img
}

func PointIteration(cx float64, cy float64, maxSquAbs float64, maxIter int) int {
 squAbs := 0.0
 iter := 0
 x := 0.0
 y := 0.0
 if *julia {
 x = cx
 y = cy
 cx = *pointX
 cy = *pointY
 }

 for squAbs <= maxSquAbs && iter < maxIter {
 xt := (x * x) - (y * y) + cx // z^2
 yt := (2.0 * x * y) + cy // z^2
 //xt := x * (x*x - 3*y*y) + cx // z^3
 //yt := y * (3*x*x - y*y) + cy // z^3
 //xt := x * (x*x*x*x - 10*x*x*y*y + 5*y*y*y*y) + cx // z^5
 //yt := y * (5*x*x*x*x - 10*x*x*y*y + y*y*y*y) + cy // z^5
 x = xt
 y = yt
 iter++
 squAbs = (x * x) + (y * y)
 }
 return iter;
}

func ChooseColor(iterValue int, maxIter int) *image.NRGBAColor {
 val := uint8(iterValue)
 if iterValue == maxIter {
 return &image.NRGBAColor {0, 0, 0, 255}
 }
 multi := uint8(255 / maxIter)
 return &image.NRGBAColor {0, val*multi, 0, 255}
 //return &image.NRGBAColor{^(val*multi), ^(val*multi), ^(val*multi), 255} // grey
}

func WriteImage(img *image.NRGBA) {
 file, err := os.Create("mandelbrot.png")
 if err != nil {
 fmt.Printf("Could not create file %s", file.Name())
 }
 writer := bufio.NewWriter(file)
 png.Encode(writer, img)
 writer.Flush()
 file.Close()
}

---------------------------------------

lanciato il comando
go run mandelbrot.go
ho ottenuto i seguenti messaggi di errore

come si vedono ci sono molti errori...possibile che sia stato pubblicato un sorgente cosi' buggato??
andando a vedere meglio nel dettaglio si vede che dalla data di pubblicazione del post (21/1/2012) alla data odierna alcune funzioni sono state sostituite da altre (e non considerate semplicemente come deprecate come di solito accade)

sono abituato ad un linguaggio di programmazione che cambia spesso come accade in Android ma francamente cosi' e' troppo e penso che lascero' stare Go fino a quando non diventa piu' stabile con una migliore documentazione

Intel C Compiler vs GCC in Mandelbrot

Ho provato a verificare la differenza tra Gcc ed il compilatore Intel C++ (icc) per quanto riguarda la velocita' e l'ottimizzazione dei calcoli
Per fare cio' e' stato impiegato il programma per generare l'insieme di Mandelbrot gia' presentato in un precedente post usando gli stessi switch di compilazione all'interno del file make



Makefile
------------------------------------------------------
main: mand_sdl.c
    /opt/intel/bin/icc -Wall -O3 mand_sdl.c -o mand_sdl_icc -lSDL
    gcc -Wall -O3 mand_sdl.c -o mand_sdl_gcc -lSDL

------------------------------------------------------

Il programma e' il seguente
 mand_sdl.c
------------------------------------------------------
 #include "SDL/SDL.h"
#include <stdio.h>

#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define SCREEN_DEPTH 8

float re_min = -2.0;
float im_min = -1.2;

float re_max = 1.0;
float im_max = 1.2;
int iterazioni = 255;


float a,b;
float x,y,x_new,y_new;

int test;

int k,j,i;

int keypress = 0;


int main() {

SDL_Surface *screen;
Uint8       *p;

float re_factor = (re_max-re_min);
float im_factor = (im_max-im_min);
   
SDL_Init(SDL_INIT_VIDEO);
screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_DEPTH, SDL_SWSURFACE);

for (i=0;i<SCREEN_HEIGHT;i++)
    {
    for (j=0;j<SCREEN_WIDTH;j++)
        {
        a = re_min+(j*re_factor/SCREEN_WIDTH);  
        b = im_min+(i*im_factor/SCREEN_HEIGHT);
      
        x = 0;
        y = 0;
        test = 0;
      
        for (k=0;k<iterazioni;k++)
            {
            x_new = (x*x)-(y*y)+a;
            y_new = (2*x*y)+b;
            if (((x_new*x_new)+(y_new*y_new))>4)
                {
                test = k;
                p = (Uint8 *)screen->pixels + i * screen->pitch + j * screen->format->BytesPerPixel;
                *p=(k%255);
                break;
                }
            x = x_new;
            y = y_new;
            }
          
        }

    }
SDL_Flip(screen);

printf("Finito\n\r");

SDL_Quit();

return(0);

}


------------------------------------------------------
Per calcolare il tempo di esecuzione e' stato usato il comando time che misura il tempo tra l'inizio e la fine dell'esecuzione

time  mand_sdl_gcc
time mand_sdl_icc

i risultati sono decisamente schiaccianti. Intel vince in velocita'

Intel
Totale 0.974
User   0.624
Sys    0.024

Gcc
Totale 1.325
User   0.948
Sys    0.020


Link al progetto

giovedì 27 settembre 2012

Gestione file testo in C++

#include <fstream>
#include <iostream>
#include <string>

using namespace std;

int main()
{
   
ofstream file_testo;

file_testo.open("file_testo.txt",ios_base::out|ios_base::trunc);
file_testo << "Prova 1" << endl;
file_testo << "Prova 2" << endl;
file_testo.close();

ifstream file_testo_input;
string stringa;

file_testo_input.open("file_testo.txt",ios_base::in);
if (file_testo_input.is_open())
   {
   while (file_testo_input.good())
         {
         getline(file_testo_input,stringa);
         cout << stringa << endl;
         }
   }
file_testo_input.close();

return 0;
}

Esempio di Vettori STL C++

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

vector <int> vecInt(10,1); //crea un vettore di 10 posti mettendo 1 in ogni cella


int stampa()
{
int s;

cout << "------------------" << endl;
for (s=0; s < vecInt.size(); ++s) cout << vecInt[s] << endl;
cout << "------------------" << endl;


}
int main()
{
    int t = 0;
   
   
    cout << "Dimesione del vettore " << vecInt.size() << endl;
    stampa();
    // inserisce 10 nuovi valori in coda
    for (t=1;t<=10;t++) vecInt.push_back(t);
    // e mostra la nuova dimensione
    cout << "Dimesione del vettore " << vecInt.size() << endl;
    stampa();
   
    //Modifica del valore di una posizione del vettore
    cout << "Valore alla posizione 15: " << vecInt[15] << endl;
    vecInt[15] = 0;
    cout << "Valore alla posizione 15: " << vecInt[15] << endl;
   
    //rimuove l'ultimo elemento dal vettore
    cout << "Rimuove elemento" << endl;
    vecInt.pop_back();
    // e mostra la nuova dimensione
    cout << "Dimesione del vettore " << vecInt.size() << endl;
    stampa();
   
    cout << "Inserisce elemento all'inizio ed alla fine" << endl;
    vecInt.insert(vecInt.begin(),100);
    vecInt.insert(vecInt.end(),200);
    stampa();
   
    cout << "Mette in ordine gli elementi" << endl;
    sort(vecInt.begin(),vecInt.end());
    stampa();
 
   
    system("PAUSE");
    return EXIT_SUCCESS;
}

mercoledì 26 settembre 2012

Installare i Codec (Mp3) su Debian

Per inserire i codec proprietari in Debian si deve aggiungere al file sources.list

deb http://www.deb-multimedia.org wheezy main non-free
Attenzione : il sito e' sempre debian-multimedia.org che e' diventato deb-multimedia.org (Debian ha richiesto che fosse rimosso il nome perche' non e' coinvolta in un progetto con codec proprietari). Molte guide riportano il vecchio dominio

apt-get update 
apt-get install deb-multimedia-keyring
apt-get install libfaad2  libfaac0 alsamixergui twolame lame libmp3lame0 libdvdnav4 libdvdread4 libdvdcss2 w32codecs ffmpeg

Debugger integrato ESP32S3

Aggiornamento In realta' il Jtag USB funziona anche sui moduli cinesi Il problema risiede  nell'ID USB della porta Jtag. Nel modulo...