Bezproblemowa konwersja z kwadratu na sześciokąt

23

W przypadku wielu gier rozgrywanych na planszy sześciokąty to Clearly Superior Choice ™. Niestety, wiele darmowych stron z grafikami gier zawiera wyłącznie bezszwowe kafelki dla kwadratowych map. W poprzednim projekcie wykorzystałem niektóre z nich i ręcznie przekonwertowałem je na sześciokąty.

Jednak na starość stałem się leniwy. Zautomatyzowanie procesu powinno być łatwe za pomocą małego skryptu.

Jednak na starość stałem się leniwy. Więc zlecam to tobie i ukrywam jako wyzwanie dla golfa 1 .


Wkład

Dane wejściowe to kwadratowy obraz w dowolnym popularnym formacie obrazu z 24-bitowym kolorem RGB. Możesz również wziąć nazwę pliku jako dane wejściowe zamiast samych danych obrazu.

Możesz założyć, że obraz jest kwadratowy i że długość boku jest wielokrotnością czterech.

Wydajność

Dane wyjściowe to kafelek wejściowy, ale przekształcony w sześciokąt (sam obraz będzie kwadratowy z przezroczystymi obszarami). Możesz zapisać go do pliku lub wyświetlić na ekranie.

Ponownie, zrobi to każdy wspólny format obrazu. Jeśli używany format obsługuje przezroczystość, obszary tła muszą być przezroczyste. Jeśli nie, możesz użyć koloru # FF00FF (ten okropny fuksja) jako stand-in.

metoda

Więc jak to zrobimy? Metoda, której używam 2, powoduje ściśnięcie obrazu nieco pionowo, ale ogólnie rzecz biorąc wygląda całkiem dobrze w większości rzeczy. Zrobimy przykład z tym obrazem wejściowym:

wkład

  • Skala: przeskaluj obraz do proporcji 3: 2. Ponieważ nasze obrazy będą kwadratami, oznacza to, że po prostu skalujesz je do 75% szerokości i 50% wysokości. Nasze przykładowe dane wejściowe to 200 x 200, więc otrzymujemy obraz o wymiarach 150 x 100:

zgnieciony

  • Kafelek: umieść kopie skalowanego obrazu w siatce 2x2:

krata

  • Przytnij: weź siatkę o odpowiednim rozmiarze z dowolnego miejsca na tej siatce 2x2. Dla ułatwienia układania ten sześciokąt nie jest dokładnie regularny. Po przycięciu kwadratu o oryginalnym rozmiarze (tutaj 200 x 200), następnie przycinasz rogi. Linie przycinania powinny przebiegać od (z grubsza) środka każdej lewej / prawej strony do jednej czwartej od krawędzi u góry / u dołu:

klątwa

I to jest twój wynik!

Oto przykład tego, jak może wyglądać po ułożeniu kafelków (tutaj pomniejszony):

taflowy

To jest kod golfowy, więc wygrywa najkrótszy kod w bajtach. Obowiązują standardowe luki itp.


1 Możesz w to wierzyć lub nie.
2 Metoda pierwsza z tej pomocnej strony.

Geobity
źródło
13
To pytanie jest żebranie na odpowiedź Hexagony.
Sanchises
22
@sanchises Powodzenia.
Martin Ender
17
W tym miejscu ważna staje się druga część Hex Agony .
flawr
2
@ mbomb007 Prawdopodobnie, chociaż zielony # 00FF00, który czasami jest używany, nie jest wcale taki zły. Mimo to wydaje mi się, że częściej używają fuksji, ponieważ nikt przy zdrowych zmysłach nie chce tego dokładnego koloru w swoich duszkach, więc jest to dość uniwersalne: P
Geobits
3
# 3 - Cierpliwie czekam na wygenerowanie fajnych algorytmów ... potem delikatnie i czule „pożyczam” je na swoje potrzeby ;-)
scunliffe

Odpowiedzi:

10

Matlab, 223 215 209 184 163 bajtów

Przeskalowanie jest dość proste. Aby przyciąć rogi, nakładam układ współrzędnych na piksele i tworzę maskę za pomocą czterech nierówności liniowych, które określają pole sześciokąta.

​l=imread(input(''));
u=size(l,1);
L=imresize(l,u*[2 3]/4);
L=[L,L;L,L];L=L(1:u,1:u,:);
[x,y]=meshgrid(1:u);
r=u/2;x=x*2;
set(imshow(L),'Al',y<x+r&y+x>r&y+x<5*r&y>x-3*r)

wprowadź opis zdjęcia tutaj

PS: To zamieniło się w grę w codegolf nim z przesłaniem @ MartinBüttner: na przemian musisz skrócić swój kod (zapewniając tę ​​samą funkcjonalność) - ten, który może sprawić, że ostatnie „skrócenie” wygra =)

wada
źródło
Możesz zapisać 5 bajtów, zmieniając obliczenie skali zmiany rozmiaru na [k.*[2 3]/4].
zlewka
4
Czy obszary tła nie powinny być w kolorze fuksji, a nie czarne?
Blackhole
@Blackhole Dzięki za poinformowanie mnie, naprawiłem to teraz, nawet zaoszczędziłem całkiem sporo bajtów =)
flawr 17'15
12

Mathematica, 231 211 209 208 201 188 173 bajtów

ImageCrop[ImageCollage@{#,#,#,#},e,Left]~SetAlphaChannel~ColorNegate@Graphics[RegularPolygon@6,ImageSize->1.05e,AspectRatio->1]&@ImageResize[#,{3,2}(e=ImageDimensions@#)/4]&

To jest nienazwana funkcja, która pobiera obiekt obrazu i zwraca obiekt obrazu:

wprowadź opis zdjęcia tutaj

Nie sądzę, żeby było tu wiele do wyjaśnienia, ale kilka ważnych szczegółów:

  • Zwykle do kafelkowania obrazu 2x2 należy użyć ImageAssemble[{{#,#},{#,#}}], tj. ImageAssemblePodajesz matrycę 2x2 z kopiami obrazu. Istnieje jednak ImageCollagejakaś magiczna funkcja, która próbuje uporządkować kilka zdjęć tak dobrze, jak to możliwe (cokolwiek to oznacza ... możesz nawet nadać poszczególnym obrazom wagi i inne rzeczy). W każdym razie, dajesz mu cztery obrazy o równej wielkości i o równej (lub żadnej) wadze, ułoży je również w siatkę 2x2. To pozwala mi zapisać niektóre bajty do zagnieżdżenia macierzy, a także nazwę funkcji.
  • Sześciokąt jest renderowany jako pojedynczy wielokąt przez Graphics. Korzystam z wbudowanego RegularPolygon@6, ale wymuszam współczynnik proporcji, 1aby go rozciągnąć w razie potrzeby. Niestety, Graphicspotrzebuje kilku kosztownych opcji, aby uniknąć wypełnienia i tym podobnych, a także renderuje czarno na białym zamiast na odwrót. Wynik jest ustalany za pomocą, ColorNegatea następnie dołączany do oryginalnych kanałów obrazu za pomocą SetAlphaChannel.
  • Graphicsnakłada niewielką ilość wypełnienia wokół sześciokąta, ale chcemy, aby sześciokąt alfa pokrył pełny rozmiar wycięcia. Jednakże, SetAlphaChannelmożna łączyć zdjęcia o różnych rozmiarach, przez centrowanie je w górnej części siebie i kadrowanie w najmniejszym rozmiarze. Oznacza to, że zamiast ręcznego ustawiania PlotRangePadding->0, możemy po prostu trochę powiększyć obraz sześciokąta ImageSize->1.05e(i tak potrzebujemy opcji `ImageSize).
Martin Ender
źródło
5

HTML5 + JavaScript, 562 bajty

<html><form><input type=text></form><canvas><script>l=document.body.children;l[0].addEventListener("submit",e=>{e.preventDefault();c=l[1].getContext("2d");i=new Image();i.onload=q=>{l[1].width=l[1].height=d=i.width;c.scale(0.75,0.5);c.drawImage(i,0,0);c.drawImage(i,d,0);c.drawImage(i,0,d);c.drawImage(i,d,d);c.globalCompositeOperation="destination-in";c.scale(1/0.75,2);c.beginPath();c.moveTo(d/4,0);c.lineTo(d/4+d/2,0);c.lineTo(d, d/2);c.lineTo(d/4+d/2, d);c.lineTo(d/4, d);c.lineTo(0, d/2);c.closePath();c.fill();};i.src=e.target.children[0].value;})</script>

Pobiera dane wejściowe jako adres URL obrazu za pośrednictwem pola tekstowego (mam nadzieję, że adres URL liczy się jako nazwa pliku). Wysyła dane do kanwy.

Wersja działająca we wszystkich przeglądarkach (580 bajtów):

<html><form><input type=text></form><canvas><script>l=document.body.children;l[0].addEventListener("submit",function(e){e.preventDefault();c=l[1].getContext("2d");i=new Image();i.onload=function(){l[1].width=l[1].height=d=i.width;c.scale(0.75,0.5);c.drawImage(i,0,0);c.drawImage(i,d,0);c.drawImage(i,0,d);c.drawImage(i,d,d);c.globalCompositeOperation = "destination-in";c.scale(1/0.75,2);c.beginPath();c.moveTo(d/4, 0);c.lineTo(d/4+d/2,0);c.lineTo(d, d/2);c.lineTo(d/4+d/2, d);c.lineTo(d/4, d);c.lineTo(0, d/2);c.closePath();c.fill();};i.src=e.target.children[0].value;})</script>

Przetestuj go za pomocą obrazu „bloków” z wcześniejszego adresu URL: http://i.stack.imgur.com/gQAZh.png

adroitwhiz
źródło
Dobra robota! Można zaoszczędzić sporo bajtów dodając id=Ado <form>i id=Bdo <canvas>, a następnie zastąpienie l[0]ze Ai l[1]ze Bi usuwanie l=document.body.children;. (Działa w przeglądarce Firefox 41; nie jestem pewien, które inne przeglądarki to obsługują). Ponadto uważam, że obok prawego nawiasów klamrowych jest kilka niepotrzebnych średników i kilka dodatkowych spacji.
ETHprodukcje
Więcej porad: Wierzę, można dodać id=Cdo <input>, a następnie zastąpić e.target.children[0]z C. 0.75jest równa 3/4, 1/0.75jest równa 4/3, d/4+d/2jest równa d*3/4, a zera wiodące na pozostałych liczbach dziesiętnych nie są konieczne. Wierzę również można wymienić pierwszą c.drawImagez c[p="drawImage"], a następnie jeden z każdym kolejnym c[p]; możesz zrobić to samo z c.lineTo.
ETHprodukcje
4

Python 2 + PIL, 320

Odczytuje nazwę pliku obrazu ze standardowego wejścia.

from PIL import ImageDraw as D,Image as I
i=I.open(raw_input())
C=A,B=i.size
i,j=i.resize((int(.75*A),B/2)),I.new('RGBA',C)
W,H=i.size
for a,b in[(0,0),(0,H),(W,0),(W,H)]:j.paste(i,(a,b,a+W,b+H))
p,d=[(0,0),(A/4,0),(0,B/2),(A/4,B),(0,B)],lambda p:D.Draw(j).polygon(p,fill=(0,)*4)
d(p)
d([(A-x,B-y)for x,y in p])
j.show()
dieter
źródło
Prawda, przepraszam za to, nie PILmiałam okazji do wypróbowania i nie myślałam o tym wystarczająco. Nadal jednak trzymam się mojego nowego oświadczenia: P
FryAmTheEggman
2

PHP, 293 bajty

Dodałem kilka nowych linii dla czytelności:

function($t){$s=imagesx($t);imagesettile($i=imagecreatetruecolor($s,$s),$t=imagescale
($t,$a=$s*3/4,$b=$s/2));imagefill($i,0,0,IMG_COLOR_TILED);$z=imagefilledpolygon;$z($i,
[0,0,$s/4,0,0,$b,$s/4,$s,0,$s],5,$f=imagecolorallocate($i,255,0,255));$z($i,[$s,0,$a,
0,$s,$b,$a,$s,$s,$s],5,$f);return$i;}

Oto wersja bez golfa:

function squareToHexagon($squareImage)
{
    $size = imagesx($squareImage);
    $tileImage = imagescale($squareImage, $size * 3/4, $size/2);

    $hexagonImage = imagecreatetruecolor($size, $size);
    imagesettile($hexagonImage, $tileImage);
    imagefill($hexagonImage, 0, 0, IMG_COLOR_TILED);

    $fuchsia = imagecolorallocate($hexagonImage, 255, 0, 255);
    imagefilledpolygon(
        $hexagonImage,
        [
            0,       0,
            $size/4, 0,
            0,       $size/2,
            $size/4, $size,
            0,       $size,
        ],
        5,
        $fuchsia
    );
    imagefilledpolygon(
        $hexagonImage,
        [
            $size,       0,
            $size * 3/4, 0,
            $size,       $size/2,
            $size * 3/4, $size,
            $size,       $size,
        ],
        5,
        $fuchsia
    );

    return $hexagonImage;
}

header('Content-type: image/gif');
$squareImage = imagecreatefrompng('squareImage.png');
$hexagonImage = squareToHexagon($squareImage);
imagegif($hexagonImage);
Czarna dziura
źródło