代码

代码

我不知道如何打乱切片图像的以下网格。如何在 (La)TeX 或 PostScript 级别执行此操作?

在此处输入图片描述

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{multido}
\usepackage{graphicx}

\def\Columns{5}% columns
\def\Rows{5}% rows
\def\Filename{ParisHilton}
\def\Scale{1}

\newsavebox\IBox
\savebox\IBox{\includegraphics[scale=\Scale]{\Filename}}


\psset
{
    xunit=\dimexpr\wd\IBox/\Columns,
    yunit=\dimexpr\ht\IBox/\Rows,
}

\SpecialCoor
\begin{document}

\multido{\ny=\Rows+-1}{\Rows}
{
    \multido{\nx=0+1}{\Columns}
    {
        \pspicture(\Columns,\Rows)
            \psclip{\psframe[linestyle=none,linewidth=0pt](!\nx\space \ny\space 1 sub)(!\nx\space 1 add \ny)}
                \rput[bl](0,0){\usebox\IBox}
            \endpsclip
        \endpspicture
    }
}

\end{document}

这里是图片我在此答案中使用它作为演示图片。

答案1

\documentclass[pstricks]{standalone}
\usepackage{multido}
\usepackage{graphicx}
\def\txG{ true setglobal globaldict begin }
\def\etxG{ end false setglobal }


\def\Columns{4}  \def\Rows{5}
\pstFPmul\MaxElements{\Columns}{\Rows}

\pstVerb{\txG
  /u.n \Columns\space \Rows\space mul def
  /Elements [ 0 1 u.n 1 sub { } for ] def
  realtime srand
  /GetElement { 
    rand u.n mod /Random ED
    Random 
    Elements length mod Elements exch get dup
    5 mod /u.Col ED % col
    5 div cvi /u.Row ED % row
    Elements aload length dup 1 sub /u.n ED 
    Random sub -1 roll pop u.n array astore /Elements ED
  } def
  \etxG }

\newsavebox\IBox
\savebox\IBox{\includegraphics{dante22}}
\psset{xunit=\dimexpr\wd\IBox/\Columns,  yunit=\dimexpr\ht\IBox/\Rows}
\SpecialCoor
\begin{document}

\multido{\iA=1+1}{\MaxElements}{%
\begin{pspicture}(\Columns,\Rows)   
 \rput[lb](!0 0){%
   \psclip{\psframe[linestyle=none]%
     (! \txG GetElement u.Row u.Col \etxG)
     (! \txG u.Row 1 add u.Col 1 add \etxG)} \usebox\IBox
    \endpsclip}
\end{pspicture}}%

\end{document}

在此处输入图片描述

答案2

这是一个基于 LuaTeX/ConTeXt 的简单解决方案。

\shuffle[nx=..., ny=...]{<box>}

其中,nx是您想要的水平切片数,而 my 是您想要的垂直切片数。该宏基于\setupclipping并执行实际的裁剪图像的艰苦工作。此宏有效生成:

\clip[nx=...,ny=...,x=...,y=...]{<box>}

通过随机改变所有可能值的xy。为了生成这样的xy,我只需生成所有可能值并打乱结果即可。据我所知,Lua 没有打乱函数,因此我基于标准 Fisher Yates 算法实现了一个。

这是结果\shuffle[nx=3,ny=2]{\externalfigure[hacker]}(黑客是随 ConTeXt 分发的示例图像之一)。

在此处输入图片描述

最后,宏:

\startluacode
  local random = math.random
  local insert = table.insert
  local format = string.format
  -- Note that ConTeXt stores the value of the random seed
  -- in the tuc file to ensure that you get the random numbers
  -- don't change across runs. If you want a different set of random
  -- numbers just delete the tuc file and compile again

  -- A function to shuffle the contents of a table
  local function shuffle_table(data)
    -- implementation of Fisher Yates shuffle
    local t
    for i=#data,1,-1 do
      local j = random(1,i)
      -- Swap i and j location
      t       = data[i]
      data[i] = data[j]
      data[j] = t
    end
    return data
  end


  local function shuffle_box(nx, ny, box)
    -- Generate table of all possible indices
    local indices = {}
    for i=1,nx do
      for j=1,ny do
        insert(indices, {i,j})
      end
    end
    indices = shuffle_table(indices)
    -- table.print(indices)

    local x, y, settings
    context("\\vbox\\bgroup")
    context("\\baselineskip\\zeropoint \\lineskip\\zeropoint")
    for i = 1,nx do
      context("\\hbox\\bgroup") -- This can be frame for more control
       for j=1,ny do
           x, y = indices[(i-1)*nx+j][2], indices[(i-1)*nx+j][2]
           settings = format("nx=%d, ny=%d, x=%d, y=%d", nx, ny, x, y)
           -- print(settings)
           context.clip({settings}, box)
      end
      context("\\egroup")
    end
    context("\\egroup")

  end
  commands.shuffle = shuffle_box

\stopluacode

\unprotect
\unexpanded\def\shuffle
    {\dosingleargument\shuffle_indeed}

\def\????shuffle{@@@@shuffle}

\def\shuffle_indeed[#1]#2% #2 should be some boxed material
    {\getparameters[\????shuffle][\c!nx=4,\c!ny=4,#1]%
     \ctxcommand{shuffle(\@@@@shufflenx, \@@@@shuffleny, \!!bs #2 \!!es)}}

\starttext
\shuffle[nx=3,ny=3]{\externalfigure[cow]}
\stoptext

答案3

这是另一个。代码有点乱,所以我将输出分开:

首先我需要获取一个随机列表,我首先声明一个常规递增数字列表。然后我从中挑选一个数字并将其放入新列表中。同时,我从旧列表中删除该数字并重复此操作,直到用完所有数字。

所以输出看起来像这样

在此处输入图片描述

拾取的号码切换到我们右侧的新列表(然后我们删除初始逗号)。

然后(计为 11-> 8+3 第二行,第三列)我们从列表中获取随机数,转换为单元格坐标,并根据我们著名的 Paulo Cereda 在关于 Sprite Sheet 的博客文章。我选择了 4 x 4 网格,但可以更改。另请注意,底层坐标系已缩放以匹配图像的宽度和高度。

我使用过巴黎希尔顿酒店,图片来自他们的网站,因为我受不了那些名人。所以输出是

在此处输入图片描述

代码

(正如 Peter Grill 所做的那样)

\documentclass{article}
\usepackage{tikz,xstring}
% Declare the image
\pgfdeclareimage[interpolate=true,width=8cm,height=5cm]{hotel}{hiltonparis.jpg}
\def\mylist{}
\def\myrandlist{}
\foreach \x in {1,...,16}{ %Generate list
\xdef\mylist{\mylist\noexpand{\x\noexpand}}
}

\begin{document}

\pgfmathdeclarerandomlist{mynum}{\mylist} %Define the list 
\foreach \x in {1,...,16}{
    \pgfmathrandomitem{\mynum}{mynum} % Pick one from that list
    \xdef\myrandlist{\myrandlist,\mynum} % place in the new list
    \StrSubstitute{\mylist}{{\mynum}}{}[\sublist] % Delete that entry from the list
    \global\let\mylist\sublist % Update the main list
    \pgfmathdeclarerandomlist{mynum}{\mylist} % Redefine the list

    \mylist\hfill \myrandlist%Let's see if we succeeded removing duplicates. Remove later
}

% Remove the first comma
\StrGobbleLeft{\myrandlist}{1}[\myrandlist] 
\xdef\myrandlist{{\myrandlist}} % After all, it's a stupid shuffle

\pgfuseimage{hotel}

\vspace{1cm}
\begin{tikzpicture}[xscale=2,yscale=1.25, %Scaling according to the image
path image/.style args={#1 shifted #2 and #3}{%
    path picture={
        \node[anchor=north west,outer sep=0] 
        at ([shift={(-#2,#3)}]path picture bounding box.north west) {\pgfuseimage{#1}};
    }
}]
\foreach \x in {0,...,3}{
    \foreach \y in {0,...,3}{
    \pgfmathtruncatemacro{\yy}{4*\x+\y}
    \pgfmathtruncatemacro{\xx}{\myrandlist[\yy]}
    \pgfmathtruncatemacro{\curry}{Mod(\xx,4)}
    \pgfmathtruncatemacro{\currx}{(\xx)/4} % Integer part
    \path[path image=hotel shifted \currx cm and \curry cm] %Shifts the image
        (\x cm,-\y cm) rectangle +(1cm,1cm); %The size is the unit shift size
    }
}
\end{tikzpicture}
\end{document}

答案4

由于对这个问题的第一条评论,我不会打乱网格位置。而是打乱用于组成动画帧的单元格的顺序。本质保持不变。

使用 C# 的混合解决方案如下。此代码已由专家

/*===================================*
 * Compile it to produce Shuffle.exe *
 * ==================================*/
using System;
using System.Collections.Generic;
using System.IO;

namespace Shuffle
{
    class Program
    {
        static void Main(string[] args)
        {
            int columns = int.Parse(args[0]);
            int rows = int.Parse(args[1]);
            int seed = int.Parse(args[2]);
            string outputFilename = args[3];

            string[] elements = new string[columns * rows];
            for (int column = 0; column < columns; column++)
                for (int row = 0; row < rows; row++)
                    elements[column * rows + row] = string.Format("{{{0},{1}}}", column, row);

            Random random = new Random(seed);
            for (int i = elements.Length - 1; i >= 0; i--)
            {
                int swapIndex = random.Next(i + 1);
                string tmp = elements[i];
                elements[i] = elements[swapIndex];
                elements[swapIndex] = tmp;
            }

            File.WriteAllLines(outputFilename, elements);
        }
    }
}

在此处输入图片描述

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{multido}
\usepackage{graphicx}

\def\Columns{10}% columns
\def\Rows{10}% rows
\def\Filename{parishilton}
\def\Scale{1}

\newsavebox\IBox
\savebox\IBox{\includegraphics[scale=\Scale]{\Filename}}


\psset
{
    xunit=\dimexpr\wd\IBox/\Columns,
    yunit=\dimexpr\ht\IBox/\Rows,
}

\SpecialCoor
\newread\myfile

\def\tempii#1,#2{%
    \pspicture(\Columns,\Rows)
        \psclip{\psframe[linestyle=none,linewidth=0pt](!#1 #2)(!#1 1 add #2 1 add)}
            \rput[bl](0,0){\usebox\IBox}
        \endpsclip
    \endpspicture}

\def\tempi#1{\expandafter\tempii#1\relax}

\begin{document}

\immediate\write18{cmd /C del data.txt}
\immediate\write18{Shuffle.exe \Columns\space \Rows\space 1 data.txt}

\openin\myfile=data.txt\relax
    \loop
        \read\myfile to \dd
        \unless\ifeof\myfile
        \expandafter\tempi\dd\relax
    \repeat
\closein\myfile

\end{document}

相关内容