mightymandel v16

GPU-based Mandelbrot set explorer

parse_gif.c
Go to the documentation of this file.
1 // mightymandel -- GPU-based Mandelbrot Set explorer
2 // Copyright (C) 2012,2013,2014,2015 Claude Heiland-Allen
3 // License GPL3+ http://www.gnu.org/licenses/gpl.html
4 
5 #include <math.h>
6 #include <stdio.h>
7 #include <string.h>
8 
9 #include "parse.h"
10 #include "parse_gif.h"
11 #include "logging.h"
12 
13 bool parse_gif(const char *source, int length, mpfr_t cx, mpfr_t cy, mpfr_t cz) {
14  // magic header strings
15  const char *gif = "GIF";
16  const int gif_length = 3;
17  const char *fractint001 = "fractint001";
18  const int fractint001_length = 11;
19  const char *info_id = "Fractal";
20  const int info_id_length = 8;
21  // magic header offsets
22  const int length_b = 1;
23  const int version_lsb = 79;
24  const int version_msb = 80;
25  const int type_lsb = 11;
26  const int type_msb = 12;
27  const int coord_doubles = 13;
28  const int max_offset = 81;
29  // magic constants
30  const int type_mandelbrot1 = 0;
31  const int type_mandelbrot2 = 4;
32  // check GIF header
33  if (0 != memcmp(source, gif, gif_length)) {
34  return false;
35  }
36  debug_message("fractint gif GIF\n");
37  // find extension block
38  for (int offset = 0; offset < length - fractint001_length; ++offset) {
39  if (0 == memcmp(source + offset, fractint001, fractint001_length)) {
40  // found fractint001 extension block
41  debug_message("fractint gif fractint001\n");
42  // parse info blocks { 1 byte length x, x bytes data }
43  // terminated by 0 length
44  const unsigned char *info = (const unsigned char *) source + offset + fractint001_length;
45  // check for overrun, we read up to max_offset bytes inside the loop
46  int info_length;
47  while (info < (const unsigned char *) source + length - max_offset && (info_length = info[0])) {
48  // parse info block
49  if (0 == memcmp((const char *) info + length_b, info_id, info_id_length)) {
50  // got Fractal block
51  debug_message("fractint gif Fractal\n");
52  // check version
53  int version = info[version_lsb] | (info[version_msb] << 8);
54  debug_message("fractint gif version %d\n", version);
55  // check Mandelbrot
56  int type = info[type_lsb] | (info[type_msb] << 8);
57  debug_message("fractint gif type %d\n", type);
58  if (type == type_mandelbrot1 || type == type_mandelbrot2) {
59  // copy coords
60  double coords[6]; memcpy(coords, info + coord_doubles, sizeof(coords));
61  double xmin = coords[0];
62  double xmax = coords[1];
63  double ymin = coords[2];
64  double ymax = coords[3];
65  double creal = coords[4];
66  double cimag = coords[5];
67  debug_message("fractint gif coords %e %e %e %e %e %e\n", xmin, xmax, ymin, ymax, creal, cimag);
68  // cook them
69  double x = (xmin + xmax) / 2.0;
70  double y = (ymin + ymax) / 2.0;
71  double z = fabs(ymax - ymin) / 2.0;
72  debug_message("fractint gif xyz %.20e %.20e %e\n", x, y, z);
73  if (z > 0.0) {
74  // output
75  mpfr_set_prec(cx, 53);
76  mpfr_set_prec(cy, 53);
77  mpfr_set_d(cx, x, MPFR_RNDN);
78  mpfr_set_d(cy, y, MPFR_RNDN);
79  mpfr_set_d(cz, z, MPFR_RNDN);
80  return true;
81  }
82  }
83  }
84  // advance to next block
85  info += 1 + info_length;
86  }
87  }
88  }
89  return false;
90 }