3

i was asked to do a program that takes an image, reads the bitmap data and than randomizes the image.

I tried the easy way, spliting the "string" on every " " and than shuffling that, but the image goes corrupt, any idea on how to do this?

I would do this on cocoa, actionscript 3 , js or php.

Basicly as long as i can use this on a mac, my client is happy :)

  • The concept is basically where you take the original bitmap and cut it up into an imaginary grid of say 10x10 blocks. Then you use a loop to run over the cells and create a new Bitmap that will sample a given cell. At the end of this process you will have a bunch of bitmaps that together make up your original, which you can move around separately and rearrange. – Marty Jun 20 '13 at 23:21
  • oh.. just like that flipping tile game we used to play as a child. It´s not as easy as i thought, but still pretty straightforward, ill trow myself at the code now =) thank you – Ricardo Cerqueira Jun 20 '13 at 23:57
  • If you run into trouble, update your question with the code you ended up with and let me know - I'll be happy to help you out from there. – Marty Jun 21 '13 at 00:02
  • 1
    thank you mate, but no need now :) i already managed to split an image into tiles, now i just need to make them go random, im doing it with actionscript3, and tomorrow i'll finish the code. thank you for your help :) – Ricardo Cerqueira Jun 21 '13 at 00:25
  • Be sure to post the solution as an answer to this question to help visitors in the future. – Marty Jun 21 '13 at 00:31
  • i will as soon as its done :) – Ricardo Cerqueira Jun 21 '13 at 08:46

2 Answers2

0

The solution in javascript for shuffling the image tile by tile: http://fiddle.jshell.net/upgradellc/53wKG/show/ edit: http://jsfiddle.net/upgradellc/53wKG/

  /* Script copyright Max @ www.upgradeyour.com - if it is used or modified, this message must remain intact! */
            $( document ).ready( function() {
                var imgData1 = 'img_url_or_base64';
                new ImageShuffler( imgData1, 3 );
                new ImageShuffler( imgData1, 5 );
                new ImageShuffler( imgData1, 10 );
            } );
            function ImageShuffler( imgUrl, numberOfSquares, elementToAddTo ) {
                var that = this;
                this.url = imgUrl;
                this.numberOfSquares = numberOfSquares;
                this.elementToAddTo = elementToAddTo || $( 'body' );
                this.holder = $( '<div></div>' ).appendTo( $( this.elementToAddTo ) )[0];
                this.c1 = $( '<canvas></canvas>' ).appendTo( $( this.holder ) )[0];
                this.c2 = $( '<canvas></canvas>' ).appendTo( $( this.holder ) )[0];
                this.img = $( '<img src="' + this.url + '">' ).prependTo( $( this.holder ) )[0];
                this.img.onload = function() {
                    that.doShuffleImage()
                };
            }
            ImageShuffler.prototype.doShuffleImage = function() {
                this.widthOfSquares = Math.ceil( this.img.width / this.numberOfSquares );
                this.heightOfSquares = Math.ceil( this.img.height / this.numberOfSquares );
                var extrax = (this.img.width - this.widthOfSquares * this.numberOfSquares);
                var extray = (this.img.height - this.heightOfSquares * this.numberOfSquares);
                var width = this.removeExtraPixels( this.img.width, extrax, this.widthOfSquares );
                var height = this.removeExtraPixels( this.img.height, extray, this.heightOfSquares );
                this.c1.width = this.c2.width = width;
                this.c1.height = this.c2.height = height;

                this.c1c = this.c1.getContext( '2d' );
                this.c2c = this.c2.getContext( '2d' );
                this.c1c.drawImage( this.img, 0, 0, this.img.width, this.img.height );
                var tlc = this.c1c.getImageData( this.img.width - 1, this.img.height - 1, 1, 1 ).data;
                this.c1c.fillStyle = "rgb(" + tlc[0] + "," + tlc[1] + "," + tlc[2] + ");";
                this.c1c.fillRect( 0, 0, this.c1.width, this.c1.height );
                this.c1c.drawImage( this.img, 0, 0, this.img.width, this.img.height );
                this.shuffleAll();
            };
            ImageShuffler.prototype.shuffleAll = function() {
                this.c2c.putImageData( this.c1c.getImageData( 0, 0, this.c1.width, this.c1.height ), 0, 0 );
                //this.c1c.getImageData( 0, 0, this.img.width, this.img.height );
                var timesToShuffle = Math.pow( this.numberOfSquares, 2 );
                for( var count = 0; count < timesToShuffle; count++ ) {
                    p1 = {x: rand( this.c2.width, this.widthOfSquares ), y: rand( this.c2.height, this.heightOfSquares )};
                    p2 = {x: rand( this.c2.width, this.widthOfSquares ), y: rand( this.c2.height, this.heightOfSquares )};
                    if( p1.x + this.widthOfSquares < this.c2.width ) {
                        this.swapTile( p1.x, p1.y, p2.x, p2.y );
                    }
                }
            };
            ImageShuffler.prototype.swapTile = function( x1, y1, x2, y2 ) {
                tile1 = this.c2c.getImageData( x1, y1, this.widthOfSquares, this.heightOfSquares );
                tile2 = this.c2c.getImageData( x2, y2, this.widthOfSquares, this.heightOfSquares );
                this.c2c.putImageData( tile1, x2, y2 );
                this.c2c.putImageData( tile2, x1, y1 );
            };

            ImageShuffler.prototype.removeExtraPixels = function( currentLength, extraPixels, sizeOfSquare ) {
                if( extraPixels < 0 ) {
                    return currentLength + (-1 * extraPixels);
                }
                if( extraPixels > 0 ) {
                    return currentLength + sizeOfSquare - extraPixels;
                }
                return currentLength;
            };

            //returns a random number below max which is a multiple of increment
            function rand( max, increment ) {
                return Math.floor( Math.random() * Math.ceil( max / increment ) ) * increment;
            }

The solution in javascript for shuffling all of the pixels in the image: http://jsfiddle.net/upgradellc/2LJwH/1/

        /* Script copyright Max @ www.upgradeyour.com - if it is used or modified, this message must remain intact! */
        $( document ).ready( function() {
            var imgData1 = '/img/logo.png';
            new ImageShuffler( imgData1 );
        } );
        function ImageShuffler( imgUrl, elementToAddTo ) {
            var that = this;
            this.url = imgUrl;
            this.elementToAddTo = elementToAddTo || $( 'body' );
            this.holder = $( '<div></div>' ).appendTo( $( this.elementToAddTo ) )[0];
            console.log( this.holder );
            this.c1 = $( '<canvas></canvas>' ).appendTo( $( this.holder ) )[0];
            this.c2 = $( '<canvas></canvas>' ).appendTo( $( this.holder ) )[0];
            this.img = $( '<img src="' + this.url + '">' ).prependTo( $( this.holder ) )[0];
            this.img.onload = function() {
                that.doShuffleImage()
            };
        }
        ImageShuffler.prototype.doShuffleImage = function() {
            this.c1.width = this.c2.width = this.img.width;
            this.c1.height = this.c2.height = this.img.height;
            this.c1c = this.c1.getContext( '2d' );
            this.c2c = this.c2.getContext( '2d' );
            this.c1c.drawImage( this.img, 0, 0, this.img.width, this.img.height );
            this.c2c.putImageData( shuffleArray( this.c1c.getImageData( 0, 0, this.img.width, this.img.height ) ), 0, 0 );
        };

        //shuffles the data array
        function shuffleArray( arr ) {
            var length = arr.data.length;
            for( x = 0; x < length; x++ ) {
                var p1x = rand( length, 4 ), p2x = rand( length, 4 );
                var p1r = arr.data[p1x];
                var p1g = arr.data[p1x + 1];
                var p1b = arr.data[p1x + 2];
                var p1a = arr.data[p1x + 3];
                for( i = 0; i < 3; i++ ) {
                    arr.data[p2x + i] = arr.data[p1x + i];
                }
                arr.data[p2x] = p1r;
                arr.data[p2x + 1] = p1g;
                arr.data[p2x + 2] = p1b;
                arr.data[p2x + 3] = p1a;
            }
            return arr;
        }

        //returns a random number below max which is a multiple of increment
        function rand( max, increment ) {
            return Math.floor( Math.random() * Math.ceil( max / increment ) ) * increment;
        }
Max
  • 2,082
  • 19
  • 25
0

Here's my solution in ActionsScript 3, but the program is quite slow for large images so there's likely some optimization that could/should be done, although processing speed will still vary depending on the image size.

  1. Display original bitmap.
  2. Read and store bitmap data (pixel colors) from the original image into a 2D vector.
  3. Flatten the 2D vector to shuffle the data then restore the 2D vector.
  4. Draw and display bitmap data using shuffled data from 2D vector.

enter image description here

package 
{
    //Imports
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.display.StageScaleMode;
    import flash.display.StageAlign;

    //Class
    [SWF(width = "1150", height = "600", frameRate = "60", backgroundColor = "0x000000")]
    public class Main extends Sprite 
    {
        //Asset
        [Embed(source = "../assets/AdobeFlashLogo.png")]  // 500 x 500 pixels
        private var Image:Class;

        //Properties
        private var originalImage:Bitmap;

        //Constructor
        public function Main():void 
        {
            init();         
        }

        //Init
        private function init():void
        {
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;

            displayOriginalImage();
            displayShuffledImage();
        }

        //Display Original Image
        private function displayOriginalImage():void
        {
            originalImage = new Image() as Bitmap;          
            originalImage.x = originalImage.y = 50;

            addChild(originalImage);
        }

        //Display Shuffled Image
        private function displayShuffledImage():void
        {
            var pixelData:Vector.<Vector.<uint>> = shufflePixelData(getPixelData(originalImage));

            var shuffledImageData:BitmapData = new BitmapData(originalImage.width, originalImage.height);

            for (var i:uint = 0; i < originalImage.width; i++)
            {
                for (var j:uint = 0; j < originalImage.height; j++)
                {
                    shuffledImageData.setPixel32(i, j, pixelData[i][j]);
                }
            }

            var shuffledImage:Bitmap = new Bitmap(shuffledImageData);
            shuffledImage.x = originalImage.x + originalImage.width + 50;
            shuffledImage.y = originalImage.y;

            addChild(shuffledImage);
        }

        //Get Pixel Data
        private function getPixelData(image:Bitmap):Vector.<Vector.<uint>>
        {
            var result:Vector.<Vector.<uint>> = new Vector.<Vector.<uint>>;

            for (var i:uint = 0; i < originalImage.width; i++)
            {
                result[i] = new Vector.<uint>;

                for (var j:uint = 0; j < originalImage.height; j++)
                {
                    result[i][j] = originalImage.bitmapData.getPixel32(i, j);
                }
            }

            return result;
        }

        //Shuffle Pixel Data
        private function shufflePixelData(pixelData:Vector.<Vector.<uint>>):Vector.<Vector.<uint>>
        {
            var i:uint;
            var j:uint;

            var imageWidth:uint = pixelData.length;
            var imageHeight:uint = pixelData[0].length;

            var flatData:Vector.<uint> = new Vector.<uint>;

            for (i = 0; i < imageWidth; i++)
            {
                for (j = 0; j < imageHeight; j++)
                {
                    flatData.push(pixelData[i][j]);
                }
            }   

            var shuffledData:Vector.<uint> = new Vector.<uint>;
            var totalPixels:uint = imageWidth * imageHeight;
            var randomIndex:uint;

            for (i = 0; i < totalPixels; i++)
            {
                randomIndex = Math.random() * flatData.length;
                shuffledData.push(flatData.splice(randomIndex, 1)[0]);              
            }

            var result:Vector.<Vector.<uint>> = new Vector.<Vector.<uint>>

            for (i = 0; i < imageWidth; i++)
            {
                result[i] = new Vector.<uint>;

                for (j = 0; j < imageHeight; j++)
                {
                    result[i][j] = shuffledData.shift();
                }
            }

            return result;
        }
    }
}
Chunky Chunk
  • 16,553
  • 15
  • 84
  • 162