Conjunto de Mandelbrot (Fractal)

Publicado por Perfil removido (última atualização em 17/11/2010)

[ Hits: 8.442 ]

Download fractal.cc




Como uma pequena homenagem ao matemático Benoît Mandelbrot , falecido no dia 14 do mês passado, um programa que gera um arquivo bitmap do conjunto de Mandelbrot. Para poupar espaço aqui, você pode encontrar maiores informações aqui:

http://en.wikipedia.org/wiki/Mandelbrot_set

Espero que o programa seja útil.

  



Esconder código-fonte

//===============================================================================
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
//    Produces a bitmap picture of the Mandelbrot set. 
//
//    You can compile this code with the command
//    g++ fractal.cc -o fractal.x 
//
//    You can play with the command line parameters; a nice set is
//
//    ./fractal.x 1024 768 -0.7 0 300 fractal.bmp
//
//    I think this program is quite portable, and you can modify to build 
//    your own fractal. If you find something cool (or have any complain, question
//    or suggestion about the code), please email me =)
//
//    Author: Victor Santos
//    Email: victor_santos@fisica.ufc.br
//===============================================================================

// Probably you want to keep all this code in a separate file.
// bitmap.h
// BMP (BitMap Files) are image files that have a relatively simple format:
//
//  The first 54 bytes contain file header information:
//     *  The first two bytes (0 and 1) must be BM
//     *  Next 4 bytes stores the file size
//     *  Bytes 18 through 21 contain the image width in pixels
//     *  Bytes 22 through 25 contain the image height in pixels
//     *  Byte 28 must be 24 for 24 bit BMP files
//  There are a few other required bytes.
//
//  Image data is stored in the following format:
//     *  Scan lines are stored bottom to top
//     *  Each scan line is padded to the next four byte boundary.
//     *  RGB vales are stored in reverse order: Blue, Green, and Red.

//#ifndef BITMAP_H
//#define BITMAP_H

#include <iostream>
#include <cstdlib>
#include <fstream>

using std::cout;
using std::cerr;
using std::endl;
using std::ofstream;

// Converte um a variável inteira num em um binário de 4 bytes. O byte mais
// significativo é armazenado primeiro no array s
void int_to_4byte(char *s, int num)
{
    // Extrai o byte mais significativo
    s[3] = (unsigned char)(num/0x1000000);
    num %= 0x1000000;
    
    s[2] = (unsigned char)(num/0x10000);
    num %= 0x10000;
    
    s[1] = (unsigned char)(num/0x100);
    num %= 0x100;
    
    // Byte menos significativo
    s[0] = (unsigned char)(num);
}

// Classe bitmap ==============================================================80
class bitmap
{
protected:
    int            width, height;  // Largura e altura do bitmap (em pixels)
    unsigned char *pixels;         // Armazena os dados referentes aos pixels
    char           header[54];     // Armazena o cabeçalho do arquivo bitmap
public:
    // Construtores
    bitmap();                           // Padrão
    bitmap(const int&, const int&);     // Sobrecarregado
    bitmap(const bitmap&);              // Cópia
    // Destrutor
    virtual ~bitmap();

    // Cria o cabeçalho para o arquivo bitmap
    void fill_header(void);

    // Ajusta a cor de um pixel
    void set_rgbcolor(const unsigned int&, const unsigned int&, 
            const unsigned int&, const unsigned int&,  const unsigned int&);

    // Salva o bitmap em um arquivo no disco
    void save_on_disk(const char *);
    
};
//=============================================================================80

bitmap::bitmap() : width(0), 
         height(0), 
         pixels(NULL) {}

bitmap::bitmap(const int& _width, 
          const int& _height) : width(_width),
                 height(_height),
                 pixels(new unsigned char[3*_width*_height])
{
    if(pixels == NULL)
    {
   cerr << "Error: could not allocate memory for the bitmap." << endl;
   exit(1);
    }
}
bitmap::bitmap(const bitmap& copy) : width(copy.width), 
                 height(copy.height),
                 pixels(copy.pixels) {}

bitmap::~bitmap() 
{
    delete [] pixels;
    width  = 0;
    height = 0;
    pixels = 0;
}

void bitmap::fill_header(void)
{
    int n_extra = 4 - ((3*width) % 4);
    if(n_extra == 4) n_extra = 0;
    int padding = ((width * 3) + n_extra) * height;

    int fileSize   = 54 + padding;
    
    for(int i = 2; i < 54; i++)    // set all bytes to null
   header[i] = '{FONTE}';

    header[0]  = 'B';
    header[1]  = 'M';
    header[10] = 54;
    header[14] = 40;
    header[26] = 1;
    
    int_to_4byte(header + 2,  fileSize);
    int_to_4byte(header + 18, width);
    int_to_4byte(header + 22, height);
    header[28] = 24;
}

void bitmap::set_rgbcolor(const unsigned int& x_coord, const unsigned int& y_coord, 
           const unsigned int& red, const unsigned int& green,  const unsigned int& blue)
{
    // Verifica se o pixel em questão está dentro da imagem
    if((x_coord < 0) || (x_coord >= width) || (y_coord < 0) || (y_coord >= height))
    {
   throw("Invalid pixel");
    }

    unsigned int r = red, g = green, b = blue;
    
    if(r > 255)
    { 
   r = 255;
    }
    else if (r < 0)
    {
   r = 0;
    }

    if(g > 255)
    { 
   g = 255;
    }
    else if (g < 0)
    {
   g = 0;
    }

    if(b > 255)
    { 
   b = 255;
    }
    else if (b < 0)
    {
   b = 0;
    }

   
   pixels[(3*x_coord) + 0 + (3*y_coord*width)] = r;
   pixels[(3*x_coord) + 1 + (3*y_coord*width)] = g;
   pixels[(3*x_coord) + 2 + (3*y_coord*width)] = b;
}

void bitmap::save_on_disk(const char *filename)
{
    unsigned int n_extra = 4 - ((3*width) % 4);
    if(n_extra == 4) n_extra = 0;

    ofstream out_stream(filename);
    if(!out_stream.is_open())
    {
   throw("Could not open bitmap file for writting");
    }

    fill_header();
    out_stream.write(header, 54);

    for(int y = (height - 1); y >= 0; y--)  // BMPs are written bottom to top.
    {
   for(int x = 0; x <= (width - 1); x++)
   {
       // Also, it's written in (b,g,r) format...
     out_stream << char(pixels[(3*x) + 2 + (3 * y * width)])
           << char(pixels[(3*x) + 1 + (3 * y * width)])
           << char(pixels[(3*x) + 0 + (3 * y * width)]);
   }
   if(n_extra)      // See above - BMP lines must be of lengths divisible by 4.
   {
       for(int n = 1; n <= n_extra; n++)
       {
         out_stream << char(0);
       }
   }
    }
    out_stream.close();
}

//#endif // BITMAP_H

// Maximum number of iterations to decide whether a points belongs (or not)
// to the set. Large numbers are better, but turns the program execution slow.
const unsigned MAX_ITERATIONS = 512;

int main(int argc, char **argv)
{
    const unsigned width    = unsigned(atoi(argv[1]));
    const unsigned height   = unsigned(atoi(argv[2]));
    const unsigned centre_x = unsigned(atoi(argv[3]));
    const unsigned centre_y = unsigned(atoi(argv[4]));
    const unsigned zoom     = unsigned(atoi(argv[5]));
    const char*    outfile  = argv[6];

    bitmap out(width, height);

    const double startx = centre_x - double(width)/double(2*zoom);
    const double endx   = centre_x + double(width)/double(2*zoom);

    const double starty = centre_y - double(height)/double(2*zoom);
    const double endy   = centre_y + double(height)/double(2*zoom);

    const double dx = endx - startx;
    const double dy = endy - starty;
    const double dx_over_width = dx / width;

    for(double x = startx, xtoplot = 0; xtoplot < width; (x += dx_over_width) && (xtoplot += 1.0))
    {
   for(double y = starty, ytoplot = 0; ytoplot < height; (y += dx_over_width) && (ytoplot += 1.0))
   {
       double r = x; double s = y;
       for(int n = 0; n <= MAX_ITERATIONS; n++)
       {
      const double nextr = (r*r - s*s) + x;
      const double nexts = (2*r*s) + y;
      r = nextr;
      s = nexts;
         
      if(n == MAX_ITERATIONS)
      {
          out.set_rgbcolor(xtoplot, ytoplot, 0, 0, 0);
      } 
      else if((r*r + s*s) > 4) 
      {
          out.set_rgbcolor(xtoplot, ytoplot, unsigned(10*n), unsigned(20*n), unsigned(0));
          break;
      }
       }
   }
    }
    out.save_on_disk(outfile);
    return 0;
}

Scripts recomendados

Lista encadeada em C

Vírus didático para Linux em C

Script em C++ de uma Lista Estática.

Campo Elétrico

Produto de duas matrizes alocadas dinamicamente


  

Comentários
[1] Comentário enviado por gigatesla boy em 09/11/2011 - 18:15h

Mais um grande matematico que se foi.

Queria ter conhecido ele pessoalmente :/


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts