Chuyển đổi liền mạch từ hình vuông sang hình lục giác


23

Đối với nhiều trò chơi được chơi trên lưới, hình lục giác là Clearly Superior Choice ™. Thật không may, nhiều trang web nghệ thuật trò chơi miễn phí chỉ có bộ gạch liền mạch cho bản đồ vuông. Trong một dự án trước đây, tôi đã sử dụng một số trong số này và tự chuyển đổi chúng thành hình lục giác.

Tuy nhiên , tôi đã trở nên lười biếng khi về già. Nó sẽ dễ dàng để tự động hóa quá trình với một kịch bản nhỏ.

Tuy nhiên , tôi đã trở nên lười biếng khi về già. Vì vậy, tôi thuê ngoài nó cho bạn và ngụy trang nó như một thử thách golf mã 1 .


Đầu vào

Đầu vào là một hình ảnh vuông ở bất kỳ định dạng hình ảnh phổ biến nào có khả năng màu RGB 24 bit. Bạn cũng có thể lấy tên tệp làm đầu vào thay vì dữ liệu hình ảnh.

Bạn có thể giả sử hình ảnh là hình vuông và chiều dài cạnh là bội số của bốn.

Đầu ra

Đầu ra là ô đầu vào, nhưng được chuyển đổi thành hình lục giác (hình ảnh sẽ là hình vuông, với các vùng trong suốt). Bạn có thể lưu nó vào một tập tin hoặc hiển thị ra màn hình.

Một lần nữa, bất kỳ định dạng hình ảnh phổ biến sẽ làm. Nếu định dạng bạn đang sử dụng hỗ trợ độ trong suốt, các vùng nền phải trong suốt. Nếu không, bạn có thể sử dụng màu # FF00FF (màu fuchsia khủng khiếp đó) làm màu độc lập.

phương pháp

Vậy làm thế nào để chúng ta làm điều đó? Phương pháp tôi sử dụng 2 squash hình ảnh một chút theo chiều dọc, nhưng nhìn chung nó có vẻ khá tốt cho hầu hết mọi thứ. Chúng tôi sẽ làm một ví dụ với hình ảnh đầu vào này:

đầu vào

  • Tỷ lệ: Chia tỷ lệ hình ảnh theo tỷ lệ 3: 2. Vì hình ảnh của chúng tôi sẽ là hình vuông, điều này có nghĩa là bạn chỉ cần chia tỷ lệ chúng thành 75% chiều rộng và 50% chiều cao. Ví dụ đầu vào của chúng tôi là 200x200, vì vậy chúng tôi kết thúc với hình ảnh 150x100 này:

bẹp

  • Ngói: Đặt các bản sao của hình ảnh được chia tỷ lệ của bạn trong lưới 2x2:

lưới điện

  • Cắt: Lấy một hình lục giác có kích thước phù hợp từ bất kỳ đâu trong lưới 2x2 này. Bây giờ, để dễ dàng ốp lát, hình lục giác này không chính xác thường xuyên. Sau khi cắt một hình vuông có kích thước ban đầu (ở đây 200x200), sau đó bạn cắt ra các góc. Các đường cắt phải chạy từ (khoảng) tâm của mỗi bên trái / phải đến một phần tư từ cạnh trên cùng / dưới cùng:

lục giác

Và đó là đầu ra của bạn!

Đây là một ví dụ về những gì nó có thể trông như thế nào khi được lát gạch (thu nhỏ ở đây):

lát gạch

Đây là mã golf, vì vậy mã ngắn nhất trong byte thắng. Lỗ hổng tiêu chuẩn áp dụng, vv và như vậy.


1 Hãy tin hay không.
2 Phương pháp một từ trang web hữu ích này.


13
Câu hỏi này đang cầu xin một câu trả lời Hexagony.
Chiếm

22
@sanchises Chúc may mắn.
Martin Ender

17
Đó là nơi phần thứ hai của Hex Agony trở nên quan trọng.
flawr

2
@ mbomb007 Có lẽ, mặc dù màu xanh # 00FF00 đôi khi được sử dụng thay vì gần như không quá tệ. Tuy nhiên, tôi cảm thấy như họ sử dụng fuchsia thường xuyên hơn bởi vì không ai trong tâm trí của họ sẽ muốn màu sắc chính xác đó trong các họa tiết của họ, vì vậy nó khá phổ biến: P
Geobits

3
# 3 - Tôi kiên nhẫn chờ đợi để xem các thuật toán tuyệt vời được tạo ra ... sau đó nhẹ nhàng và yêu thương "mượn" chúng để sử dụng ;-)
scunliffe

Câu trả lời:


10

Matlab, 223 215 209 184 163 byte

Việc thay đổi kích thước là khá thẳng về phía trước. Để cắt xén các góc, tôi phủ một hệ tọa độ lên các pixel và tạo mặt nạ thông qua bốn bất đẳng thức tuyến tính, xác định diện tích của hình lục giác.

​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)

nhập mô tả hình ảnh ở đây

Tái bút: Điều này đã biến thành một trò chơi codegolf nim với đệ trình của @ MartinBüttner: Bạn phải luân phiên làm cho mã của mình ngắn hơn (trong khi cung cấp cùng chức năng) - trò chơi có thể thực hiện chiến thắng 'rút ngắn' cuối cùng =)


Bạn có thể lưu 5 byte bằng cách thay đổi phép tính tỷ lệ thay đổi kích thước thành [k.*[2 3]/4].
cốc

4
Không phải các khu vực nền nên là fuchsia, không phải màu đen?
Hố đen

@Blackhole Cảm ơn đã cho tôi biết, tôi đã sửa nó ngay bây giờ, thậm chí còn tiết kiệm cho tôi khá nhiều byte =)
flawr

12

Toán học, 231 211 209 208 201 188 173 byte

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

Đây là một hàm không tên, lấy một đối tượng hình ảnh và trả về một đối tượng hình ảnh:

nhập mô tả hình ảnh ở đây

Tôi không nghĩ có nhiều điều để giải thích ở đây, nhưng một số chi tiết cần lưu ý:

  • Thông thường, để xếp hình ảnh 2x2, bạn sẽ sử dụng ImageAssemble[{{#,#},{#,#}}], tức là bạn dùng tayImageAssemble ma trận 2x2 với các bản sao của hình ảnh. Tuy nhiên, có ImageCollagemột số loại chức năng ma thuật cố gắng sắp xếp một loạt các hình ảnh "tốt" nhất có thể (bất cứ điều gì có nghĩa là ... bạn thậm chí có thể cung cấp cho từng hình ảnh trọng lượng và công cụ). Dù sao, bạn cung cấp cho nó bốn hình ảnh có kích thước bằng nhau và với trọng lượng bằng nhau (hoặc không), nó cũng sẽ sắp xếp chúng theo dạng lưới 2x2. Điều đó cho phép tôi lưu một số byte cho việc lồng vào ma trận, cũng như tên hàm.
  • Hình lục giác được hiển thị dưới dạng một đa giác đơn thông qua Graphics. Tôi đang sử dụng tích hợp sẵn RegularPolygon@6, nhưng thực thi tỷ lệ khung hình 1để kéo dài nó khi cần thiết. Thật không may, Graphicscần một vài lựa chọn đắt tiền để tránh đệm và như vậy, và nó cũng hiển thị màu đen trên nền trắng thay vì ngược lại. Kết quả được cố định với ColorNegatevà sau đó được gắn vào các kênh gốc của hình ảnh với SetAlphaChannel.
  • Graphicsđặt một lượng nhỏ đệm xung quanh hình lục giác, nhưng chúng tôi muốn hình lục giác alpha bao phủ toàn bộ kích thước của phần bị cắt. Tuy nhiên, SetAlphaChannelcó thể kết hợp các hình ảnh có kích thước khác nhau, bằng cách đặt chúng lên nhau và cắt thành kích thước nhỏ nhất. Điều đó có nghĩa là, thay vì cài đặt thủ công PlotRangePadding->0, chúng ta chỉ cần phóng to hình lục giác một chút bằng ImageSize->1.05e(và dù sao chúng ta cũng cần tùy chọn `ImageSize).

5

HTML5 + Javascript, 562 byte

<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>

Đưa đầu vào dưới dạng URL hình ảnh qua hộp văn bản (hy vọng URL được tính là tên tệp). Xuất dữ liệu ra canvas.

Phiên bản hoạt động trên tất cả các trình duyệt (580 byte):

<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>

Kiểm tra nó với hình ảnh "khối" từ trước đó thông qua URL này: http://i.stack.imgur.com/gQAZh.png


Công việc tốt đẹp! Bạn có thể lưu khá nhiều byte bằng cách thêm id=Avào <form>id=Bvào <canvas>, sau đó thay thế l[0]bằng Al[1]bằng Bvà xóa l=document.body.children;. (Hoạt động trong Firefox 41; không chắc chắn các trình duyệt khác hỗ trợ điều này.) Ngoài ra, tôi tin rằng có một vài dấu chấm phẩy không cần thiết bên cạnh dấu ngoặc nhọn bên phải và thêm một vài khoảng trắng.
Sản phẩm ETH

Thêm lời khuyên: Tôi tin rằng bạn có thể thêm id=Cvào <input>, sau đó thay thế e.target.children[0]bằng C. 0.75bằng 3/4, 1/0.75bằng 4/3, d/4+d/2bằng d*3/4, và các số 0 đứng đầu trên các số thập phân khác là không cần thiết. Tôi cũng tin rằng bạn có thể thay thế cái đầu tiên c.drawImagebằng c[p="drawImage"], sau đó là cái tiếp theo c[p]; bạn có thể làm tương tự với c.lineTo.
Sản phẩm ETH

4

Python 2 + PIL, 320

Đọc tên của tệp hình ảnh từ stdin.

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()

Đúng, xin lỗi về điều đó, không có PILích để thử và tôi đã không nghĩ về nó đủ. Mặc dù vậy, tôi vẫn đứng trước tuyên bố về dòng mới của mình: P
FryAmTheEggman

2

PHP, 293 byte

Tôi đã thêm một số dòng mới để dễ đọc:

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;}

Đây là phiên bản chưa được chỉnh sửa:

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);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.