Автостереограммы, 2004.
Заметка: если вы не встречались с автостереограммами, вы можете ввести “как смотреть стереограммы” в любом интернет поисковике, чтобы получить разносторонние советы. В кратце – цель – получить сфокусированное раздвоение изображения, чтобы каждый глаз видел другой фрагмент повторяющейся текстуры. Этого может быть проще достичь начиная близко к изображению, смотря сквозь него. Затем постепенно оталяя изображение, стараясь сохранить фокус немного дальше, чем изображение в реальности.
Будучи заинтересованным в 3D и, следовательно, восприятии глубины, моё внимание привлекли стереограммы. Особенно – автостереограммы (стереокартинки) основанные на повторении изображения, конечный продукт которых технологически прост и самодостаточен, а также наиболее синтетичен, в смысле передания чистого и содержательно не привязонного восприятия глубины. Стереограммы такого типа так же известны под торговой маркой “Магический Глаз” или “Magic Eye”.
После небольшого эксперементирования, механизм работы показался достаточно простым и я сделал рудиментарную программу для создания автостереограмм. Основной принцип сводится к горизонтальному смещению пикселов повторяющейся текстуры в пропорции к необходимой воспринимаемой глубине (карта глубины или “Z-буфер”) и ширинее повторения текстуры.
Исходный код главной функции:
[+] Показать
[-] Спрятать
/*
Note: I was self-teaching programming at the time, hence the dreadful form. The source is mostly provided as a future note to myself :) Might replace with a proper version if I get back to stereograms.
*/
double emi,dem,per,dr,dg,db,x1,x2;
unsigned __int8 cr,cg,cb,fr,fg,fb;
emi=(double)255/100*CSpinEdit2->Value;//Depth -% of 255, UI?
for(int z=(Image1->Width/CSpinEdit1->Value)-1; z>=0; z--){//CSpinEdit1: Pereod size
//iterate for every pattern repetition?
for(int x=Image1->Width; x>0; x--){
for(int y=0; y<Image1->Height; y++){
//get depth
dem=(double)GetRValue(Image2->Canvas->Pixels[x][y])/100*CSpinEdit2->Value;//depth magnitude
for(per=dem; per>=1; per--){}//I didn't know how to modulo???
x1=x-(z*CSpinEdit1->Value)-(dem-per);
x2=x-(z*CSpinEdit1->Value)-(dem-per+1);
if(x1<0)
{cr=GetRValue(Image1->Canvas->Pixels[x1+Image1->Width][y]);
cg=GetGValue(Image1->Canvas->Pixels[x1+Image1->Width][y]);
cb=GetBValue(Image1->Canvas->Pixels[x1+Image1->Width][y]);}
else
{cr=GetRValue(Image1->Canvas->Pixels[x1][y]);
cg=GetGValue(Image1->Canvas->Pixels[x1][y]);
cb=GetBValue(Image1->Canvas->Pixels[x1][y]);}
if(x2<0)
{fr=GetRValue(Image1->Canvas->Pixels[x2+Image1->Width][y]);
fg=GetGValue(Image1->Canvas->Pixels[x2+Image1->Width][y]);
fb=GetBValue(Image1->Canvas->Pixels[x2+Image1->Width][y]);}
else
{fr=GetRValue(Image1->Canvas->Pixels[x2][y]);
fg=GetGValue(Image1->Canvas->Pixels[x2][y]);
fb=GetBValue(Image1->Canvas->Pixels[x2][y]);}
if(per!=0)dr=(fr*per)+(cr*(1-per));
else dr=cr;
if(per!=0)dg=(fg*per)+(cg*(1-per));
else dg=cg;
if(per!=0)db=(fb*per)+(cb*(1-per));
else db=cb;
Image1->Canvas->Pixels[x-(z*CSpinEdit1->Value)][y]=RGB(dr,dg,db);
}}Image1->Refresh();}
ShowMessage("Complete!");
Карты глубины: