Siyah ve Beyaz Gökkuşağı


60

Yalnızca siyah ve beyaz piksellere ve beyaz bir piksel olan bir (x, y) konumuna sahip bir görüntü verildiğinde, beyaz pikselleri , yalnızca diğer beyaz pikselleri geçen bir yoldaki (x, y) uzaklıklarından en az Manhattan uzaklığına göre renklendirin .

Renk renkli piksel en uzak 0 ° (saf kırmızı) bir renk tonuna ve pikseller olacaktır (x, y), yani (x, y) piksel kendi mesafe ile orantılı olması gerekmektedir (x, y) diğer tonlar arasında kesintisiz ve doğrusal olarak karışan 360 ° (ayrıca kırmızı) bir ton olacaktır. Doygunluk ve değer hem de% 100 olmalıdır.

Beyaz bir piksel (x, y) 'ye diğer beyaz piksellerle bağlı değilse , o zaman beyaz kalmalıdır.

ayrıntılar

  • Giriş, görüntünün dosya adından veya ham görüntü verilerinden ve x ve y tam sayılarından oluşur.
  • Çıktı görüntüsü bir dosyaya kaydedilebilir veya herhangi bir ortak görüntü dosyası biçiminde stdout'a işlenmemiş olabilir veya basitçe görüntülenebilir.
  • En sol piksellerde x değeri 0'dır ve sağa doğru ilerler. En yüksek piksellerde y değeri 0'dır ve aşağı iner. (x, y) daima resim sınırları içinde olacaktır.
  • Hem tam programlara hem de işlevlere izin verilir.

Bayt cinsinden en kısa kod kazanır.

Örnekler

Yer tasarrufu için tüm bu resimler küçültüldü. Tam boyutta görmek için üzerlerine tıklayın.

Giriş resmi:

örnek 1 giriş

(x,y) = (165,155) ve (x,y) = (0,0)

örnek 1 A çıkışı örnek 1 çıktı B


Görüntü giriş ve çıkış (x,y) = (0,0):

örnek 5 giriş örnek 5 giriş A


Görüntü giriş ve çıkış (x,y) = (600,350):

örnek 2 girişi örnek 2 çıktısı


Görüntü giriş ve çıkış (x,y) = (0,0):

örnek 3 girişi örnek 3 çıktısı


Görüntü giriş ve çıkış (x,y) = (0,0):

örnek 4 girişi örnek 4 çıktı


İsteğe bağlı -30% bonus: Öklid mesafesini kullanın. Algoritmanız için bir öneri aşağıdaki gibidir (genel taslak):

  1. Bir başlangıç ​​pikseli var.
  2. O pikselden sel doldurun.
  3. Sel dolgusunda ulaşılan her piksel için,
  4. Düz bir çizgide, başlangıç ​​pikselinden bu piksele yarım birim adımlarla gidin.
  5. Her adımda, int()x ve y koordinatlarına uygulanır. Bu koordinatlardaki piksel siyahsa, durdurun. Aksi takdirde, devam edin. (Bu bir görüş hattı yöntemidir.)
  6. Beyaz bir pikseli ve / veya daha önce belirgin şekilde daha yüksek bir mesafeyle etiketlenmiş bir pikseli (yani, +10) sınırlayan ulaşılan piksel başlangıç ​​pikseline dönüşür.

Daha meta bir anlamda, bu algoritma başlangıç ​​/ zaten renkli piksellerden düz bir çizgide erişilebilen her piksele, ardından kenarlarda "inç" e yayılır. "Önemli ölçüde daha yüksek mesafe" bitinin algoritmayı hızlandırması amaçlanmıştır. Açıkçası, Öklid mesafesini nasıl uyguladığınız önemli değil , sadece buna çok benzemesi gerekiyor.

İlk algoritmayı, yukarıdaki algoritmayı kullanarak Öklid mesafesiyle benzer şekilde görebilirsiniz:

Giriş görüntü ve (x,y) = (165,155)

örnek 1 giriş görüntü tanımını buraya girin


Calvin's Hobbies ve trichoplax'a bu mücadeleyi yazmada yardımcı oldukları için çok teşekkürler! İyi eğlenceler!


7
Golf oynamayı planlamıyorum ama görüntünün üzerinde farenin üzerinde durabileceğiniz bir Javascript sürümü hazırladım ve renkler anında güncellenir. Burada test görüntüleri ben gibi daha küçük resimler çalışırken öneriyorum Dolayısıyla hızlıdır çalıştırmak için çok büyük bu veya bu .
Calvin'in Hobileri

Bu harika! Golf edilmiş bir sürüm için iyi bir temel olamayacak kadar verimli olduğundan şüpheleniyorum =)
kusur 20:15

2
Labirentler, bu şekilde renkli olduklarında çözülmesi çok daha kolaydır!
mbomb007

Son örnek gerçekten çok güzel. Giriş görüntüsü sadece gürültü mü?
dylnan

@dylnan: Bonustan hemen önceki örnekden bahsediyorsanız, bu aslında bir labirent. Tam boyutta görmek için üzerine tıklayabilirsiniz.
El'endia Starman,

Yanıtlar:


33

Matlab, 255 245 231 bayt

Bu, sonra resim adını bekler yve sonra x.

I=@input;i=imread(I('','s'));[r,c]=size(i);m=zeros(r,c);m(I(''),I(''))=1;M=m;d=m;K=[1,2,1];for k=1:r*c;d(m&~M)=k;M=m;m=~~conv2(m,K'*K>1,'s');m(~i)=0;end;z=max(d(:));v=[1,1,3];imshow(ind2rgb(d,hsv(z)).*repmat(m,v)+repmat(~d&i,v),[])

İlk önce tohum pikselinin 1 olarak ayarlandığı bir maske oluşturarak ve mesafe akümülatörlü (görüntünün her ikisi de) bir maske oluşturarak taşkın dolgusunu (veya '4-mahalle için dijkstra') kabaca uyguladım adımlar:

  • maskeyi 4 mahalle çekirdeği ile bükün (bu çok verimsiz kısımdır)
  • maskenin sıfır olmayan piksellerini 1 olarak ayarlama
  • Resmin tüm siyah piksellerini sıfıra ayarla
  • maskenin bu adımda değiştiği akümülatördeki tüm değerleri k
  • artırmak k
  • maskede daha fazla değişiklik olmadıkça tekrarlayın (bu durumu kontrol etmiyorum, ancak görüntüdeki piksel sayısını genellikle çok kötü bir üst sınır olan üst sınır olarak kullanın, ancak bu kodgolf =)

Bu da bizi her pikselin manhattan mesafeleri ile mesafe akümülatöründeki tohum pikseline bırakır. Daha sonra verilen renk aralığına giderek yeni bir görüntü yaratır ve "ilk" renk tonunu sıfır değerine ve "son" renk tonunu maksimum mesafeye eşler.

Örnekler

görüntü tanımını buraya girin

görüntü tanımını buraya girin

görüntü tanımını buraya girin

görüntü tanımını buraya girin

Bonus olarak, burada mesafenin nasıl hesaplandığına dair güzel bir resim. daha parlak = daha uzakta.

görüntü tanımını buraya girin


3
Bu, kızımın çizmesi için basmak istediğim türden şeyler.
rayryeng - Monica

@rayryeng Şablonlar El'endia Starman'ın eseridir, benim değil =)
kusur

Resimlere hala renk eklediniz: D. Son adımı sen yaptın.
rayryeng - Monica

4
Etkilendim. Ben zorlukla anlayamadım lol
zfrisch

Açıkçası, onu kullanmak istediğim manzaralar yaratıyor.
corsiKa

3

Blitz 2D / 3D , 3068 * 0.7 = 2147.6

Bu, Euclid algoritması için atfedilen referans uygulamasıdır.

image=LoadImage("HueEverywhere_example1.png")
Graphics ImageWidth(image),ImageHeight(image)
image=LoadImage("HueEverywhere_example1.png")
x=0
y=0
w=ImageWidth(image)
h=ImageHeight(image)
Type start
Field x,y
Field dis#
Field nex.start
End Type
Type cell
Field x,y
Field dis#
End Type
Type oldCell
Field x,y
Field dis#
End Type
initCell.start=New start
initCell\x=x
initCell\y=y
initCell\dis=1
Dim array#(w,h)
imgBuff=ImageBuffer(image)
LockBuffer(imgBuff)
s.start=First start
colr=col(0,0,0)
colg=col(0,0,1)
colb=col(0,0,2)
newcol=colr*256*256+colg*256+colb
WritePixelFast(s\x,s\y,newcol,imgBuff)
While s<>Null
c.cell=New cell
c\x=s\x
c\y=s\y
c\dis=s\dis
While c<>Null
For dy=-1To 1
For dx=-1To 1
If dx*dy=0And dx+dy<>0
nx=c\x+dx
ny=c\y+dy
ndis#=s\dis+Sqr#((nx-s\x)*(nx-s\x)+(ny-s\y)*(ny-s\y))
If nx >= 0And nx<w And ny >= 0And ny<h
If KeyHit(1)End
pixcol=ReadPixelFast(nx,ny,imgBuff)
If pixcol<>-16777216
If array(nx,ny)=0Or ndis<array(nx,ny)
check=1
steps=Ceil(dis)*2
For k=0 To steps
r#=k*1./steps
offx#=Int(s\x+(c\x-s\x)*r)
offy#=Int(s\y+(c\y-s\y)*r)
pixcol2=ReadPixelFast(offx,offy,imgBuff)
If pixcol2=-16777216
check=0
Exit
EndIf
Next
If check
array(nx,ny)=ndis
newCell.cell=New cell
newCell\x=nx
newCell\y=ny
newCell\dis=ndis
EndIf
EndIf
EndIf
EndIf
EndIf
Next
Next
o.oldCell=New oldCell
o\x=c\x
o\y=c\y
o\dis=c\dis
Delete c
c=First cell
Wend
For o.oldCell=Each oldCell
bordersWhite=0
For dy=-1To 1
For dx=-1To 1
If dx<>0Or dy<>0
nx=o\x+dx
ny=o\y+dy
If nx>=0And nx<w And ny>=0And ny<h
pixcol=ReadPixelFast(nx,ny,imgBuff)
If (pixcol=-1And array(nx,ny)=0)Or array(nx,ny)>o\dis+9
bordersWhite=1
Exit
EndIf
EndIf
EndIf
Next
If bordersWhite Exit
Next
If bordersWhite
ns.start=New start
ns\x=o\x
ns\y=o\y
ns\dis=o\dis
s2.start=First start
While s2\nex<>Null
If ns\dis<s2\nex\dis
Exit
EndIf
s2=s2\nex
Wend
ns\nex=s2\nex
s2\nex=ns
EndIf
Delete o
Next
EndIf
s2=s
s=s\nex
Delete s2
Wend
maxDis=0
For j=0To h
For i=0To w
If array(i,j)>maxDis maxDis=array(i,j)
Next
Next
For j=0To h
For i=0To w
dis2#=array(i,j)*360./maxDis
If array(i,j) <> 0
colr=col(dis2,0,0)
colg=col(dis2,0,1)
colb=col(dis2,0,2)
newcol=colr*256*256+colg*256+colb
WritePixelFast(i,j,newcol,imgBuff)
EndIf
Next
Next
UnlockBuffer(imgBuff)
DrawImage image,0,0
Function col(ang1#,ang2#,kind)
While ang1>360
ang1=ang1-360
Wend
While ang1<0 
ang1=ang1+360
Wend
While ang2>180
ang2=ang2-360
Wend
While ang2<-180
ang2=ang2+360
Wend
a3#=ang2/180.
If ang1>300
diff#=(ang1-300)/60.
r=255
g=0
b=255*(1-diff)
ElseIf ang1>240
diff#=(ang1-240)/60.
r=255*diff
g=0
b=255
ElseIf ang1>180
diff#=(ang1-180)/60.
r=0
g=255*(1-diff)
b=255
ElseIf ang1>120
diff#=(ang1-120)/60.
r=0
g=255
b=255*diff
ElseIf ang1>60
diff#=(ang1-60)/60.
r=255*(1-diff)
g=255
b=0
Else
diff#=(ang1-00)/60.
r=255
g=255*diff
b=0
EndIf
If a3>0
r2=r+a3*(255-r)
g2=g+a3*(255-g)
b2=b+a3*(255-b)
Else
r2=r+a3*r
g2=g+a3*g
b2=b+a3*b
EndIf
If r2>255
r2=255
ElseIf r2<0
r2=0
EndIf
If g2>255
g2=255
ElseIf g2<0
g2=0
EndIf
If b2>255
b2=255
ElseIf b2<0
b2=0
EndIf
If kind=0
Return r2
ElseIf kind=1
Return g2
ElseIf kind=2
Return b2
Else
Return 0
EndIf
End Function

Aslında, bunun orjinali ile karşılaştırılamaz olmasından nefret ediyorum. (Bu arada, 5305 bayttır.) Aslında, her şey için tek karakterli değişken adları kullanarak epeyce bayt saptabiliyordum, ama bu zaten yeterince saçma. Ve yakında hiçbir zaman kazanmıyor. : P


2

C ++ / SFML: 1271 1235 1226 bayt

User202729 sayesinde -36 bayt Zacharý sayesinde -9 bayt

#include<SFML\Graphics.hpp>
#include<iostream>
#define V std::vector
#define P e.push_back
#define G(d,a,b,c) case d:return C(a,b,c);
#define FI(r,s)(std::find_if(e.begin(),e.end(),[&a](const T&b){return b==T{a.x+(r),a.y+(s),0};})!=e.end())
using namespace sf;using C=Color;struct T{int x,y,c;bool operator==(const T&a)const{return x==a.x&&y==a.y;}};int max(V<V<int>>&v){int m=INT_MIN;for(auto&a:v)for(auto&b:a)m=b>m?b:m;return m;}C hsv2rgb(int t){int ti=t/60%6;float f=t/60.f-ti,m=(1.f-f)*255,n=f*255;switch(ti){G(0,255,n,0)G(1,m,255,0)G(2,0,255,n)G(3,0,m,255)G(4,n,0,255)G(5,255,0,m)default:throw std::exception();}}void r(Image&a,int x,int y){auto d=a.getSize();V<V<int>>m(d.x,V<int>(d.y));int i=0,j,c=0,t;for(;i<d.y;++i)for(j=0;j<d.x;++j)m[j][i]=a.getPixel(j,i)==C::Black?-1:0;V<T>e{{x,y,1}};while(e.size()){V<T>t=std::move(e);for(auto&a:t){m[a.x][a.y]=a.c;if(a.x>0&&m[a.x-1][a.y]==0&&!FI(-1,0))P({a.x-1,a.y,a.c+1});if(a.y>0&&m[a.x][a.y-1]==0&&!FI(0,-1))P({a.x,a.y-1,a.c+1});if(a.x<m.size()-1&&m[a.x+1][a.y]==0&&!FI(1,0))P({a.x+1,a.y,a.c+1});if(a.y<m[0].size()-1&&m[a.x][a.y+1]==0&&!FI(0,1))P({a.x,a.y+1,a.c+1});}}c=max(m)-1;for(i=0,j;i<d.y;++i)for(j=0;j<d.x;++j)if(m[j][i]>0)a.setPixel(j,i,hsv2rgb(360.f*(m[j][i]-1)/c));}

sf::ImageParametresi de çıkış (değiştirilecek). Böyle kullanabilirsiniz:

sf::Image img;
if (!img.loadFromFile(image_filename))
    return -1;

r(img, 0, 0);

if (!img.saveToFile(a_new_image_filename))
    return -2;

İlk parametre görüntü girişidir (ve çıktı), ikinci ve üçüncü parametreler başlamak için gereken xve yparametresidir.


Geçiş durumu o kadar boş görünüyor ki, muhtemelen bir makro tanımı faydalı olacak ... Ayrıca `` setPixel(j, i,hsv2ve FI(xm,ym) (std::find_ifgerçekten gerekli mi?
user202729

G(d,a,b,c)Ve arasındaki boşluğu kaldırabilirsiniz case d:. Ayrıca arasındaki boşluk case d:ve return C(a,b,c)aynı zamanda gereksiz olduğunu. (b>m?b:m)parantez gerektirmez ve işlem sırasına göre (t/60)%6=> t/60%6.
Zacharı

Muhtemelen ayrıca, ismini değiştirmeli xmve ymdeğişken isimleri kısaltmalısınız
Zacharý

Bunun arasındaki boşluğu kaldırmak mümkün olduğunu düşünüyorum G(d,a,b,c)ve case, FI, ti, ve hsv2rgbher kısa bir adla değiştirilebilir.
Zacharı

1

C ++, 979 969 898 859 848 bayt

#include<cstdio>
#include<cstdlib>
#define K 400
#define L 400
#define M (i*)malloc(sizeof(i))
#define a(C,X,Y)if(C&&b[Y][X].c){t->n=M;t=t->n;b[Y][X].d=d+1;t->n=0;t->c=X;t->d=Y;}
#define A(n,d)case n:d;break;
#define F fgetc(f)
#define W(A,B) for(A=0;A<B;A++){
struct i{int c;int d;int v;i*n;}b[L][K]={0},*h,*t;float m=0;int main(){FILE*f=fopen("d","r+b");int x,y,d=0;W(y,L)W(x,K)b[y][x].c=F<<16|F<<8|F;}}rewind(f);x=165,y=155;h=M;h->c=x;h->d=y;b[y][x].d=d;t=h;while(h){i*p=b[h->d]+h->c;if(p->v)h=h->n;else{p->v=1;x=h->c;y=h->d;d=p->d;m=d>m?d:m;a(x>0,x-1,y)a(x<K-1,x+1,y)a(y>0,x,y-1)a(y<L-1,x,y+1)}}W(y,L)W(x,K)i p=b[y][x];unsigned char n=-1,h=p.d/(m/n),R=h%43*6,Q=n*(n-(n*R>>8))>>8,t=n*(n-(n*(n-R)>>8))>>8,r,g,b;switch(h/43){A(0,n,t,0)A(1,Q,n,0)A(2,0,n,t)A(3,0,Q,n)A(4,t,0,n)A(5,n,0,Q)}d=h?r|g<<8|b<<16:p.c?-1:0;fwrite(&d,1,3,f);}}}
  • Giriş: RGB veri dosyası (dosyada: d)
  • Çıktı: RGBA RGB veri dosyası (dosyada çıktı: d)
  • Örnek: dönüştürmek -depth 8 -size "400x400" test.png d.rgb && mv -f d.rgb d && g ++ -o test main.c && ./test
  • NOT: görüntü boyutu ve başlangıç, kaynak düzeyinde kontrol edilir, eğer bu 50 bayt veya başka bir şey ekliyorsa - dürüst olmak gerekirse değiştirmedim.

Tam olarak doğrudan "ungolf" değil, ama bu ilk önce alay ettiğim bir C prototipiydi:

#include "stdio.h"
#include "stdlib.h"

struct i{
    unsigned int c;
    int d;
    int v;
}b[400][400]={0};

typedef struct q{
    int x;
    int y;
    struct q *n;
}q;
q *qu;
q *t;
float m=0;
int get_dist(int x, int y)
{
    int d = 0;

}

void flood(int x,int y,int d){
    qu=malloc(sizeof(q));
    qu->x=x;qu->y=y;b[y][x].d=d;
    t=qu;
    while(qu){
        struct i *p = &b[qu->y][qu->x];
        if(p->v){qu=qu->n; continue;}
        p->v=1;x=qu->x;y=qu->y;d=p->d;
        #define a(C,X,Y) if(C&&b[Y][X].c){t->n=malloc(sizeof(q));t=t->n;b[Y][X].d=d+1;t->n=0;t->x=X;t->y=Y;}
        a(x>0,x-1,y);
        a(x<399,x+1,y);
        a(y>0,x,y-1);
        a(y<399,x,y+1);
        m=p->d>m?p->d:m;
    }
}

unsigned int C(int h)
{
    int r=0,g=0,b=0;
    int s=255,v=255;
    unsigned char R, qq, t;

    R = h%43*6; 

    qq = (v * (255 - ((s * R) >> 8))) >> 8;
    t = (v * (255 - ((s * (255 - R)) >> 8))) >> 8;

    switch (h / 43){
        case 0: r = v; g = t; break;
        case 1: r = qq; g = v; break;
        case 2: g = v; b = t; break;
        case 3: g = qq; b = v; break;
        case 4: r = t; b = v; break;
        case 5: r = v; b = qq; break;
    }

    return r|(g<<8)|(b<<16)|255<<24;
}

#define F fgetc(f)
int main()
{
    FILE *f=fopen("d", "r+b");
    for(int y=0; y<400; y++){
        for(int x=0; x<400; x++){
            b[y][x].c = (F<<24)|(F<<16)|(F<<8);
        }
    }
    rewind(f);
    flood(165,155,1);
    m/=255.f;
    for(int y=0; y<400; y++){
        for(int x=0; x<400; x++){
            struct i p = b[y][x];
            unsigned int h = C(p.d/m);
            int o = p.c?-1:255<<24;
            if(p.d)fwrite(&h,4,1,f);
            else fwrite(&o,4,1,f);
        }
    }
}

Birçok konsept benzer kalır, ancak kesinlikle çok sayıda küçük değişiklik var. Bunu derlemek için C olarak C11 kullanmanız gerekir (C99 muhtemelen işe yarayacaktır, ancak ben sadece kesinlikle C11'de test edilmiştir).
Bu zorluğu çok beğendim, bana yeni bir şeyler deneme fikrini verdiğiniz için teşekkürler :).
Düzenleme: Golf biraz daha iyi.
Düzen2: İki yapı birleştirildi, böylece piksel yapı ve kuyruğum aynı, biraz daha fazla makro suistimal ve 255'in yeniden kullanımı, bir imzasız karakter dizisi tanımlanırken -1 olarak tanımlanabilmesi ve son olarak bir işlev çağrısını kaldırması için yeniden akıtılmış kullanımları.
Edit3: Birkaç değişken daha kullandım, operatör önceliği tweaks ve alfa kanalını kaydederek RGB'ye dönüştürülmüş çıktı
Edit4: Sanırım şu an bitmiştim, bazı işaretçi aritmetik değişiklikleri ve hafif kontrol akışı tweaks.


0

Python 3 ve matplotlib, 251 bayt

from pylab import*
def f(i,p):
    h,w,_=i.shape;o=full((h,w),inf);q=[p+(0,)]
    while q:
        x,y,d=q.pop(0)
        if w>x>=0and h>y>=0and i[y,x,0]:o[y,x]=d;i[y,x]=0;d+=1;q+=[(x-1,y,d),(x+1,y,d),(x,y-1,d),(x,y+1,d)]
    imshow(i);imshow(o,'hsv')

Giriş, matplotlib imshow()işlevinin döndürdüğü MxNx3 numpy dizisidir . Giriş, fonksiyon tarafından değiştirildiğinden önceden kopyalanmalıdır. Matplotlib "etkileşimli" moddaysa görüntüyü otomatik olarak görüntüler; Aksi takdirde show()başka bir 7 bayt için bir çağrı eklenmelidir.

Çıktı önce orijinal görüntüyü göstererek, sonra da üstündeki gökkuşağı görüntüsünü göstererek oluşturulur. Matplotlib, inf ve nan'i şeffaf bir şekilde ele alır, böylece siyah ve beyaz görüntü gösterir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.