Görüntüdeki pikselleri yeniden düzenleyin, böylece tanınmayacak ve daha sonra geri alın


86

Görüntüdeki pikselleri yeniden düzenleyebilecek, böylece tanınamayacak bir program oluşturun. Ancak programınız tekrar orijinal görüntüye dönüştürebilmelidir.

İki fonksiyon yazabilirsiniz - kodlama ve kod çözme için, tekrar tekrar uygulanan orijinal görüntüyü verir (matematikte örnek olarak f(x) = 1 - x) bir bonusdur.

Ayrıca çıktıda bir miktar kalıp üretmek de bonus verir.

Diliniz destekliyorsa, görüntü 1D / 2D dizi veya görüntü nesnesi olarak gösterilebilir. Sadece piksel sırasını değiştirebileceğinizi unutmayın!

Daha az tanınabilir görüntü üreten kazanan kod olarak seçilmesi mantıklı olacaktır, ancak tam olarak nasıl ölçüleceğini bilmiyorum, hayal edebileceğim tüm yollar aldatılabilir. Dolayısıyla bu soruyu popülerlik yarışması olarak seçtim - kullanıcıların en iyi cevabı seçmelerini sağlayın!

Test görüntüsü 1 (800 x 422 piksel): Test görüntüsü 2 (800 x 480 piksel): Lütfen kod çıkış görüntüsünü girin.


Soru, çok uzun soluklu bir şekilde "Çıktısı bir görüntü olan görüntüler için bir şifreleme algoritması yazın" demenin yoludur.
David Richerby

3
@DavidRicherby… aynı piksel / renkleri kullanır. "Düz resim" de beş siyah piksel -> "şifre resim" de beş siyah piksel.
Daniel Beck,

2
@ user2992539 Tamam, bu durumda açıkça bunun bağlayıcı olarak kullanıldığını belirtmek isteyebilirsiniz. Aksi takdirde, sadece bunun bir bonus olduğunu söylemek çok anlamlı değildir.
Martin Ender

3
Bu soru bana Arnold'un kedi haritasını düşündürdü . Bunun için uygun olduğunu sanmıyorum ama aynı şekilde ilginç - haritayı yeterince tekrarlamak sizi orijinal görüntüye geri götürür.
trichoplax

4
Şimdi Stack Exchange ağında başka bir yerde: Güvenlik . Her yerin güvenliği
Doorknob

Yanıtlar:


58

Python 2.7 (PIL ile) - Sahte Adsızlık Yok

Görüntüyü 2'ye 2 bloğa ayırırım (kalanı yok sayarak) ve her bloğu 180 derece döndürürüm, ardından aynı parametreyi BLKSZ'ye kadar 3'e 3 blokla, sonra 4'le vb. Sonra aynısını BLKSZ-1, ardından BLKSZ-2, 3'e ve ardından 2'ye geri yapıyorum. Bu yöntem tam olarak kendini tersine çeviriyor; deşifre işlevi deşifre işlevidir.

Kod :

from PIL import Image
import math

im = Image.open("ST1.png", "r")
arr = im.load() #pixel data stored in this 2D array

def rot(A, n, x1, y1): #this is the function which rotates a given block
    temple = []
    for i in range(n):
        temple.append([])
        for j in range(n):
            temple[i].append(arr[x1+i, y1+j])
    for i in range(n):
        for j in range(n):
            arr[x1+i,y1+j] = temple[n-1-i][n-1-j]


xres = 800
yres = 480
BLKSZ = 50 #blocksize
for i in range(2, BLKSZ+1):
    for j in range(int(math.floor(float(xres)/float(i)))):
        for k in range(int(math.floor(float(yres)/float(i)))):
            rot(arr, i, j*i, k*i)
for i in range(3, BLKSZ+1):
    for j in range(int(math.floor(float(xres)/float(BLKSZ+2-i)))):
        for k in range(int(math.floor(float(yres)/float(BLKSZ+2-i)))):
            rot(arr, BLKSZ+2-i, j*(BLKSZ+2-i), k*(BLKSZ+2-i))

im.save("ST1OUT "+str(BLKSZ)+".png")

print("Done!")

Blok ölçüsüne bağlı olarak, hesaplamanın orijinal görüntünün tüm benzerliğini ortadan kaldırmasını sağlayabilirsiniz: (BLKSZ = 50) görüntü tanımını buraya girin görüntü tanımını buraya girin

Veya hesaplamayı verimli hale getirin: (BLKSZ = 10) görüntü tanımını buraya girin görüntü tanımını buraya girin


6
En iyi sonuçlar gibi ses, BLKSZ resim boyutunun yaklaşık yarısı kadar olacaksa olacaktır. Her neyse, algoritmayı seviyorum ve küçük BLKSZ için modern bir sanat eserine benziyor! Güzel!
Somnium

11
Pitonu her zaman büyütürüm.
qwr

2 ile 50 arasındaki tüm değerler için karıştırmak yerine, sadece asal sayıları mı kullanmalısınız?
Neil,

@Neil Muhtemelen o zaman daha rastgele ve daha az sanatsal görünecek.
Somnium

BLKSZ = 10Manzara gerçekten iyidir!
wchargin

52

C #, Winform

Düzenleme Koordinatlar dizisini doldurma şeklinizi değiştirmek farklı desenlere sahip olabilir - aşağıya bakınız

Bu tür bir desen hoşunuza gitti mi?

peyzaj

Soyut, Özet

Bonus:

Çığlık Scrambled Çığlık

Rastgele takas tam olarak bir kez tüm pikselleri üst yarıda, tüm pikseller alt yarıda. Şifresini çözmek için aynı işlemi tekrarlayın (bonus).

kod

Scramble.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.IO;

namespace Palette
{
    public partial class Scramble : Form
    {
        public Scramble()
        {
            InitializeComponent();
        }

        public struct Coord
        {
            public int x, y;
        }

        private void Work(Bitmap srcb, Bitmap outb)
        {
            int w = srcb.Width, h = srcb.Height;
            Coord[] coord = new Coord[w * h];

            FastBitmap fsb = new FastBitmap(srcb);
            FastBitmap fob = new FastBitmap(outb);
            fsb.LockImage();
            fob.LockImage();
            ulong seed = 0;
            int numpix = 0;
            for (int y = 0; y < h; y++)
                for (int x = 0; x < w; numpix++, x++)
                {
                    coord[numpix].x = x;
                    coord[numpix].y = y;
                    uint color = fsb.GetPixel(x, y);
                    seed += color;
                    fob.SetPixel(x, y, color);
                }
            fsb.UnlockImage();
            fob.UnlockImage();
            pbOutput.Refresh();
            Application.DoEvents();

            int half = numpix / 2;
            int limit = half;
            XorShift rng = new XorShift(seed);
            progressBar.Visible = true;
            progressBar.Maximum = limit;

            fob.LockImage();
            while (limit > 0)
            {
                int p = (int)(rng.next() % (uint)limit);
                int q = (int)(rng.next() % (uint)limit);
                uint color = fob.GetPixel(coord[p].x, coord[p].y); 
                fob.SetPixel(coord[p].x, coord[p].y, fob.GetPixel(coord[half+q].x, coord[half+q].y)); 
                fob.SetPixel(coord[half+q].x, coord[half+q].y, color); 
                limit--;
                if (p < limit)
                {
                    coord[p]=coord[limit];
                }
                if (q < limit)
                {
                    coord[half+q]=coord[half+limit];
                }
                if ((limit & 0xfff) == 0)
                {
                    progressBar.Value = limit;
                    fob.UnlockImage();
                    pbOutput.Refresh();
                    fob.LockImage();
                }
            }
            fob.UnlockImage();
            pbOutput.Refresh();
            progressBar.Visible = false; 
        }

        void DupImage(PictureBox s, PictureBox d)
        {
            if (d.Image != null)
                d.Image.Dispose();
            d.Image = new Bitmap(s.Image.Width, s.Image.Height);  
        }

        void GetImagePB(PictureBox pb, string file)
        {
            Bitmap bms = new Bitmap(file, false);
            Bitmap bmp = bms.Clone(new Rectangle(0, 0, bms.Width, bms.Height), PixelFormat.Format32bppArgb);
            bms.Dispose(); 
            if (pb.Image != null)
                pb.Image.Dispose();
            pb.Image = bmp;
        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();

            openFileDialog.InitialDirectory = "c:\\temp\\";
            openFileDialog.Filter = "Image Files(*.BMP;*.JPG;*.PNG)|*.BMP;*.JPG;*.PNG|All files (*.*)|*.*";
            openFileDialog.FilterIndex = 1;
            openFileDialog.RestoreDirectory = true;

            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    string file = openFileDialog.FileName;
                    GetImagePB(pbInput, file);
                    pbInput.Tag = file;
                    DupImage(pbInput, pbOutput);
                    Work(pbInput.Image as Bitmap, pbOutput.Image as Bitmap);
                    file = Path.GetDirectoryName(file) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(file) + ".scr.png";
                    pbOutput.Image.Save(file);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
                }

            }
        }
    }

    //Adapted from Visual C# Kicks - http://www.vcskicks.com/
    unsafe public class FastBitmap
    {
        private Bitmap workingBitmap = null;
        private int width = 0;
        private BitmapData bitmapData = null;
        private Byte* pBase = null;

        public FastBitmap(Bitmap inputBitmap)
        {
            workingBitmap = inputBitmap;
        }

        public BitmapData LockImage()
        {
            Rectangle bounds = new Rectangle(Point.Empty, workingBitmap.Size);

            width = (int)(bounds.Width * 4 + 3) & ~3;

            //Lock Image
            bitmapData = workingBitmap.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
            pBase = (Byte*)bitmapData.Scan0.ToPointer();
            return bitmapData;
        }

        private uint* pixelData = null;

        public uint GetPixel(int x, int y)
        {
            pixelData = (uint*)(pBase + y * width + x * 4);
            return *pixelData;
        }

        public uint GetNextPixel()
        {
            return *++pixelData;
        }

        public void GetPixelArray(int x, int y, uint[] Values, int offset, int count)
        {
            pixelData = (uint*)(pBase + y * width + x * 4);
            while (count-- > 0)
            {
                Values[offset++] = *pixelData++;
            }
        }

        public void SetPixel(int x, int y, uint color)
        {
            pixelData = (uint*)(pBase + y * width + x * 4);
            *pixelData = color;
        }

        public void SetNextPixel(uint color)
        {
            *++pixelData = color;
        }

        public void UnlockImage()
        {
            workingBitmap.UnlockBits(bitmapData);
            bitmapData = null;
            pBase = null;
        }
    }

    public class XorShift
    {
        private ulong x; /* The state must be seeded with a nonzero value. */

        public XorShift(ulong seed)
        {
            x = seed;
        }

        public ulong next()
        {
            x ^= x >> 12; // a
            x ^= x << 25; // b
            x ^= x >> 27; // c
            return x * 2685821657736338717L;
        }
    }
} 

Scramble.designer.cs

namespace Palette
{
    partial class Scramble
    {
        private System.ComponentModel.IContainer components = null;

        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        private void InitializeComponent()
        {
            this.panel = new System.Windows.Forms.FlowLayoutPanel();
            this.pbInput = new System.Windows.Forms.PictureBox();
            this.pbOutput = new System.Windows.Forms.PictureBox();
            this.progressBar = new System.Windows.Forms.ProgressBar();
            this.btnOpen = new System.Windows.Forms.Button();
            this.panel.SuspendLayout();
            ((System.ComponentModel.ISupportInitialize)(this.pbInput)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.pbOutput)).BeginInit();
            this.SuspendLayout();
            // 
            // panel
            // 
            this.panel.AutoScroll = true;
            this.panel.AutoSize = true;
            this.panel.Controls.Add(this.pbInput);
            this.panel.Controls.Add(this.pbOutput);
            this.panel.Dock = System.Windows.Forms.DockStyle.Top;
            this.panel.Location = new System.Drawing.Point(0, 0);
            this.panel.Name = "panel";
            this.panel.Size = new System.Drawing.Size(748, 306);
            this.panel.TabIndex = 3;
            // 
            // pbInput
            // 
            this.pbInput.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.pbInput.Location = new System.Drawing.Point(3, 3);
            this.pbInput.MinimumSize = new System.Drawing.Size(100, 100);
            this.pbInput.Name = "pbInput";
            this.pbInput.Size = new System.Drawing.Size(100, 300);
            this.pbInput.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
            this.pbInput.TabIndex = 3;
            this.pbInput.TabStop = false;
            // 
            // pbOutput
            // 
            this.pbOutput.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.pbOutput.Location = new System.Drawing.Point(109, 3);
            this.pbOutput.MinimumSize = new System.Drawing.Size(100, 100);
            this.pbOutput.Name = "pbOutput";
            this.pbOutput.Size = new System.Drawing.Size(100, 300);
            this.pbOutput.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
            this.pbOutput.TabIndex = 4;
            this.pbOutput.TabStop = false;
            // 
            // progressBar
            // 
            this.progressBar.Dock = System.Windows.Forms.DockStyle.Bottom;
            this.progressBar.Location = new System.Drawing.Point(0, 465);
            this.progressBar.Name = "progressBar";
            this.progressBar.Size = new System.Drawing.Size(748, 16);
            this.progressBar.TabIndex = 5;
            // 
            // btnOpen
            // 
            this.btnOpen.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
            this.btnOpen.Location = new System.Drawing.Point(12, 429);
            this.btnOpen.Name = "btnOpen";
            this.btnOpen.Size = new System.Drawing.Size(53, 30);
            this.btnOpen.TabIndex = 6;
            this.btnOpen.Text = "Start";
            this.btnOpen.UseVisualStyleBackColor = true;
            this.btnOpen.Click += new System.EventHandler(this.btnOpen_Click);
            // 
            // Scramble
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.BackColor = System.Drawing.SystemColors.ControlDark;
            this.ClientSize = new System.Drawing.Size(748, 481);
            this.Controls.Add(this.btnOpen);
            this.Controls.Add(this.progressBar);
            this.Controls.Add(this.panel);
            this.Name = "Scramble";
            this.Text = "Form1";
            this.panel.ResumeLayout(false);
            this.panel.PerformLayout();
            ((System.ComponentModel.ISupportInitialize)(this.pbInput)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.pbOutput)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();

        }


        private System.Windows.Forms.FlowLayoutPanel panel;
        private System.Windows.Forms.PictureBox pbOutput;
        private System.Windows.Forms.ProgressBar progressBar;
        private System.Windows.Forms.PictureBox pbInput;
        private System.Windows.Forms.Button btnOpen;
    }
}

program.cs

using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace Palette
{
  static class Program
  {
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Scramble());
    }
  }
}

Derlemek için proje özelliğinde 'Güvensiz kod' seçeneğini işaretleyin.

Karmaşık desen

karıştırmak

İş işlevinin ilk bölümünü, Application.DoEvents'a kadar değiştirin:

        int w = srcb.Width, h = srcb.Height;
        string Msg = "Scramble";

        Graphics gr = Graphics.FromImage(outb);

        Font f = new Font("Arial", 100, FontStyle.Bold);
        var size = gr.MeasureString(Msg, f);
        f = new Font("Arial", w / size.Width * 110, FontStyle.Bold);
        size = gr.MeasureString(Msg, f);
        gr.DrawString(Msg, f, new SolidBrush(Color.White), (w - size.Width) / 2, (h - size.Height) / 2);

        gr.Dispose();

        Coord[] coord = new Coord[w * h];
        FastBitmap fsb = new FastBitmap(srcb);
        FastBitmap fob = new FastBitmap(outb);
        fsb.LockImage();
        fob.LockImage();
        ulong seed = 1;
        int numpix = h * w;
        int c1 = 0, c2 = numpix;
        int y2 = h / 2;

        int p2 = numpix/2;

        for (int p = 0; p < p2; p++)
        {
            for (int s = 1; s > -2; s -= 2)
            {
                int y = (p2+s*p) / w;
                int x = (p2+s*p) % w;

                uint d = fob.GetPixel(x, y);
                if (d != 0)
                {
                    c2--;
                    coord[c2].x = x;
                    coord[c2].y = y;
                }
                else
                {
                    coord[c1].x = x;
                    coord[c1].y = y;
                    c1++;
                }
                fob.SetPixel(x, y, fsb.GetPixel(x, y));
            }
        }
        fsb.UnlockImage();
        fob.UnlockImage();
        pbOutput.Refresh();
        Application.DoEvents();

1
İlginç) Benzer bir yaklaşımla çıktıda daha karmaşık kalıplar yapmanın mümkün olup olmadığını merak ediyorum.
Somnium

1
Güzel fikir - tek sayıda satır olduğunda orta hatta ne olur?
kusur

1
@flawr ayırma piksel başına. Tek sayıda piksel varsa, sonuncusu dokunulmadan bırakılır. Tek sayıda satır varsa, orta sıranın sol yarısı "üst taraf" ve sağ yarısı "alt taraf" dır.
edc65

1
@ user2992539 Daha da fazla alt bölüm ekleyebileceğinizi düşünüyorum - dama tahtası bile. Daha fazla alt bölümle, görüntü daha belirgindir.
edc65

7
"Scramble" versiyonunuz gibi!)
Somnium

43

C, keyfi bulanıklık, kolayca geri dönüşümlü

Partiye geç. İşte girişim!

Bu yöntem çırpınıyor bulanıklığı yapar. Ben buna scramblur diyorum . Bu son derece basit. Bir döngüde, rastgele bir piksel seçer ve sonra toroidal tuval modelinde rastgele seçilen yakındaki bir pikselle değiştirir. "Yakındaki pikselin" ne anlama geldiğini (1 her zaman bitişik bir piksel seçmek anlamına gelir), yineleme sayısını ve isteğe bağlı olarak rastgele bir sayı tohumunu tanımlayan maksimum mesafeyi belirlersiniz. Maksimum mesafe ne kadar büyükse ve yineleme sayısı ne kadar büyükse, sonuç o kadar bulanık olur.

Negatif sayıda yineleme belirterek tersine çevrilebilir (bu sadece bir komut satırı arabirimi kolaylığı; aslında negatif yinelemeler diye bir şey yoktur). Dahili olarak, özel bir 64-bit LCPRNG (doğrusal uyumlu sözde rasgele sayı üreteci) kullanır ve bir değerler bloğu önceden oluşturur. Tablo, sırasıyla karıştırma veya çözme işlemi için blok boyunca ileri veya geri gitmeyi sağlar.

gösteri

İlk iki resim için, aşağı kaydırdığınızda, her resim daha yüksek bir maksimum ofset kullanılarak bulanıklaştırılır: En üstteki orijinal resim (örn. 0 piksel ofset), ardından 1, 2, 4, 8, 16, 32, 64 , 128 ve son olarak 256. İterasyon sayısı, aşağıdaki tüm resimler için 10⁶ = 1.000.000'dir.

İkinci iki resim için, her resim aşamalı olarak daha düşük bir ofset (örneğin, en bulanık ve en az bulanıklığa kadar), 256 ila 0 arasında bir maksimum ofset kullanarak bulanıklaştırılır.

peyzaj Soyut, Özet

Ve sonraki iki resim için, ilerlemeleri tam boyutlu olarak burada ve burada görebilirsiniz :

Kötü kırma Simpsonlar

kod

Bu sabah uyanırken bunu yaklaşık bir saat içinde hackledim ve neredeyse hiçbir belge içermiyor. Birkaç gün içinde geri gelebilir ve insanlar talep ederse daha fazla belge ekleyebilirim.

//=============================================================================
// SCRAMBLUR
//
// This program is a image-processing competition entry which scrambles or
// descrambles an image based on a pseudorandom process.  For more details,
// information, see:
//
//    http://codegolf.stackexchange.com/questions/35005
//
// It is assumed that you have the NETPBM package of image-processing tools
// installed on your system.  This can be obtained from:
//
//    http://netpbm.sourceforge.net/
//
// or by using your system's package manager, e.g., yum, apt-get, port, etc.
//
// Input to the program is a 24-bit PNM image (type "P6").  Output is same.
// Example command-line invocation:
//
// pngtopnm original.png  | scramblur 100  1000000 | pnmtopng >scrambled.png
// pngtopnm scrambled.png | scramblur 100 -1000000 | pnmtopng >recovered.png
//
//
// Todd S. Lehman, July 2014

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>

typedef uint8_t uint8;
typedef uint64_t uint64;

//-----------------------------------------------------------------------------
// PIXEL STRUCTURE

#pragma pack(push, 1)
typedef struct
{
  uint8 r, g, b;     // Red, green, and blue color components
}
Pixel;
#pragma pack(pop)

//-----------------------------------------------------------------------------
// IMAGE STRUCTURE

typedef struct
{
  int width;          // Width of image in pixels
  int height;         // Height of image in pixels
  int pixel_count;    // Total number of pixels in image (e.g., width * height)
  int maxval;         // Maximum pixel component value (e.g., 255)
  Pixel *data;        // One-dimensional array of pixels
}
Image;

//-----------------------------------------------------------------------------
// 64-BIT LCG TABLE

static const long lcg64_table_length = 1000000;  // 10⁶ entries => 8 Megabytes

static uint64 lcg64_table[lcg64_table_length];

//-----------------------------------------------------------------------------
// GET 64-BIT LCG VALUE FROM TABLE

uint64 lcg64_get(long const iteration)
{
  return lcg64_table[iteration % lcg64_table_length];
}

//-----------------------------------------------------------------------------
// INITIALIZE 64-BIT LCG TABLE

void lcg64_init(uint64 const seed)
{
  uint64 x = seed;
  for (long iteration = 0; iteration < lcg64_table_length; iteration++)
  {
    uint64 const a = UINT64_C(6364136223846793005);
    uint64 const c = UINT64_C(1442695040888963407);
    x = (x * a) + c;
    lcg64_table[iteration] = x;
  }
}

//-----------------------------------------------------------------------------
// READ BINARY PNM IMAGE

Image image_read(FILE *const file)
{
  Image image = { .data = NULL };

  char *line = NULL;
  size_t linecap = 0;

  // Read image type.  (Currently only P6 is supported here.)
  if (getline(&line, &linecap, file) < 0) goto failure;
  if (strcmp(line, "P6\n") != 0) goto failure;

  // Read width and height of image in pixels.
  {
    if (getline(&line, &linecap, file) < 0) goto failure;
    char *pwidth = &line[0];
    char *pheight = strchr(line, ' ');
    if (pheight != NULL) pheight++; else goto failure;
    image.width = atoi(pwidth);
    image.height = atoi(pheight);
    image.pixel_count = image.width * image.height;
  }

  // Read maximum color value.  (Currently only 255 is supported here.)
  {
    if (getline(&line, &linecap, file) < 0) goto failure;
    image.maxval = atoi(line);
    if (image.maxval != 255)
      goto failure;
  }

  // Allocate image buffer and read image data.
  if (!(image.data = calloc(image.pixel_count, sizeof(Pixel))))
    goto failure;

  if (fread(image.data, sizeof(Pixel), image.pixel_count, file) !=
      image.pixel_count)
    goto failure;

success:
  free(line);
  return image;

failure:
  free(line);
  free(image.data); image.data = NULL;
  return image;
}

//-----------------------------------------------------------------------------
// WRITE BINARY PNM IMAGE

void image_write(const Image image, FILE *const file)
{
  printf("P6\n");
  printf("%d %d\n", image.width, image.height);
  printf("%d\n", image.maxval);
  (void)fwrite(image.data, sizeof(Pixel), image.pixel_count, file);
}

//-----------------------------------------------------------------------------
// DISCARD IMAGE

void image_discard(Image image)
{
  free(image.data);
}

//-----------------------------------------------------------------------------
// SCRAMBLE OR UNSCRAMBLE IMAGE

void image_scramble(Image image,
                    int const max_delta,
                    long const iterations,
                    uint64 const lcg64_seed)
{
  if (max_delta == 0) return;

  int neighborhood1 = (2 * max_delta) + 1;
  int neighborhood2 = neighborhood1 * neighborhood1;

  lcg64_init(lcg64_seed);

  long iteration_start = (iterations >= 0)? 0 : -iterations;
  long iteration_end   = (iterations >= 0)? iterations : 0;
  long iteration_inc   = (iterations >= 0)? 1 : -1;

  for (long iteration = iteration_start;
       iteration != iteration_end;
       iteration += iteration_inc)
  {
    uint64 lcg64 = lcg64_get(iteration);

    // Choose random pixel.
    int pixel_index = (int)((lcg64 >> 0) % image.pixel_count);

    // Choose random pixel in the neighborhood.
    int d2 = (int)((lcg64 >> 8) % neighborhood2);
    int dx = (d2 % neighborhood1) - (neighborhood1 / 2);
    int dy = (d2 / neighborhood1) - (neighborhood1 / 2);
    int other_pixel_index = pixel_index + dx + (dy * image.width);
    while (other_pixel_index < 0)
      other_pixel_index += image.pixel_count;
    other_pixel_index %= image.pixel_count;

    // Swap pixels.
    Pixel t = image.data[pixel_index];
    image.data[pixel_index] = image.data[other_pixel_index];
    image.data[other_pixel_index] = t;
  }
}

//-----------------------------------------------------------------------------
int main(const int argc, char const *const argv[])
{
  int max_delta     = (argc > 1)? atoi(argv[1]) : 1;
  long iterations   = (argc > 2)? atol(argv[2]) : 1000000;
  uint64 lcg64_seed = (argc > 3)? (uint64)strtoull(argv[3], NULL, 10) : 0;

  Image image = image_read(stdin);
  if (!image.data) { fprintf(stderr, "Invalid input\n"), exit(1); }

  image_scramble(image, max_delta, iterations, lcg64_seed);

  image_write(image, stdout);

  image_discard(image);

  return 0;
}

4
Sadece bu cevabı kaydırdı, harika görünüyor
Thomas

1
Bu cevap gerçekten çok uzun. Ekstra görüntüleri (yani iki test görüntüsü dışındaki her şey tamamen bulanık) saha dışı bir galeriye taşıyabileceğinizi düşünüyor musunuz?
Tim S.

@TimS. - bitti! küçücük minik resimlere küçülttüm.
Todd Lehman,

42

Python 3.4

  • Bonus 1: Kendi kendine ters: yinelenen orijinal görüntüyü geri yükler.
  • İsteğe bağlı anahtar görüntü: orijinal görüntü yalnızca aynı anahtar görüntü kullanılarak yeniden yüklenebilir.
  • Bonus 2: Çıktıda model üretmek: şifrelenmiş piksellerde ana görüntü yaklaşıkdır.

Bonus 2'ye ulaşıldığında, ilave bir anahtar görüntü kullanarak, bonus 1 kaybedilmez. Yine aynı tuş görüntüsü ile çalıştırılması şartıyla program hala kendi kendine ters.

Standart kullanım

Test görüntüsü 1:

Şifreli test görüntüsü 1

Test görüntüsü 2:

Şifreli test resmi 2

Programı argüman olarak tek bir görüntü dosyasıyla çalıştırmak, görüntü dosyasını tüm görüntünün üzerine eşit şekilde karıştırılmış olarak kaydeder. Tekrar karıştırılmış çıktıyla çalıştırmak, tekrar uygulanan karıştırmayla bir görüntü dosyasını kaydeder; bu, yeniden karıştırma işlemi kendi tersi olduğundan orijinali geri yükler.

Çırpma işlemi kendi kendine terstir, çünkü tüm piksellerin listesi 2 çevrime ayrılır, böylece her piksel bir ve yalnızca bir pikselle değiştirilir. İkinci kez çalıştırma, her pikseli ilk olarak değiştirildiği pikselle değiştirerek her şeyi nasıl başladığına geri döndürür. Tek sayıda piksel varsa, hareket etmeyen bir piksel olacaktır.

Sayesinde mfvonh cevabı ilk olarak 2-döngüleri önermek.

Anahtar görüntü ile kullanım

Scrambling Test görüntüsü 1 ile Test görüntüsü 2 ile anahtar görüntü olarak

Scramble testi 1 ile test 2

Scrambling Test görüntüsü 2 Test görüntüsü 1 ile anahtar görüntü olarak

Scramble testi 2 testi 1 ile

Programı ikinci bir görüntü dosyası argümanı (anahtar görüntü) ile çalıştırmak, orijinal görüntüyü anahtar görüntüye göre bölgelere ayırır. Bu bölgelerin her biri ayrı ayrı 2-çevrime bölünmüştür, böylece çırpma işleminin tamamı bölgeler içinde gerçekleşir ve pikseller bir bölgeden diğerine taşınmaz. Bu, pikselleri her bölgeye yayar ve böylelikle bölgeler düzgün bir benekli renk olur, ancak her bölge için biraz farklı bir ortalama renge sahiptir. Bu, yanlış görüntünün yanlış renklerde çok kaba bir şekilde tahmin edilmesini sağlar.

Tekrar çalıştırmak, her bölgedeki aynı piksel çiftlerini değiştirir, böylece her bölge orijinal durumuna geri yüklenir ve görüntü bir bütün olarak yeniden belirir.

Görüntüyü bölgelere ayırmayı öneren ilk olarak edc65'in cevabı sayesinde . Keyfi bölgeleri kullanmak için bunu genişletmek istedim, ancak bölge 1'deki her şeyi bölge 2'deki her şeyle değiştirme yaklaşımı, bölgelerin aynı büyüklükte olması gerektiği anlamına geliyordu. Benim çözümüm bölgeleri birbirinden yalıtılmış tutmak ve her bölgeyi kendi içine karıştırmak. Bölgelerin artık benzer boyutta olmaları gerekmediğinden, isteğe bağlı şekilli bölgelerin uygulanması daha kolay hale gelir.

kod

import os.path
from PIL import Image   # Uses Pillow, a fork of PIL for Python 3
from random import randrange, seed


def scramble(input_image_filename, key_image_filename=None,
             number_of_regions=16777216):
    input_image_path = os.path.abspath(input_image_filename)
    input_image = Image.open(input_image_path)
    if input_image.size == (1, 1):
        raise ValueError("input image must contain more than 1 pixel")
    number_of_regions = min(int(number_of_regions),
                            number_of_colours(input_image))
    if key_image_filename:
        key_image_path = os.path.abspath(key_image_filename)
        key_image = Image.open(key_image_path)
    else:
        key_image = None
        number_of_regions = 1
    region_lists = create_region_lists(input_image, key_image,
                                       number_of_regions)
    seed(0)
    shuffle(region_lists)
    output_image = swap_pixels(input_image, region_lists)
    save_output_image(output_image, input_image_path)


def number_of_colours(image):
    return len(set(list(image.getdata())))


def create_region_lists(input_image, key_image, number_of_regions):
    template = create_template(input_image, key_image, number_of_regions)
    number_of_regions_created = len(set(template))
    region_lists = [[] for i in range(number_of_regions_created)]
    for i in range(len(template)):
        region = template[i]
        region_lists[region].append(i)
    odd_region_lists = [region_list for region_list in region_lists
                        if len(region_list) % 2]
    for i in range(len(odd_region_lists) - 1):
        odd_region_lists[i].append(odd_region_lists[i + 1].pop())
    return region_lists


def create_template(input_image, key_image, number_of_regions):
    if number_of_regions == 1:
        width, height = input_image.size
        return [0] * (width * height)
    else:
        resized_key_image = key_image.resize(input_image.size, Image.NEAREST)
        pixels = list(resized_key_image.getdata())
        pixel_measures = [measure(pixel) for pixel in pixels]
        distinct_values = list(set(pixel_measures))
        number_of_distinct_values = len(distinct_values)
        number_of_regions_created = min(number_of_regions,
                                        number_of_distinct_values)
        sorted_distinct_values = sorted(distinct_values)
        while True:
            values_per_region = (number_of_distinct_values /
                                 number_of_regions_created)
            value_to_region = {sorted_distinct_values[i]:
                               int(i // values_per_region)
                               for i in range(len(sorted_distinct_values))}
            pixel_regions = [value_to_region[pixel_measure]
                             for pixel_measure in pixel_measures]
            if no_small_pixel_regions(pixel_regions,
                                      number_of_regions_created):
                break
            else:
                number_of_regions_created //= 2
        return pixel_regions


def no_small_pixel_regions(pixel_regions, number_of_regions_created):
    counts = [0 for i in range(number_of_regions_created)]
    for value in pixel_regions:
        counts[value] += 1
    if all(counts[i] >= 256 for i in range(number_of_regions_created)):
        return True


def shuffle(region_lists):
    for region_list in region_lists:
        length = len(region_list)
        for i in range(length):
            j = randrange(length)
            region_list[i], region_list[j] = region_list[j], region_list[i]


def measure(pixel):
    '''Return a single value roughly measuring the brightness.

    Not intended as an accurate measure, simply uses primes to prevent two
    different colours from having the same measure, so that an image with
    different colours of similar brightness will still be divided into
    regions.
    '''
    if type(pixel) is int:
        return pixel
    else:
        r, g, b = pixel[:3]
        return r * 2999 + g * 5869 + b * 1151


def swap_pixels(input_image, region_lists):
    pixels = list(input_image.getdata())
    for region in region_lists:
        for i in range(0, len(region) - 1, 2):
            pixels[region[i]], pixels[region[i+1]] = (pixels[region[i+1]],
                                                      pixels[region[i]])
    scrambled_image = Image.new(input_image.mode, input_image.size)
    scrambled_image.putdata(pixels)
    return scrambled_image


def save_output_image(output_image, full_path):
    head, tail = os.path.split(full_path)
    if tail[:10] == 'scrambled_':
        augmented_tail = 'rescued_' + tail[10:]
    else:
        augmented_tail = 'scrambled_' + tail
    save_filename = os.path.join(head, augmented_tail)
    output_image.save(save_filename)


if __name__ == '__main__':
    import sys
    arguments = sys.argv[1:]
    if arguments:
        scramble(*arguments[:3])
    else:
        print('\n'
              'Arguments:\n'
              '    input image          (required)\n'
              '    key image            (optional, default None)\n'
              '    number of regions    '
              '(optional maximum - will be as high as practical otherwise)\n')

JPEG görüntü yazma

.jpg dosyaları çok hızlı bir şekilde işleniyor, ancak çok sıcak çalıştırma pahasına. Bu, orijinal geri yüklendiğinde görüntüden sonra yanık bırakıyor:

jpg yakmak

Ancak cidden, kayıplı bir format bazı piksel renklerinin hafifçe değişmesine neden olur ve bu da kendi başına çıktıyı geçersiz kılar. Bir anahtar görüntü kullanıldığında ve piksellerin karıştırılması bölgelere sınırlandırıldığında, tüm bozulma gerçekleştiği bölgede tutulur ve ardından görüntü geri yüklendiğinde bu bölgeye eşit şekilde yayılır. Bölgeler arasındaki ortalama bozulma farkı, aralarında gözle görülür bir fark bırakır, bu nedenle karıştırma işleminde kullanılan bölgeler geri yüklenen görüntüde görünmeye devam eder.

Çırpmadan önce .png'ye (veya kayıpsız herhangi bir biçime) dönüştürmek, şifrelenmemiş görüntünün, yanma veya bozulma olmadan orijinaliyle aynı olmasını sağlar:

png yanık olmadan

Küçük detaylar

  • Bölgelere asgari boyutta 256 piksel uygulanır. Görüntünün çok küçük bölgelere bölünmesine izin verilirse, orijinal görüntü karıştırıldıktan sonra hala kısmen görünebilir.
  • Tek sayıda piksel içeren birden fazla bölge varsa, ikinci bölgeden bir piksel birinciye atanır vb. Bunun anlamı, tek sayıda piksel içeren yalnızca bir bölgenin olabileceği ve bu nedenle yalnızca bir pikselin şifrelenmemiş kalacağı anlamına gelir.
  • Bölge sayısını kısıtlayan üçüncü bir isteğe bağlı argüman vardır. Bunu 2'ye ayarlamak örneğin, iki tonlu karıştırılmış görüntü verecektir. İlgili görüntülere bağlı olarak bu daha iyi veya daha kötü görünebilir. Burada bir numara belirtilirse, görüntü yalnızca aynı numara kullanılarak tekrar geri yüklenebilir.
  • Orijinal görüntüdeki farklı renklerin sayısı, bölge sayısını da sınırlar. Orijinal resim iki ton ise, o zaman ana resim veya üçüncü argüman ne olursa olsun, yalnızca en fazla 2 bölge olabilir.

2
+1 Alkış! Bunu belli belirsiz düşündüm, ancak uygulanması çok zordu.
edc65

1
Bu harika. Bir giriş yaptım, ancak kilit resim özelliği nedeniyle sizinkini daha çok seviyorum.
Todd Lehman,

Bu iki görüntünün birbirine karşı nasıl göründüğünü merak ediyorum: lardlad.com/assets/wallpaper/simpsons1920.jpg ve blogs.nd.edu/oblation/files/2013/09/BreakingBad.jpg ( 720x450 boyutuna küçültülmüş veya ne olursa olsun mantıklı ve elbette JPEG yanmasını önlemek için PNG'ye önceden dönüştürülmüş).
Todd Lehman,

2
@ToddLehman benim algoritmam kendi tersi olma zorunluluğu ile sınırlıdır. Bir görüntüyü bir başkasına benzetmek için karıştırmakta gerçekten ilginç yaklaşımlar görmek istiyorsanız , Mona Lisa'nın paletindeki Amerikan Gotiklerine bakmalısınız . Bu programlardan bazıları bahsettiğiniz resimlerle harika şeyler yapar.
trichoplax

2
Anahtar görüntü özelliği bu baş ve omuzları diğerlerinin üzerine koyar.
Jack Aidley

33

İşte bir değişiklik için rastgele olmayan bir dönüşüm

  1. Tüm çift sütunları sola, tüm tek sütunları sağa koy.
  2. tekrar nxkere
  3. satırlar için aynı şeyi nykez

Dönüşüm neredeyse kendi kendine terstir, dönüşümü toplam size_xkez (x yönünde) tekrarlayarak orijinal görüntüyü döndürür. Tam matematiği anlamadım, ancak tamsayı katlarını kullanmak int(log_2(size_x))en küçük hayalet görüntülerle en iyi karıştırmayı sağlar

karıştırılmış dağlar görüntü tanımını buraya girin

from numpy import *
from pylab import imread, imsave

def imshuffle(im, nx=0, ny=0):
    for i in range(nx):
        im = concatenate((im[:,0::2], im[:,1::2]), axis=1)
    for i in range(ny):
        im = concatenate((im[0::2,:], im[1::2,:]), axis=0)
    return im

im1 = imread('circles.png')
im2 = imread('mountain.jpg')

imsave('s_circles.png', imshuffle(im1, 7,7))
imsave('s_mountain.jpg', imshuffle(im2, 8,9))

Bu, 20 adımdaki ilk adımların nasıl göründüğüdür (nx = ny, farklı çözünürlüklerin etkisine dikkat edin). görüntü tanımını buraya girin


7
Bu gerçekten harika bir algoritma. Ve Lena Söderberg fotoğrafını kullandığın için tamamen bonus kazanmalısın. :)
Todd Lehman,

Her zaman Lena upvote

24

Mathematica

Bu oldukça basit. 5 * nPixelsRasgele koordinat çiftleri seçerim ve bu iki pikseli değiştiririm (bu da resmi tamamen gizler). Şifresini çözmek için aynısını tersten yaparım. Tabii ki, her iki adımda da aynı koordinat çiftlerini elde etmek için PRNG'yi tohumlamam gerekiyor.

scramble[image_] := Module[
   {data, h, w, temp},
   data = ImageData@image;
   {h, w} = Most@Dimensions@data;
   SeedRandom[42];
   (
      temp = data[[#[[1]], #[[2]]]];
      data[[#[[1]], #[[2]]]] = data[[#2[[1]], #2[[2]]]];
      data[[#2[[1]], #2[[2]]]] = temp;
      ) & @@@
    Partition[
     Transpose@{RandomInteger[h - 1, 10*h*w] + 1, 
       RandomInteger[w - 1, 10*h*w] + 1}, 2];
   Image@data
   ];
unscramble[image_] := Module[
   {data, h, w, temp},
   data = ImageData@image;
   {h, w} = Most@Dimensions@data;
   SeedRandom[42];
   (
      temp = data[[#[[1]], #[[2]]]];
      data[[#[[1]], #[[2]]]] = data[[#2[[1]], #2[[2]]]];
      data[[#2[[1]], #2[[2]]]] = temp;
      ) & @@@
    Reverse@
     Partition[
      Transpose@{RandomInteger[h - 1, 10*h*w] + 1, 
        RandomInteger[w - 1, 10*h*w] + 1}, 2];
   Image@data
   ];

İki fonksiyonları arasındaki tek fark Reverse@içinde unscramble. Her iki işlev de gerçek bir görüntü nesnesi alır. Bunları aşağıdaki gibi kullanabilirsiniz:

in = Import["D:\\Development\\CodeGolf\\image-scrambler\\circles.png"]
scr = scramble[im]
out = unscramble[scr]

outve inaynıdır. İşte neye scrbenziyor:

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


4
Harika! Tek sorun PRNG'yi kendiniz yapmak için daha güvenli olmasıdır, çünkü eğer bir süre sonra Mathematica PRNG algoritmasını değiştirmeyi düşünüyorsa, bu eski şifreli görüntülerin kodunu çözmez!
Somnium

1
Güzel. Permute ve FindPermutation ile aynı sonucu elde edebilmelisiniz.
DavidC

Anladığımdan emin değilim. İstediğiniz kesin permütasyonu bir döngü listesi olarak girebilirsiniz.
DavidC

@DavidCarraher Hm, ilginç. FindPermutationYine de kullanmak için orijinal müsaadeyi hatırlamak zorunda kalmaz mıyım ?
Martin Ender

Ya da belki kullanılabilecek bir şey {c, a, b}[[{2, 3, 1}]]?
Somnium

22

C # (Simetrik Algoritma için + Bonus)

Bu, xböyle bir şey bulmak x^2 == 1 mod (number of pixels in image)ve ardından her bir pikselin dizinini çarparak xyeni konumunu bulmak için çarparak çalışır . Bu, bir görüntüyü karıştırmak ve deşifre etmek için aynı algoritmayı kullanmanıza izin verir.

using System.Drawing;
using System.IO;
using System.Numerics;

namespace RearrangePixels
{
    class Program
    {
        static void Main(string[] args)
        {
            foreach (var arg in args)
                ScrambleUnscramble(arg);
        }

        static void ScrambleUnscramble(string fileName)
        {
            using (var origImage = new Bitmap(fileName))
            using (var newImage = new Bitmap(origImage))
            {
                BigInteger totalPixels = origImage.Width * origImage.Height;
                BigInteger modSquare = GetSquareRootOf1(totalPixels);
                for (var x = 0; x < origImage.Width; x++)
                {
                    for (var y = 0; y < origImage.Height; y++)
                    {
                        var newNum = modSquare * GetPixelNumber(new Point(x, y), origImage.Size) % totalPixels;
                        var newPoint = GetPoint(newNum, origImage.Size);
                        newImage.SetPixel(newPoint.X, newPoint.Y, origImage.GetPixel(x, y));
                    }
                }
                newImage.Save("scrambled-" + Path.GetFileName(fileName));
            }
        }

        static BigInteger GetPixelNumber(Point point, Size totalSize)
        {
            return totalSize.Width * point.Y + point.X;
        }

        static Point GetPoint(BigInteger pixelNumber, Size totalSize)
        {
            return new Point((int)(pixelNumber % totalSize.Width), (int)(pixelNumber / totalSize.Width));
        }

        static BigInteger GetSquareRootOf1(BigInteger modulo)
        {
            for (var i = (BigInteger)2; i < modulo - 1; i++)
            {
                if ((i * i) % modulo == 1)
                    return i;
            }
            return modulo - 1;
        }
    }
}

ilk test görüntüsü, şifreli

ikinci test görüntüsü, şifreli


1
Zeki biri) Her zaman bu uyum denklemine bir çözüm olacak mı?
Somnium

1
@ user2992539 Her zaman önemsiz çözümler, 1(orijinal resim) ve modulo-1(ters / ters resim) olacak. Sayıların çoğu önemsiz olmayan çözümlere sahip, ancak bazı istisnalar var, öyle görünüyor . (asal çarpanlara ayırma ile ilgili modulo)
Tim S.

Anladığım kadarıyla önemsiz çözümler, bir öncekine benzer bir imaja yol açar.
Somnium

Doğru: 1Orijinal resim üretir ve -1çıkışlar örneğin imgur.com/EiE6VW2
Tim S.

19

C #, kendi kendine ters, rasgelelik yok

Orijinal görüntünün gücü iki olan boyutlar varsa, her satır ve sütun, örneğin 256 genişliğinde bir görüntü için ters bit desenine sahip satır ve sütunla değiştirilir, daha sonra satır 0x2D ile değiştirilir. Diğer boyutlardaki görüntüler 2'nin güçleri olan dikdörtgenlere bölünmüştür.

namespace CodeGolf
{
    class Program
    {
        static void Main(string[] args)
        {
            foreach (var arg in args)
                Scramble(arg);
        }

        static void Scramble(string fileName)
        {
            using (var origImage = new System.Drawing.Bitmap(fileName))
            using (var tmpImage = new System.Drawing.Bitmap(origImage))
            {
                {
                    int x = origImage.Width;
                    while (x > 0) {
                       int xbit = x & -x;
                        do {
                            x--;
                            var xalt = BitReverse(x, xbit);
                            for (int y = 0; y < origImage.Height; y++)
                                tmpImage.SetPixel(xalt, y, origImage.GetPixel(x, y));
                        } while ((x & (xbit - 1)) != 0);
                    }
                }
                {
                    int y = origImage.Height;
                    while (y > 0) {
                        int ybit = y & -y;
                        do {
                            y--;
                            var yalt = BitReverse(y, ybit);
                            for (int x = 0; x < origImage.Width; x++)
                                origImage.SetPixel(x, yalt, tmpImage.GetPixel(x, y));
                        } while ((y & (ybit - 1)) != 0);
                    } 
                }
                origImage.Save(System.IO.Path.GetFileNameWithoutExtension(fileName) + "-scrambled.png");
            }
        }

        static int BitReverse(int n, int bit)
        {
            if (bit < 4)
                return n;
            int r = n & ~(bit - 1);
            int tmp = 1;
            while (bit > 1) {
                bit >>= 1;
                if ((n & bit) != 0)
                    r |= tmp;
                tmp <<= 1;
            }
            return r;
        }
    }
}

İlk resim:

Şifreli ilk görüntü

İkinci resim:

Şifreli ikinci görüntü


2
Bunun "ekose" çıktısını beğendim.
Brian Rogers

14

C #

Çırpma ve çözme için aynı yöntem. Bunu geliştirmek için önerileri takdir ediyorum.

using System;
using System.Drawing;
using System.Linq;

public class Program
{
    public static Bitmap Scramble(Bitmap bmp)
    {
        var res = new Bitmap(bmp);
        var r = new Random(1);

        // Making lists of even and odd numbers and shuffling them
        // They contain numbers between 0 and picture.Width (or picture.Height)
        var rX = Enumerable.Range(0, bmp.Width / 2).Select(x => x * 2).OrderBy(x => r.Next()).ToList();
        var rrX = rX.Select(x => x + 1).OrderBy(x => r.Next()).ToList();
        var rY = Enumerable.Range(0, bmp.Height / 2).Select(x => x * 2).OrderBy(x => r.Next()).ToList();
        var rrY = rY.Select(x => x + 1).OrderBy(x => r.Next()).ToList();

        for (int y = 0; y < bmp.Height; y++)
        {
            for (int x = 0; x < rX.Count; x++)
            {
                // Swapping pixels in a row using lists rX and rrX
                res.SetPixel(rrX[x], y, bmp.GetPixel(rX[x], y));
                res.SetPixel(rX[x], y, bmp.GetPixel(rrX[x], y));
            }
        }
        for (int x = 0; x < bmp.Width; x++)
        {
            for (int y = 0; y < rY.Count; y++)
            {
                // Swapping pixels in a column using sets rY and rrY
                var px = res.GetPixel(x, rrY[y]);
                res.SetPixel(x, rrY[y], res.GetPixel(x, rY[y]));
                res.SetPixel(x, rY[y], px);
            }
        }

        return res;
    }
}

Psychedelic plaid ile sonuçlanır İlk İkinci


Bunun bazı çizgili desenleri olması güzel)
Somnium

1
Lütfen 2 resmi değiştirebilir misiniz? Soruda dağ görüntüsü ilk önce.
AL,

1
Algoritmanın kısa bir açıklamasını ekler misiniz?
trichoplax

14

Python 2 (kendi kendine ters, rastgele değil, içeriğe duyarlı)

Bu "en az tanınan" için hiçbir ödül kazanmaz, ancak belki de "ilginç" olarak puan alabilir. :-)

Bağlam duyarlı bir şey yapmak istedim, piksellerin karıştırılması aslında görüntünün kendisine bağlı.

Fikir oldukça basit: Tüm pikselleri, pikselin renginden türetilmiş bir rasgele değere göre sıralayın ve ardından o listedeki ilk pikselin konumlarını sonuncuyla, ikincisini ikinciyle ve benzeriyle değiştirin.

Ne yazık ki bu basit yaklaşımda aynı renkteki piksellerle ilgili bir sorun var, bu yüzden onu tersine çevirmek için programım biraz daha karmaşıklaştı ...

from PIL import Image

img = Image.open('1.png', 'r')
pixels = img.load()
size_x, size_y = img.size

def f(colour):
    r,g,b = colour[:3]
    return (abs(r-128)+abs(g-128)+abs(b-128))//128

pixel_list = [(x,y,f(pixels[x,y])) for x in xrange(size_x) for y in xrange(size_y)]
pixel_list.sort(key=lambda x: x[2])
print "sorted"

colours = {}
for p in pixel_list:
    if p[2] in colours:
        colours[p[2]] += 1
    else:
        colours[p[2]] = 1
print "counted"

for n in set(colours.itervalues()):
    pixel_group = [p for p in pixel_list if colours[p[2]]==n]
    N = len(temp_list)
    for p1, p2 in zip(pixel_group[:N//2], pixel_group[-1:-N//2:-1]):
        pixels[p1[0],p1[1]], pixels[p2[0],p2[1]] = pixels[p2[0],p2[1]], pixels[p1[0],p1[1]]
print "swapped"

img.save('1scrambled.png')
print "saved"

Sonuç bu: (Abs (R-128) + abs (G-128) + abs (B-128)) // 128 (Abs (R-128) + abs (G-128) + abs (B-128)) // 128

Karma işlevini değiştirerek oldukça farklı sonuçlar elde edebilirsiniz f:

  • r-g-b:

    rgb

  • r+g/2.**8+b/2.**16:

    , r + g / in2. ** 8 + B / 2. ** 16

  • math.sin(r+g*2**8+b*2**16):

    Math.sin (r + g * 2 ** 8 + b * 2 ** 16)

  • (r+g+b)//600:

    (R + g + b) // 600

  • 0:

    0


3
VAOV! Bu harika !!! İyi iş!
Todd Lehman,

1
Bu şimdiye kadarki en ilginç olanı. İyi iş!
bebe

12

Mathematica (+ bonus)

Bu, renk kanallarını daraltır ve görüntüyü uzun bir veri listesi olarak karıştırır. Sonuç, daha az farkedilir bir karıştırılmış versiyondur çünkü orijinal ile aynı renk dağılımına sahip değildir (çünkü bu veriler de karıştırılmıştır). Bu ikinci karıştırılmış görüntüde en belirgin olanıdır, ancak yakından bakarsanız ilkinde de aynı etkiyi görürsünüz. İşlev kendi tersidir.

Kanal başına karıştığı için bunun geçerli olamayacağı yönünde bir yorum yapıldı. Olması gerektiğini düşünüyorum, ama önemli bir şey değil. Tüm pikselleri (kanal başına değil) karıştırmak için gereken tek değişiklik :) olarak değiştirmek Flatten @ xolacaktır.Flatten[x, 1]

ClearAll @ f;

f @ x_ := 
  With[
    {r = SeedRandom[Times @@ Dimensions @ x], f = Flatten @ x},
    ArrayReshape[
      Permute[f, Cycles @ Partition[RandomSample @ Range @ Length @ f, 2]],
      Dimensions @ x]]

açıklama

f2 boyutlu bir dizi alan bir işlevi tanımlar x. İşlev, görüntünün boyutlarının ürününü rastgele bir tohum olarak kullanır ve ardından diziyi 1 boyutlu bir listeye düzleştirir f(yerel olarak gölgeli). Daha sonra, biçim listesi oluşturan bir uzunluğu 2 (bu nedenle, örneğin, bir parça halinde bölmeler bunu rastgele, bu listeyi değiştiren permütasyon kodunun değiştirilmesini boyutları her ikisi de tek ise (son numarayı bırakarak) ve sonra da değiştiren permütasyon kodunun değiştirilmesini de değerleri değiştirerek her alt listede belirtilen konumlar yeni yaratıldı ve sonunda izin verilen listeyi orijinal boyutlarına geri şekillendiriyor, çünkü görüntü boyutlarını daraltmanın yanı sıra{1, 2, ... n}nf{{1, 2}, {3, 4}, ...}fxFlattenkomutu ayrıca kanal verilerini her bir pikselde daraltır. İşlev kendi tersidir, çünkü çevrimler her biri yalnızca iki piksel içerir.

kullanım

img1=Import@"http://i.stack.imgur.com/2C2TY.jpg"//ImageData;
img2=Import@"http://i.stack.imgur.com/B5TbK.png"//ImageData;

f @ img1 // Image

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

f @ f @ img1 // Image

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

f @ img2 // Image

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

f @ f @ img2 // Image

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

İşte kullanıyor Flatten[x, 1].

g@x_ := With[{r = SeedRandom[Times @@ Dimensions @ x], f = Flatten[x, 1]}, 
  ArrayReshape[
   Permute[f, Cycles@Partition[RandomSample@Range@Length@f, 2]], 
   Dimensions@x]]

g@img2 // Image

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


1
Tahminime göre, bu ölçütleri karşılamıyor, çünkü piksel ölçeğinden küçük bir değerde değişiyor.
trichoplax

1
Bunun geçerli bir cevap olduğunu sanmıyorum, ama gerçekten hoşuma gitti. Büyüleyici bir twist, bu yüzden yine de +1 ...
trichoplax

1
@githubphagocyte Güncelleştirmeye bakın :)
mfvonh

Harika - Yine +1’e ulaştım ama elbette iki kez
yapamam

1
@githubphagocyte Oh doğru, kısa sözdiziminin tuhaf olabileceğini unutuyorum. Evet. f @ f @ img1 // Imageis (tam sözdiziminde)Image[f[f[img1]]]
mfvonh

10

Matlab (+ bonus)

Temel olarak iki pikselin konumunu rastgele değiştiriyorum ve değiştirilen her pikseli tekrar etiketlemiyorum. Aynı şifre 'şifre çözme' için tekrar kullanılabilir çünkü her seferinde rastgele sayı üretecini sıfırlarım. Bu, neredeyse tüm pikseller değiştirilene kadar yapılır (bu yüzden adım boyutu 2'den büyüktür)

EDIT: Martin Büttner'in benzer bir yaklaşım kullandığını gördüm - fikri kopyalamayı düşünmedim - cevapları olmadığında kodumu yazmaya başladım, bunun için üzgünüm. Ben hala sürümümün farklı fikirler kullandığını düşünüyorum =) (Ve eğer rastgele iki koordinatın seçili olduğu bitlere bakarsanız algoritmam çok daha yetersizdir)

Görüntüler

1 2

kod

img = imread('shuffle_image2.bmp');
s = size(img)
rand('seed',0)
map = zeros(s(1),s(2));
for i = 1:2.1:s(1)*s(2) %can use much time if stepsize is 2 since then every pixel has to be exchanged
    while true %find two unswitched pixels
        a = floor(rand(1,2) .* [s(1),s(2)] + [1,1]);
        b = floor(rand(1,2) .* [s(1),s(2)] + [1,1]);
        if map(a(1),a(2)) == 0 && map(b(1),b(2)) == 0
            break
        end
    end
    %switch
    map(a(1),a(2)) = 1;
    map(b(1),b(2)) = 1;
    t = img(a(1),a(2),:);
    img(a(1),a(2),:) = img(b(1),b(2),:);
    img(b(1),b(2),:) = t;
end
image(img)
imwrite(img,'output2.png')

Tamamen anlamıyorum, şifreli görüntüye ikinci kez uygulanan kodunuz şifresini çözecek mi?
Somnium

2
Tam olarak: Her seferinde tam olarak iki piksel değiş tokuş edilir ve tüm süreç boyunca tekrar değiştirilmez. 'Rastgele' sayılar her iki kez tamamen aynı olduğundan (rastgele sayı üretecinin sıfırlanmasından dolayı), piksel çiftleri geri alınacaktır. (RNG her zaman bir sonrakini üretmek için önceki üretilen sayıya güvenir, umarım bu açıktır.)
kusur

1
Ha, oldu aslında benim ilk fikir, ama çalışmak almak zorunda kaldı çünkü o zaman ben emin her piksel yalnızca bir kez takas edilir hale getirmek için rahatsız olamazdı. : D + 1!
Martin Ender

3
@ user2992539 Eh kontrol Octave matlab için güzel opensource alternatiftir ve oktav doğrudan matlab kod% 99 çalıştırabilirsiniz.
kusur

2
Resimlerinize gerçekten çok sert bakarsanız, girişten bir miktar yapı görmeye devam edersiniz (bu, tüm piksellerin taşınmamasından kaynaklanmaktadır). Seçim algoritmanızı O (∞) yerine O (1) 'de çalışacak şekilde değiştirdiyseniz, bunu düzeltebilirsiniz. ;)
Martin Ender

10

Mathematica-Çırpmak için bir permütasyon ve deşifre etmek için tersini kullanın.

Jpg görüntüsü, üç boyutlu bir {r,g,b}piksel renkleri dizisidir . (3 boyut, piksel kümesini satır, sütun ve renge göre yapılandırır). {r,g,b}Üçlüler listesine düzleştirilebilir , daha sonra "bilinen" bir döngü listesine göre izin verilir ve nihayet orijinal boyutların bir dizisine yeniden birleştirilir. Sonuç şifreli bir görüntüdür.

Şifresini çözmek, şifreli görüntüyü alır ve döngü listesinin tersi ile işler. Çıktıları, evet, orijinal görüntü.

Dolayısıyla, tek bir işlev (mevcut durumda scramble), görüntüdeki pikselleri çözmenin yanı sıra görüntüyü deşifre etmeye yarar.

Bir tohum numarasıyla birlikte bir resim girilir (Rastgele sayı üreticisinin karıştırmak ve çözmek için aynı durumda olmasını sağlamak için). Ters, parametresi Yanlış ise, işlev karıştırılır. Doğru olduğunda işlev çözülemez.


karıştırmak

Pikseller düzleştirilir ve rastgele bir döngü listesi oluşturulur. İzin, düzleştirilmiş listedeki piksellerin konumlarını değiştirmek için döngüleri kullanır.

deşifre etmek

Aynı fonksiyon, scrambleşifresini çözmek için kullanılır. Ancak döngü listesinin sırası tersine çevrilir.

scramble[img_,s_,reverse_:False,imgSize_:300]:=
  Module[{i=ImageData[img],input,r},input=Flatten[i,1];SeedRandom[s];
  r=RandomSample@Range[Length[input]];Image[ArrayReshape[Permute[input,
  Cycles[{Evaluate@If[reverse,Reverse@r,r]}]],Dimensions[i]],ImageSize->imgSize]]

Örnekler

Aynı tohum (37), karıştırmak ve çözmek için kullanılır.

Bu dağın karışık görüntüsünü oluşturur. Aşağıdaki resim şifreliMount değişkeninin dağ manzarasının gerçek görüntüsü ile değiştirilebileceğini göstermektedir.

scrambledMount=scramble[mountain, 37, True]

mount1


Şimdi tersini işletiyoruz; şifreliMount girilir ve orijinal resim kurtarılır.

 scramble[scrambledMount, 37, True]

mount2


Daireler için aynı şey:

circles1


 scramble[scrambledCircles, 37, True]

circles2


Bir görüntünün nasıl 3 boyutlu bir dizi olabileceğini göremiyorum.
edc65

1
@ edc65, Satırlar x Sütunlar x Renkler. Dağ görüntüsü 422 sıra ile 3 sütun 800 sütun. Dizi düzleştirilirse, 1012800 adet veriyi tek boyutlu bir dizi, yani bir liste olarak verir.
DavidC,

@ edc65 Renkleri rgb üçlü olarak yeniden düzenlemek için Permute kullanıldığını eklemeliyim. Bunu daha fazla düzleştirmedim, çünkü herhangi bir pikselin renkleri listesinde herhangi bir değişiklik yapmak istemiyordum. Eğer rgb bilgisini, {r, g, b} bir eleman olarak düşünürseniz, 2B diziden bahsediyoruz. Bu şekilde bakıldığında, dile getirdiğiniz soruyu ortaya koymak mantıklı geliyor (Resim nasıl 3 boyutlu bir dizi olabilir?). Aslında, rgb öğelerinin başka bir boyut eklediği gerçeğini göz ardı ederek, bir görüntüyü 2B dizi olarak görmek daha normal olabilir.
DavidC

10

piton

Bu bulmacayı sevdim, ilginç görünüyordu ve resme uygulamak için sarılmış ve Hareket işleviyle geldim.

wraped

Resmi bir metin olarak (soldan sağa, yukarı ve aşağı) okudum ve bir salyangoz kabuğu olarak yazdım.

Bu fonksiyon döngüseldir: örneğin N = f ^ (n) (x) = x, örneğin 4 * 2 için, f (f (f (f (x)))) = x

hareket

Rastgele bir sayı alıyorum ve her bir sütunu ve ligini ondan hareket ettiriyorum.

kod

# Opening and creating pictures
img = Image.open("/home/faquarl/Bureau/unnamed.png")
PM1 = img.load()
(w,h) = img.size
img2 = Image.new( 'RGBA', (w,h), "black") 
PM2 = img2.load()
img3 = Image.new( 'RGBA', (w,h), "black") 
PM3 = img3.load()

# Rotation
k = 0
_i=w-1
_j=h-1
_currentColMin = 0
_currentColMax = w-1
_currentLigMin = 0
_currentLigMax = h-1
_etat = 0
for i in range(w):
    for j in range(h):
        PM2[_i,_j]=PM1[i,j]
        if _etat==0:
            if _currentColMax == _currentColMin:
                _j -= 1
                _etat = 2
            else:
                _etat = 1
                _i -= 1
        elif _etat==1:
            _i -= 1
            if _j == _currentLigMax and _i == _currentColMin:
                _etat = 2
        elif _etat==2:
            _j -= 1
            _currentLigMax -= 1
            if _j == _currentLigMin and _i == _currentColMin:
                _etat = 5
            else:
                _etat = 3
        elif _etat==3:
            _j -= 1
            if _j == _currentLigMin and _i == _currentColMin:
                _etat = 4
        elif _etat==4:
            _i += 1
            _currentColMin += 1
            if _j == _currentLigMin and _i == _currentColMax:
                _etat = 7
            else:
                _etat = 5
        elif _etat==5:
            _i += 1
            if _j == _currentLigMin and _i == _currentColMax:
                _etat = 6
        elif _etat==6:
            _j += 1
            _currentLigMin += 1
            if _j == _currentLigMax and _i == _currentColMax:
                _etat = 1
            else:
                _etat = 7
        elif _etat==7:
            _j += 1
            if _j == _currentLigMax and _i == _currentColMax:
                _etat = 8
        elif _etat==8:
            _i -= 1
            _currentColMax -= 1
            if _j == _currentLigMax and _i == _currentColMin:
                _etat = 3
            else:
                _etat = 1
        k += 1
        if k == w * h:
            i = w
            j = h
# Movement
if w>h:z=w
else:z=h
rand.seed(z)
a=rand.randint(0,h)
for i in range(w):
  for j in range(h):
  if i%2==0:
    PM3[(i+a)%w,(j+a)%h]=PM2[i,j]
  else:
    PM3[(i-a)%w,(j-a)%h]=PM2[i,j]
# Rotate Again

Resimler

İlk rotasyon: görüntü tanımını buraya girin

sonra permütasyon: görüntü tanımını buraya girin

Ve son dönüşte: görüntü tanımını buraya girin

Diğer örnek gelince: görüntü tanımını buraya girin


2
Orijinal görüntüyü nasıl geri yüklersiniz?
trichoplax

Sadece rotasyon ise, belli bir süre yapabilirim (boyuta bağlı). Bununla birlikte, eğer izinlerim olsaydı, döngüsel olup olmadığından emin değilim, bu yüzden sadece değiştiren ikinci bir işleve sahibim; PM2 [_i, _j] = PM1 [i, j] PM2 [i, j] = PM1 [ _i, _j] ve PM3 [(i + a)% w, (j + a)% h] = PM2 [i, j], PM3 [(ia)% w, (ja)% h] = PM2 [i, j]. Bu iki çizgiyi değiştirmeden yapmanın bir yolunu arıyorum
Faquarl

8

VB.NET (+ bonus)

Bu onun yerine kusurun fikrini kullanır, ancak bu farklı değişim ve kontrol algoritmalarını kullanır. Program aynı şekilde kodlar ve kodları çözer.

Imports System

Module Module1

    Sub swap(ByVal b As Drawing.Bitmap, ByVal i As Integer, ByVal j As Integer)
        Dim c1 As Drawing.Color = b.GetPixel(i Mod b.Width, i \ b.Width)
        Dim c2 As Drawing.Color = b.GetPixel(j Mod b.Width, j \ b.Width)
        b.SetPixel(i Mod b.Width, i \ b.Width, c2)
        b.SetPixel(j Mod b.Width, j \ b.Width, c1)
    End Sub

    Sub Main(ByVal args() As String)
        For Each a In args
            Dim f As New IO.FileStream(a, IO.FileMode.Open)
            Dim b As New Drawing.Bitmap(f)
            f.Close()
            Dim sz As Integer = b.Width * b.Height - 1
            Dim w(sz) As Boolean
            Dim r As New Random(666)
            Dim u As Integer, j As Integer = 0
            Do While j < sz
                Do
                    u = r.Next(0, sz)
                Loop While w(u)
                ' swap
                swap(b, j, u)
                w(j) = True
                w(u) = True
                Do
                    j += 1
                Loop While j < sz AndAlso w(j)
            Loop
            b.Save(IO.Path.ChangeExtension(a, "png"), Drawing.Imaging.ImageFormat.Png)
            Console.WriteLine("Done!")
        Next
    End Sub

End Module

Çıkış görüntüleri:


8

Bunun pikselleri değiştirmek üzere olduğu ve değiştirilmediği hatırlatıldıktan sonra, bunun için benim çözümüm:

şifreli: görüntü tanımını buraya girin

Geri yüklendi: görüntü tanımını buraya girin

Bu, piksel sırasını randomize ederek yapılır, ancak onu geri yükleyebilmek için randomizasyon sabittir. Bu, sabit bir tohum ile rastgele bir sahte rasgele kullanma kullanılarak yapılır ve hangi piksellerin değiştirileceğini açıklayan bir dizin listesi oluşturulur. Değişim aynı olacağından, aynı liste orijinal resmi geri yükler.

public class ImageScramble {

  public static void main(String[] args) throws IOException {
    if (args.length < 2) {
      System.err.println("Usage: ImageScramble <fileInput> <fileOutput>");
    } else {
      // load image
      final String extension = args[0].substring(args[0].lastIndexOf('.') + 1);
      final BufferedImage image = ImageIO.read(new File(args[0]));
      final int[] pixels = image.getRGB(0, 0, image.getWidth(), image.getHeight(), null, 0, image.getWidth());

      // create randomized swap list
      final ArrayList<Integer> indexes = IntStream.iterate(0, i -> i + 1).limit(pixels.length).collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
      Collections.shuffle(indexes, new Random(1337));

      // swap all pixels at index n with pixel at index n+1
      int tmp;
      for (int i = 0; i < indexes.size(); i += 2) {
        tmp = pixels[indexes.get(i)];
        pixels[indexes.get(i)] = pixels[indexes.get(i + 1)];
        pixels[indexes.get(i + 1)] = tmp;
      }

      // write image to disk
      final BufferedImage imageScrambled = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
      imageScrambled.setRGB(0, 0, imageScrambled.getWidth(), imageScrambled.getHeight(), pixels, 0, imageScrambled.getWidth());
      ImageIO.write(imageScrambled, extension, new File(args[1]));
    }
  }
}

Görüntü algoritmasının verileri değiştireceği için bu algoritmayı kayıplı bir sıkıştırma biçiminde kullanmanın aynı sonucu vermeyeceğini unutmayın. Bu PNG gibi herhangi bir kayıpsız codec ile iyi çalışması gerekir.


8

Mathematica

Bir yardımcı işlevi hve karıştırıcı işlevi scrambleşu şekilde tanımlarız :

h[l_List, n_Integer, k_Integer: 1] := 
  With[{ m = Partition[l, n, n, 1, 0] }, 
    Flatten[
      Riffle[
        RotateLeft[ m[[ ;; , {1} ]] , k ],
        m[[ ;; , 2;; ]]
      ], 1
    ] [[ ;; Length[l] ]]
  ];

scramble[img_Image, k_Integer] :=
  Module[{ list , cNum = 5 },
    Which[
      k > 0,    list = Prime@Range[cNum],
      k < 0,    list = Reverse@Prime@Range[cNum],
      True,     list = {}
    ];
    Image[
      Transpose[
        Fold[ h[ #1, #2, k ] &, #, list ] & /@
        Transpose[
          Fold[ h[#1, #2, k] &, #, list ] & /@ ImageData[img]
        ]
      ]
    ]
  ];

Bir görüntüyü yükledikten sonra görüntüyü karıştırmak için herhangi bir tamsayı scramble[img, k]olduğu kyeri çağırabilirsiniz . İle tekrar aramak -kdeşifre olur. (Eğer kbir 0, daha sonra bir değişiklik olmaz.) Tipik kgibi bir şey olması seçilmelidir 100oldukça şifreli bir görüntü verir,:

Örnek çıktı 1

Örnek çıktı 2


7

Matlab: Satır / Sütun Toplam Değişmezlerine Göre Satır ve Sütun Karıştırması

Bu eğlenceli bir bilmeceye benziyordu, bu yüzden onun hakkında düşündüm ve aşağıdaki işlevi gördüm. Dairesel kaydırma sırasında satır ve sütun piksel değeri toplamlarının değişmezliğine dayanır: satır / sütunun piksel değerlerinin toplamının toplamına göre her bir satır, ardından her sütunu kaydırır (vardiya değişkenindeki tüm sayı için bir uint8 varsayar) ). Bu, daha sonra her bir sütunun kaydırılmasıyla tersine çevrilebilir, ardından ters yönde toplam değerine göre sıraya koyulabilir.

Diğerleri kadar güzel değil, ama rastgele olmamasını ve görüntü tarafından tam olarak tanımlanmasını seviyorum - seçim parametreleri yok.

Her renk kanalını ayrı ayrı kaydırması için tasarladım, ancak ardından sadece tam pikselleri taşıma özelliğini gördüm.

function pic_scramble(input_filename)
i1=imread(input_filename);
figure;
subplot(1,3,1);imagesc(i1);title('Original','fontsize',20);

i2=i1;
for v=1:size(i1,1)
    i2(v,:,:)=circshift(i2(v,:,:),sum(sum(i2(v,:,:))),2);
end
for w=1:size(i2,2)
    i2(:,w,:)=circshift(i2(:,w,:),sum(sum(i2(:,w,:))),1);
end
subplot(1,3,2);imagesc(i2);title('Scrambled','fontsize',20);

i3=i2;
for w=1:size(i3,2)
    i3(:,w,:)=circshift(i3(:,w,:),-1*sum(sum(i3(:,w,:))),1);
end
for v=1:size(i3,1)
    i3(v,:,:)=circshift(i3(v,:,:),-1*sum(sum(i3(v,:,:))),2);
end
subplot(1,3,3);imagesc(i3);title('Recovered','fontsize',20);

İlk test görüntüsü Secont test resmi


6

Java

Bu program rastgele pikselleri değiştirir (piksel eşlemesine piksel oluşturur), ancak rastgele işlev yerine Math.sin () (tamsayı x) kullanır. Tamamen geri dönüşümlü. Test görüntüleri ile bazı desenler oluşturur.

Parametreler: tamsayı sayısı (geçiş sayısı, tersine çevrilecek negatif sayı, 0 hiçbir şey yapmaz), girdi büyüsü ve çıktı görüntüsü (aynı olabilir). Çıktı dosyası kayıpsız sıkıştırma kullanan biçimde olmalıdır.

1 geçiş: görüntü tanımını buraya girin görüntü tanımını buraya girin

100 geçiş (bunu yapmak birkaç dakika sürer): görüntü tanımını buraya girin görüntü tanımını buraya girin

Kod:

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class Test{

public static void main(String... args) {
    String in = "image.png";
    String out = in;
    int passes = 0;
    if (args.length < 1) {
        System.out.println("no paramem encryptimg, 1 pass, reading and saving image.png");
        System.out.println("Usage: pass a number. Negative - n passes of decryption, positive - n passes of encryption, 0 - do nothing");
    } else {
        passes = Integer.parseInt(args[0]);
        if (args.length > 1) {
            in = args[1];
        }
        if(args.length > 2){
            out = args[2];
        }
    }
    boolean encrypt = passes > 0;
    passes = Math.abs(passes);
    for (int a = 0; a < passes; a++) {
        BufferedImage img = null;
        try {
            img = ImageIO.read(new File(a == 0 ? in : out));
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }
        int pixels[][] = new int[img.getWidth()][img.getHeight()];
        int[][] newPixels = new int[img.getWidth()][img.getHeight()];
        for (int x = 0; x < pixels.length; x++) {
            for (int y = 0; y < pixels[x].length; y++) {
                pixels[x][y] = img.getRGB(x, y);
            }
        }
        int amount = img.getWidth() * img.getHeight();
        int[] list = new int[amount];
        for (int i = 0; i < amount; i++) {
            list[i] = i;
        }
        int[] mapping = new int[amount];
        for (int i = amount - 1; i >= 0; i--) {
            int num = (Math.abs((int) (Math.sin(i) * amount))) % (i + 1);
            mapping[i] = list[num];
            list[num] = list[i];
        }
        for (int xz = 0; xz < amount; xz++) {
            int x = xz % img.getWidth();
            int z = xz / img.getWidth();
            int xzMap = mapping[xz];
            int newX = xzMap % img.getWidth();
            int newZ = xzMap / img.getWidth();
            if (encrypt) {
                newPixels[x][z] = pixels[newX][newZ];
            } else {
                newPixels[newX][newZ] = pixels[x][z];
            }
        }
        BufferedImage newImg = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < pixels.length; x++) {
            for (int y = 0; y < pixels[x].length; y++) {
                newImg.setRGB(x, y, newPixels[x][y]);
            }
        }

        try {
            String[] s = out.split("\\.");
            ImageIO.write(newImg, s[s.length - 1],
                    new File(out));
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }
    }
}
}

6

Python 2.7 ile PIL

Partiye biraz geç kaldım, ancak görüntüleri ekose haline dönüştürmenin eğlenceli olacağını düşündüm. İlk olarak, sütunları sayı sayısının 4 katı yukarı veya aşağı kaydırırız (hatta aşağı sütunları, tek sıradaki sütunları yukarı). Daha sonra satırları satır sayısının 4 katı kadar sola veya sağa kaydırırız (hatta sola sütunlar, tek sütunlar sağa).

Sonuç oldukça Tartanca.

Tersine çevirmek için, tam tersi sırada bunları yapıyoruz ve tam tersi miktarda kayıyoruz.

kod

from PIL import Image

def slideColumn (pix, tpix, x, offset, height):
  for y in range(height):
    tpix[x,(offset+y)%height] = pix[x,y]

def slideRow (pix, tpix, y, offset, width):
  for x in range(width):
    tpix[(offset+x)%width,y] = pix[x,y]

def copyPixels (source, destination, width, height):
  for x in range(width):
    for y in range(height):
      destination[x,y]=source[x,y]

def shuffleHorizontal (img, tmpimg, factor, encoding):
  xsize,ysize = img.size
  pix = img.load()
  tpix = tmpimg.load()
  for y in range(ysize):
    offset = y*factor
    if y%2==0:
      offset = xsize-offset
    offset = (xsize + offset) % xsize
    if encoding:
      slideRow(pix,tpix,y,offset,xsize)
    else:
      slideRow(pix,tpix,y,-offset,xsize)
  copyPixels(tpix,pix,xsize,ysize)

def shuffleVertical (img, tmpimg, factor, encoding):
  xsize,ysize = img.size
  pix = img.load()
  tpix = tmpimg.load()
  for x in range(xsize):
    offset = x*factor
    if x%2==0:
      offset = ysize-offset
    offset = (ysize + offset) % ysize
    if encoding:
      slideColumn(pix,tpix,x,offset,ysize)
    else:
      slideColumn(pix,tpix,x,-offset,ysize)
  copyPixels(tpix,pix,xsize,ysize)


def plaidify (img):
  tmpimg = Image.new("RGB",img.size)
  shuffleVertical(img,tmpimg,4,True)
  shuffleHorizontal(img,tmpimg,4,True)

def deplaidify (img):
  tmpimg = Image.new("RGB",img.size)
  shuffleHorizontal(img,tmpimg,4,False)
  shuffleVertical(img,tmpimg,4,False)

Sonuçlar

Resim 1'deki ekose:

imlenen 1.jpg

Ekose form görüntüsü 2:

imlenen 2.png


2
Çok hoş! Köşegenleri 45 ° açıyla almak mümkün müdür?
Todd Lehman, 7

2
Ofset çizgilerini şu şekilde değiştirerek mümkündür: offset = x*xsize/ysize ve offset = y*ysize/xsize Ancak, maalesef görüntüyü de gerçekten gizlemiyor.
jrrl

5

Python (+ bonus) - piksellerin nüfuzu

Bu yöntemde, her piksel başka bir konuma yerleştirilir, diğer pikselin ilk konuma getirilmesi zorunluluğu vardır. Matematiksel olarak, döngü uzunluğu 2 olan bir permütasyondur. Bu nedenle, metot kendi tersidir.

Geçmişe bakıldığında, mfvonh'a çok benzer, ancak bu başvuru Python'da ve ben bu müsaadeyi kendim yapmak zorunda kaldım.

def scramble(I):
    result = np.zeros_like(I)
    size = I.shape[0:2]
    nb_pixels = size[0]*size[1]
    #Build permutation
    np.random.seed(0)
    random_indices = np.random.permutation( range(nb_pixels) )
    random_indices1 = random_indices[0:int(nb_pixels/2)]
    random_indices2 = random_indices[-1:-1-int(nb_pixels/2):-1]
    for c in range(3):
        Ic = I[:,:,c].flatten()
        Ic[ random_indices2 ] = Ic[random_indices1]
        Ic[ random_indices1 ] = I[:,:,c].flatten()[random_indices2]
        result[:,:,c] = Ic.reshape(size)
    return result

İlk test görüntüsü: İlk test görüntüsü İkinci test görüntüsü: İkinci test görüntüsü


5

Python 2.7 + PIL, Sürgülü Yapbozlardan İlham Alın

Sadece başka bir fikir vardı. Temel olarak, bu yöntem bir görüntüyü eşit boyutlu bloklara böler ve sonra sıralarını değiştirir. Yeni sipariş sabit bir tohumu temel aldığından, aynı tohumu kullanarak süreci tamamen geri almak mümkündür. Ayrıca, ayrıntı düzeyi adı verilen ek parametre ile farklı ve tanınmayan sonuçlar elde etmek mümkündür.

Sonuçlar:

orijinal

orijinal

Tanecik 16

16

Ayrıntı 13

13

Tanecik 10

10

Tanecik 3

3

Tanecik 2

2

Tanecik 1

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

orijinal

orijinal

Tanecik 16

16

Ayrıntı 13

13

Tanecik 10

10

Tanecik 3

3

Tanecik 2

2

Tanecik 1

1

Kod:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from PIL import Image
import random

def scramble_blocks(im,granularity,password,nshuffle):
    set_seed(password)
    width=im.size[0]
    height=im.size[1]

    block_width=find_block_dim(granularity,width)       #find the possible block dimensions
    block_height=find_block_dim(granularity,height)

    grid_width_dim=width/block_width                #dimension of the grid
    grid_height_dim=height/block_height

    nblocks=grid_width_dim*grid_height_dim          #number of blocks

    print "nblocks: ",nblocks," block width: ",block_width," block height: ",block_height
    print "image width: ",width," image height: ",height
    print "getting all the blocks ..."
    blocks=[]
    for n in xrange(nblocks): #get all the image blocks
        blocks+=[get_block(im,n,block_width,block_height)]

    print "shuffling ..."
    #shuffle the order of the blocks
    new_order=range(nblocks)
    for n in xrange(nshuffle):
        random.shuffle(new_order)

    print "building final image ..."
    new_image=im.copy()
    for n in xrange(nblocks):
        #define the target box where to paste the new block
        i=(n%grid_width_dim)*block_width                #i,j -> upper left point of the target image
        j=(n/grid_width_dim)*block_height
        box = (i,j,i+block_width,j+block_height)    

        #paste it   
        new_image.paste(blocks[new_order[n]],box)

    return new_image



#find the dimension(height or width) according to the desired granularity (a lower granularity small blocks)
def find_block_dim(granularity,dim):
    assert(granularity>0)
    candidate=0
    block_dim=1
    counter=0
    while counter!=granularity:         #while we dont achive the desired granularity
        candidate+=1
        while((dim%candidate)!=0):      
            candidate+=1
            if candidate>dim:
                counter=granularity-1
                break

        if candidate<=dim:
            block_dim=candidate         #save the current feasible lenght

        counter+=1

    assert(dim%block_dim==0 and block_dim<=dim)
    return block_dim

def unscramble_blocks(im,granularity,password,nshuffle):
    set_seed(password)
    width=im.size[0]
    height=im.size[1]

    block_width=find_block_dim(granularity,width)       #find the possible block dimensions
    block_height=find_block_dim(granularity,height)

    grid_width_dim=width/block_width                #dimension of the grid
    grid_height_dim=height/block_height

    nblocks=grid_width_dim*grid_height_dim          #number of blocks

    print "nblocks: ",nblocks," block width: ",block_width," block height: ",block_height
    print "getting all the blocks ..."
    blocks=[]
    for n in xrange(nblocks): #get all the image blocks
        blocks+=[get_block(im,n,block_width,block_height)]

    print "shuffling ..."
    #shuffle the order of the blocks
    new_order=range(nblocks)
    for n in xrange(nshuffle):
        random.shuffle(new_order)

    print "building final image ..."
    new_image=im.copy()
    for n in xrange(nblocks):
        #define the target box where to paste the new block
        i=(new_order[n]%grid_width_dim)*block_width             #i,j -> upper left point of the target image
        j=(new_order[n]/grid_width_dim)*block_height
        box = (i,j,i+block_width,j+block_height)    

        #paste it   
        new_image.paste(blocks[n],box)

    return new_image

#get a block of the image
def get_block(im,n,block_width,block_height):

    width=im.size[0]

    grid_width_dim=width/block_width                        #dimension of the grid

    i=(n%grid_width_dim)*block_width                        #i,j -> upper left point of the target block
    j=(n/grid_width_dim)*block_height

    box = (i,j,i+block_width,j+block_height)
    block_im = im.crop(box)
    return block_im

#set random seed based on the given password
def set_seed(password):
    passValue=0
    for ch in password:                 
        passValue=passValue+ord(ch)
    random.seed(passValue)


if __name__ == '__main__':

    filename="0RT8s.jpg"
    # filename="B5TbK.png"
    password="yOs0ZaKpiS"
    nshuffle=1
    granularity=1

    im=Image.open(filename)

    new_image=scramble_blocks(im,granularity,password,nshuffle)
    new_image.show()
    new_image.save(filename.split(".")[0]+"_puzzled.png")

    new_image=unscramble_blocks(new_image,granularity,password,nshuffle)
    new_image.save(filename.split(".")[0]+"_unpuzzled.png")
    new_image.show()

5

47

94 satır. Kodlama için 47, kod çözme için 47.

require 'chunky_png'
require_relative 'codegolf-35005_ref.rb'


REF = {:png => ref, :w => 1280, :h => 720}
REF[:pix] = REF[:png].to_rgb_stream.unpack('C*').each_slice(3).to_a
SEVENTH_PRIME = 4*7 - 4-7 - (4&7)
FORTY_SEVEN   = 4*7 + 4+7 + (4&7) + (4^7) + 7/4
THRESHOLD     = FORTY_SEVEN * SEVENTH_PRIME


class RNG
    @@m = 2**32
    @@r = 0.5*(Math.sqrt(5.0) - 1.0)
    def initialize(n=0)
        @cur = FORTY_SEVEN + n
    end
    def hash(seed)
        (@@m*((seed*@@r)%1)).floor
    end
    def _next(max)
        hash(@cur+=1) % max
    end
    def _prev(max)
        hash(@cur-=1) % max
    end        
    def advance(n)
        @cur += n
    end
    def state
        @cur
    end
    alias_method :rand, :_next
end


def load_png(file, resample_w = nil, resample_h = nil)
    png  = ChunkyPNG::Image.from_file(file)
    w    = resample_w || png.width
    h    = resample_h || png.height
    png.resample_nearest_neighbor!(w,h) if resample_w || resample_h
    pix  = png.to_rgb_stream.unpack('C*').each_slice(3).to_a
    return {:png => png, :w => w, :h => h, :pix => pix}
end


def make_png(img)
    rgb_stream = img[:pix].flatten.pack('C*')
    img[:png] = ChunkyPNG::Canvas.from_rgb_stream(img[:w],img[:h],rgb_stream)
    return img
end


def difference(pix_a,pix_b)
    (pix_a[0]+pix_a[1]+pix_a[2]-pix_b[0]-pix_b[1]-pix_b[2]).abs
end


def code(img, img_ref, mode)
    img_in  = load_png(img)
    pix_in  = img_in[:pix]
    pix_ref = img_ref[:pix]
    s = img_in[:w] * img_in[:h] 
    rng = RNG.new(mode==:enc ? 0 : FORTY_SEVEN*s+1)
    rand = mode == :enc ? rng.method(:_next) : rng.method(:_prev)
    s.times do
        FORTY_SEVEN.times do
            j = rand.call(s)
            i = rng.state % s
            diff_val = difference(pix_ref[i],pix_ref[j])
            if diff_val > THRESHOLD
               pix_in[i], pix_in[j] = pix_in[j], pix_in[i]
            end
        end
    end
    make_png(img_in)
end


case ARGV.shift
when 'enc'
    org, cod = ARGV
    encoded_image = code(org,REF,:enc)
    encoded_image[:png].save(cod)
when 'dec'
    org, cod = ARGV
    decoded_image = code(cod,REF,:dec)
    decoded_image[:png].save(org)
else
    puts '<original> <coded>'
    puts 'specify either <enc> or <dec>'
    puts "ruby #{$0} enc codegolf-35005_inp.png codegolf-35005_enc.png"
end

codegolf-35005_ref.rb

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

(jpg'ye dönüştürüldü)

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

(orijinal küçültülmüş)

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


3
Orijinal desenin bir kısmı bu çizgilerden görülebilir. Ancak buğulu pencerede bir parmakla çizdiğinizde benzer).
Somnium

2
... codegolf-35005_ref.rb için + 184426 bayt?
edc65

5

Bir tutam Grup Teorisi (+ bonus) ile

Bu yaklaşımda eşit sayıda toplam piksele sahip olduğumuzu varsayıyoruz. (Değilse, yalnızca bir pikseli yok sayarız) Öyleyse diğer yarıyla değiştirmek için piksellerin yarısını seçmemiz gerekir. Bunun için tüm pikselleri dizine 0kadar dizine alıyoruz 2N-1ve bu dizinleri döngüsel bir grup olarak görüyoruz .

Asallar arasında, pçok küçük ve çok büyük olmayan ve 2Ngrubumuzun sırasına göre bir sayı ararız . Bu araç g üretir grubumuza veya {k*g mod 2N | k=0,1,...,2N-1} = {0,1,...,2N-1}.

Bu yüzden , bir küme olarak ilk Nkatları gve diğer küme olarak kalan tüm bileşenleri seçeriz ve karşılık gelen piksel kümesini değiştiririz.

Eğer pdoğru yolu seçilir, ilk seti eşit tüm görüntü üzerinden dağıtılır.

İki test durumu:

Biraz konu dışı ama ilginç:

Test sırasında, onu (kayıpsız sıkıştırılmış) bir jpg'ye (kayıpsız olarak sıkıştırılmış bir png yerine) kaydedip ileri geri dönüşümü uygularsanız, sıkıştırma işleminin özelliklerini hemen hızla görüyorsanız, bu art arda iki düzenlemenin sonuçlarını gösterir. :

Gördüğünüz gibi, jpg sıkıştırma sonucu neredeyse siyah beyaz görünmesini sağlar!

clc;clear;
inputname = 'codegolf_rearrange_pixels2.png';
inputname = 'codegolf_rearrange_pixels2_swapped.png';
outputname = 'codegolf_rearrange_pixels2_swapped.png';

%read image
src = imread(inputname);

%separate into channels
red = src(:,:,1);
green = src(:,:,2);
blue = src(:,:,3);

Ntotal = numel(red(:));  %number of pixels
Nswap = floor(Ntotal/2); %how many pairs we can swap

%find big enough generator
factors = unique(factor(Ntotal));
possible_gen = primes(max(size(red)));
eliminated = setdiff(possible_gen,factors);
if mod(numel(eliminated),2)==0 %make length odd for median
    eliminated = [1,eliminated];
end
generator = median(eliminated);

%set up the swapping vectors
swapindices1 = 1+mod((1:Nswap)*generator, Ntotal);
swapindices2 = setdiff(1:Ntotal,swapindices1);
swapindices2 = swapindices2(1:numel(swapindices1)); %make sure both have the same length

%swap the pixels
red([swapindices1,swapindices2]) = red([swapindices2,swapindices1]);
green([swapindices1,swapindices2]) = green([swapindices2,swapindices1]);
blue([swapindices1,swapindices2]) = blue([swapindices2,swapindices1]);

%write and display
output = cat(3,red,green,blue);
imwrite(output,outputname);
subplot(2,1,1);
imshow(src)
subplot(2,1,2);
imshow(output);

4

JavaScript (+ bonus) - piksel bölme takas tekrarlayıcı

İşlev bir görüntü öğesini alır ve

  1. Pikselleri 8'e böler.
  2. Bir piksel grubunun tersinir takas yapar.
  3. Piksel grubu> = 8 ise değiş tokuş eder.
function E(el){
    var V=document.createElement('canvas')
    var W=V.width=el.width,H=V.height=el.height,C=V.getContext('2d')
    C.drawImage(el,0,0)
    var id=C.getImageData(0,0,W,H),D=id.data,L=D.length,i=L/4,A=[]
    for(;--i;)A[i]=i
    function S(A){
        var L=A.length,x=L>>3,y,t,i=0,s=[]
        if(L<8)return A
        for(;i<L;i+=x)s[i/x]=S(A.slice(i,i+x))
        for(i=4;--i;)y=[6,4,7,5,1,3,0,2][i],t=s[i],s[i]=s[y],s[y]=t
        s=[].concat.apply([],s)
        return s
    }
    var N=C.createImageData(W,H),d=N.data,A=S(A)
    for(var i=0;i<L;i++)d[i]=D[(A[i>>2]*4)+(i%4)]
    C.putImageData(N,0,0)
    el.src=C.canvas.toDataURL()
}

Dağlar Çemberler


4

Python 2.7 + PIL, Sütun / Satır Karıştırıcı

Bu yöntem, görüntünün satırlarını ve sütunlarını karıştırır. Boyutlardan sadece birini veya her ikisini de karıştırmak mümkündür. Ayrıca, yeni karıştırılmış satır / sütunun sırası bir parolaya dayanmaktadır. Ayrıca, başka bir olasılık, boyutları göz önünde bulundurmadan tüm resim dizisini karıştırmaktır.

Sonuçlar:

Resmin tamamı karıştırılıyor:

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

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

Sütunları karıştırmak:

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

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

Satırları karıştırmak:

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

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

Hem sütunları hem de satırları karıştırmak:

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

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

Ayrıca, görüntüye birkaç işlem uygulamaya çalıştım, ancak sonuçların sonuçları çok da farklı değildi, yalnızca şifresini çözmek için zorluk çekti.

Kod:

from PIL import Image
import random,copy

def scramble(im,columns,rows):
    pixels =list(im.getdata())

    newOrder=range(columns*rows)        
    random.shuffle(newOrder)            #shuffle

    newpixels=copy.deepcopy(pixels)
    for i in xrange(len(pixels)):
        newpixels[i]=pixels[newOrder[i]]

    im.putdata(newpixels)

def unscramble(im,columns,rows):
    pixels =list(im.getdata())

    newOrder=range(columns*rows)        
    random.shuffle(newOrder)            #unshuffle

    newpixels=copy.deepcopy(pixels)
    for i in xrange(len(pixels)):
        newpixels[newOrder[i]]=pixels[i]

    im.putdata(newpixels)

def scramble_columns(im,columns,rows):
    pixels =list(im.getdata())

    newOrder=range(columns)     
    random.shuffle(newOrder)            #shuffle

    newpixels=[]
    for i in xrange(rows):
        for j in xrange(columns):
            newpixels+=[pixels[i*columns+newOrder[j]]]

    im.putdata(newpixels)

def unscramble_columns(im,columns,rows):
    pixels =list(im.getdata())

    newOrder=range(columns)     
    random.shuffle(newOrder)            #shuffle

    newpixels=copy.deepcopy(pixels)
    for i in xrange(rows):
        for j in xrange(columns):
            newpixels[i*columns+newOrder[j]]=pixels[i*columns+j]

    im.putdata(newpixels)

def scramble_rows(im,columns,rows):
    pixels =list(im.getdata())

    newOrder=range(rows)        
    random.shuffle(newOrder)            #shuffle the order of pixels

    newpixels=copy.deepcopy(pixels)
    for j in xrange(columns):
        for i in xrange(rows):
            newpixels[i*columns+j]=pixels[columns*newOrder[i]+j]

    im.putdata(newpixels)

def unscramble_rows(im,columns,rows):
    pixels =list(im.getdata())

    newOrder=range(rows)        
    random.shuffle(newOrder)            #shuffle the order of pixels

    newpixels=copy.deepcopy(pixels)
    for j in xrange(columns):
        for i in xrange(rows):
            newpixels[columns*newOrder[i]+j]=pixels[i*columns+j]

    im.putdata(newpixels)


#set random seed based on the given password
def set_seed(password):
    passValue=0
    for ch in password:                 
        passValue=passValue+ord(ch)
    random.seed(passValue)

def encrypt(im,columns,rows,password):
    set_seed(password)
    # scramble(im,columns,rows)
    scramble_columns(im,columns,rows)
    scramble_rows(im,columns,rows)

def decrypt(im,columns,rows,password):
    set_seed(password)
    # unscramble(im,columns,rows)
    unscramble_columns(im,columns,rows)
    unscramble_rows(im,columns,rows)

if __name__ == '__main__':
    passwords=["yOs0ZaKpiS","NA7N3v57og","Nwu2T802mZ","6B2ec75nwu","FP78XHYGmn"]
    iterations=1
    filename="0RT8s.jpg"
    im=Image.open(filename)
    size=im.size
    columns=size[0]
    rows=size[1]

    for i in range(iterations):
        encrypt(im,columns,rows,passwords[i])
    im.save(filename.split(".")[0]+"_encrypted.jpg")

    for i in range(iterations):
        decrypt(im,columns,rows,passwords[iterations-i-1])
    im.save(filename.split(".")[0]+"_decrypted.jpg")

3

C # Winforms

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

Resim 2: görüntü tanımını buraya girin

Kaynak kodu:

class Program
{
    public static void codec(String src, String trg, bool enc)
    {
        Bitmap bmp = new Bitmap(src);
        Bitmap dst = new Bitmap(bmp.Width, bmp.Height);

        List<Point> points = new List<Point>();
        for (int y = 0; y < bmp.Height; y++)
            for (int x = 0; x < bmp.Width; x++)
                points.Add(new Point(x, y));

        for (int y = 0; y < bmp.Height; y++)
        {
            for (int x = 0; x < bmp.Width; x++)
            {
                int py = Convert.ToInt32(y + 45 * Math.Sin(2.0 * Math.PI * x / 128.0));
                int px = Convert.ToInt32(x + 45 * Math.Sin(2.0 * Math.PI * y / 128.0));

                px = px < 0 ? 0 : px;
                py = py < 0 ? 0 : py;
                px = px >= bmp.Width ? bmp.Width - 1 : px;
                py = py >= bmp.Height ? bmp.Height - 1 : py;

                int srcIndex = x + y * bmp.Width;
                int dstIndex = px + py * bmp.Width;

                Point temp = points[srcIndex];
                points[srcIndex] = points[dstIndex];
                points[dstIndex] = temp;
            }
        }

        for (int y = 0; y < bmp.Height; y++)
        {
            for (int x = 0; x < bmp.Width; x++)
            {
                Point p = points[x + y * bmp.Width];
                if (enc)
                    dst.SetPixel(x, y, bmp.GetPixel(p.X, p.Y));
                else
                    dst.SetPixel(p.X, p.Y, bmp.GetPixel(x, y));
            }
        }

        dst.Save(trg);
    }


    static void Main(string[] args)
    {
        // encode
        codec(@"c:\shared\test.png", @"c:\shared\test_enc.png", true);

        // decode
        codec(@"c:\shared\test_enc.png", @"c:\shared\test_dec.png", false);
    }
}

1

Python 3.6 + pypng

Oluk / Master Shuffle

#!/usr/bin/env python3.6

import argparse
import itertools

import png

def read_image(filename):
    img = png.Reader(filename)
    w, h, data, meta = img.asRGB8()
    return w, h, list(itertools.chain.from_iterable(
        [
            (row[i], row[i+1], row[i+2])
            for i in range(0, len(row), 3)
        ]
        for row in data
    ))

def riffle(img, n=2):
    l = len(img)
    base_size = l // n
    big_groups = l % n
    base_indices = [0]
    for i in range(1, n):
        base_indices.append(base_indices[-1] + base_size + int(i <= big_groups))
    result = []
    for i in range(0, base_size):
        for b in base_indices:
            result.append(img[b + i])
    for i in range(big_groups):
        result.append(img[base_indices[i] + base_size])
    return result

def master(img, n=2):
    parts = [[] for _ in range(n)]
    for i, pixel in enumerate(img):
        parts[i % n].append(pixel)
    return list(itertools.chain.from_iterable(parts))

def main():
    parser = argparse.ArgumentParser()

    parser.add_argument('infile')
    parser.add_argument('outfile')
    parser.add_argument('-r', '--reverse', action='store_true')
    parser.add_argument('-i', '--iterations', type=int, default=1)
    parser.add_argument('-n', '--groupsize', type=int, default=2)
    parser.add_argument('-c', '--complex', nargs='+', type=int)

    args = parser.parse_args()

    w, h, img = read_image(args.infile)

    if args.complex:
        if any(-1 <= n <= 1 for n in args.complex):
            parser.error("Complex keys must use group sizes of at least 2")
        if args.reverse:
            args.complex = [
                -n for n in reversed(args.complex)
            ]
        for n in args.complex:
            if n > 1:
                img = riffle(img, n)
            elif n < -1:
                img = master(img, -n)
    elif args.reverse:
        for _ in range(args.iterations):
            img = master(img, args.groupsize)
    else:
        for _ in range(args.iterations):
            img = riffle(img, args.groupsize)

    writer = png.Writer(w, h)
    with open(args.outfile, 'wb') as f:
        writer.write_array(f, list(itertools.chain.from_iterable(img)))


if __name__ == '__main__':
    main()

Algoritmam, oluk karıştırmasını bir yöne ve diğerini de ana karıştırmaya uygular (çünkü ikisi birbirinin tersidir), her biri birkaç yinelemedir, ancak her biri yalnızca iki yerine herhangi bir sayıda alt gruba ayrılmak için genelleştirilir. Bunun etkisi, görüntüde oluklanma ve ana karışmaların kesin sırasını bilmeden geri yüklenmeyeceğinden, çok yinelemeli bir permütasyon anahtarı yapabilmenizdir. Bir dizi, tam sayı dizisi ile belirlenebilir; olukları temsil eden pozitif sayılar ve üstatları temsil eden negatif sayılar.

Manzarayı [3, -5, 2, 13, -7] tuşuyla karıştırdım:

Manzara 3-5 2 13 -7

İlginçtir ki, orijinal görüntüden bazı eserleri bırakılan [3, -5] 'ten bazı ilginç şeyler oluyor:

Manzara 3-5

Anahtar [2, 3, 5, 7, -11, 13, -17] tuşlarıyla karıştırılmış soyut desen:

Daireler 2 3 5 7 -11 13 -17

Anahtarda yalnızca bir parametre yanlışsa, unshuffle görüntüyü geri yüklemez:

Kötü karışıklık

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.