static void draw_mandelbrot(AVFilterContext *ctx, uint32_t *color, int linesize, int64_t pts) { MBContext *mb = ctx->priv; int x,y,i, in_cidx=0, next_cidx=0, tmp_cidx; double scale= mb->start_scale*pow(mb->end_scale/mb->start_scale, pts/mb->end_pts); int use_zyklus=0; fill_from_cache(ctx, NULL, &in_cidx, NULL, mb->start_y+scale*(-mb->h/2-0.5), scale); for(y=0; y<mb->h; y++){ const double ci=mb->start_y+scale*(y-mb->h/2); memset(color+linesize*y, 0, sizeof(*color)*mb->w); fill_from_cache(ctx, color+linesize*y, &in_cidx, &next_cidx, ci, scale); tmp_cidx= in_cidx; fill_from_cache(ctx, color+linesize*y, &tmp_cidx, NULL, ci + scale/2, scale); for(x=0; x<mb->w; x++){ const double cr=mb->start_x+scale*(x-mb->w/2); double zr=cr; double zi=ci; uint32_t c=0; double dv= mb->dither / (double)(1LL<<32); mb->dither= mb->dither*1664525+1013904223; if(color[x + y*linesize] & 0xFF000000) continue; use_zyklus= (x==0 || mb->inner!=BLACK ||color[x-1 + y*linesize] == 0xFF000000); #define Z_Z2_C(outr,outi,inr,ini)\ outr= inr*inr - ini*ini + cr;\ outi= 2*inr*ini + ci; #define Z_Z2_C_ZYKLUS(outr,outi,inr,ini, Z)\ Z_Z2_C(outr,outi,inr,ini)\ if(use_zyklus){\ if(Z && mb->zyklus[i>>1][0]==outr && mb->zyklus[i>>1][1]==outi)\ break;\ mb->zyklus[i][0]= outr;\ mb->zyklus[i][1]= outi;\ } for(i=0; i<mb->maxiter-8; i++){ double t; Z_Z2_C_ZYKLUS(t, zi, zr, zi, 0) i++; Z_Z2_C_ZYKLUS(zr, zi, t, zi, 1) i++; Z_Z2_C_ZYKLUS(t, zi, zr, zi, 0) i++; Z_Z2_C_ZYKLUS(zr, zi, t, zi, 1) i++; Z_Z2_C_ZYKLUS(t, zi, zr, zi, 0) i++; Z_Z2_C_ZYKLUS(zr, zi, t, zi, 1) i++; Z_Z2_C_ZYKLUS(t, zi, zr, zi, 0) i++; Z_Z2_C_ZYKLUS(zr, zi, t, zi, 1) if(zr*zr + zi*zi > mb->bailout){ i-= FFMIN(7, i); for(; i<mb->maxiter; i++){ zr= mb->zyklus[i][0]; zi= mb->zyklus[i][1]; if(zr*zr + zi*zi > mb->bailout){ switch(mb->outer){ case ITERATION_COUNT: zr = i; break; case NORMALIZED_ITERATION_COUNT: zr= i + log2(log(mb->bailout) / log(zr*zr + zi*zi)); break; } c= lrintf((sin(zr)+1)*127) + lrintf((sin(zr/1.234)+1)*127)*256*256 + lrintf((sin(zr/100)+1)*127)*256; break; } } break; } } if(!c){ if(mb->inner==PERIOD){ int j; for(j=i-1; j; j--) if(SQR(mb->zyklus[j][0]-zr) + SQR(mb->zyklus[j][1]-zi) < 0.0000000000000001) break; if(j){ c= i-j; c= ((c<<5)&0xE0) + ((c<<16)&0xE000) + ((c<<27)&0xE00000); } }else if(mb->inner==CONVTIME){ c= floor(i*255.0/mb->maxiter+dv)*0x010101; } else if(mb->inner==MINCOL){ int j; double closest=9999; int closest_index=0; for(j=i-1; j>=0; j--) if(SQR(mb->zyklus[j][0]) + SQR(mb->zyklus[j][1]) < closest){ closest= SQR(mb->zyklus[j][0]) + SQR(mb->zyklus[j][1]); closest_index= j; } closest = sqrt(closest); c= lrintf((mb->zyklus[closest_index][0]/closest+1)*127+dv) + lrintf((mb->zyklus[closest_index][1]/closest+1)*127+dv)*256; } } c |= 0xFF000000; color[x + y*linesize]= c; if(next_cidx < mb->cache_allocated){ mb->next_cache[next_cidx ].p[0]= cr; mb->next_cache[next_cidx ].p[1]= ci; mb->next_cache[next_cidx++].val = c; } } fill_from_cache(ctx, NULL, &in_cidx, &next_cidx, ci + scale/2, scale); } FFSWAP(void*, mb->next_cache, mb->point_cache); mb->cache_used = next_cidx; if(mb->cache_used == mb->cache_allocated) av_log(0, AV_LOG_INFO, "Mandelbrot cache is too small!\n"); }