/// <summary>
        /// Generate puzzle pieces from image.
        /// </summary>
        /// <param name="NoOfPiecesInRow"></param>
        /// <param name="NoOfPiecesInCol"></param>
        /// <param name="Image"></param>
        /// <param name="JointMaskImage">Mask image for joints. Null value means default circular joints.</param>
        /// <returns></returns>
        private SPieceMetaData[,] GenerateJigsawPieces(Texture2D Image, Texture2D[] JointMaskImage, out Texture2D CreatedImageMask, int NoOfPiecesInRow, int NoOfPiecesInCol)
        {

#region "Argument Error Checking"

            if (NoOfPiecesInRow < 2)
            {
                throw new System.ArgumentOutOfRangeException("NoOfPiecesInRow", "Argument should be greater then 1");
            }
            else if (NoOfPiecesInCol < 2)
            {
                throw new System.ArgumentOutOfRangeException("NoOfPiecesInCol", "Argument should be greater then 1");
            }
            else if (Image == null)
            {
                throw new System.ArgumentNullException("No texture2d assigned to this class");
            }

#endregion

            
            Texture2D[,] PuzzlePieces = null;

            Color[][] _PuzzleImageMask = Texture2DToColorArr(Image);

            int PieceWidthWithoutJoint = 0;
            int PieceHeightWithoutJoint = 0;
            SPieceInfo[,] PiecesInformation = null;

            if (JointMaskImage == null || JointMaskImage.Length == 0)
            {
                Texture2D[] _maskImage = new Texture2D[1];
                _maskImage[0] = CreateCircularJointMaskImage();

                PiecesInformation = DrawCustomPieceJointsMask(ref _PuzzleImageMask, _maskImage, out PieceWidthWithoutJoint,
                    out PieceHeightWithoutJoint, Image.width, Image.height, NoOfPiecesInCol, NoOfPiecesInRow);

            }
            else
            {
                PiecesInformation = DrawCustomPieceJointsMask(ref _PuzzleImageMask, JointMaskImage,  out PieceWidthWithoutJoint,
                    out PieceHeightWithoutJoint,Image.width, Image.height, NoOfPiecesInCol, NoOfPiecesInRow);
            }

            
            _PieceWidthWithoutJoint = PieceWidthWithoutJoint;
            _PieceHeightWithoutJoint = PieceHeightWithoutJoint;


            CreatedImageMask = ColorArrToTexture2D(_PuzzleImageMask);

            Color[][] _PuzzleImage = Texture2DToColorArr(Image);
            PuzzlePieces = MaskToPieces(ref _PuzzleImage, _PuzzleImageMask, PieceWidthWithoutJoint, PieceHeightWithoutJoint,
                    Image.width, Image.height, NoOfPiecesInCol, NoOfPiecesInRow);

            _NoOfPiecesInRow = NoOfPiecesInRow;
            _NoOfPiecesInCol = NoOfPiecesInCol;


            //Return data for puzzle pieces
            SPieceMetaData[,] ResultData = new SPieceMetaData[NoOfPiecesInCol, NoOfPiecesInRow];
            for (int i = 0; i < NoOfPiecesInCol; i++)
            {
                for (int j = 0; j < NoOfPiecesInRow; j++)
                {
                    ResultData[i, j] = new SPieceMetaData(PiecesInformation[i, j], PuzzlePieces[i, j]);

                }
            }

            return ResultData;

        }
        /// <summary>
        /// Load data from stream of file for puzzle maker.
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        private bool LoadStreamData(System.IO.Stream stream)
        {
            System.IO.BinaryReader bReader = null;

            try
            {
                using (bReader = new System.IO.BinaryReader(stream))
                {
                    //Get secret number to check file intigrity
                    int secretNumber = bReader.ReadInt32();
                    if (secretNumber != 6640330)
                    {
                        bReader.Close();
                        Debug.LogError("Error reading file. Make sure this file is created with puzzle maker`s current version");
                        return false;
                    }

                    //Get basic variables data
                    _NoOfPiecesInRow = bReader.ReadInt32();
                    _NoOfPiecesInCol = bReader.ReadInt32();

                    _PieceWidthWithoutJoint = bReader.ReadInt32();
                    _PieceHeightWithoutJoint = bReader.ReadInt32();

                    ColorPieces = bReader.ReadBoolean();


#region "Retrieve basic images"


                    int lengthImageEncoded = bReader.ReadInt32();
                    byte[] imageEncoded = bReader.ReadBytes(lengthImageEncoded);
                    _Image = new Texture2D(100, 100);
                    _Image.LoadImage(imageEncoded);


                    int lengthBackgroundImageEncoded = bReader.ReadInt32();
                    byte[] createdBackgroundImageEncoded = bReader.ReadBytes(lengthBackgroundImageEncoded);
                    _CreatedBackgroundImage = new Texture2D(100, 100);
                    _CreatedBackgroundImage.LoadImage(createdBackgroundImageEncoded);

#endregion


#region "Retrieve joint mask array"

                    int lengthJointMaskArr = bReader.ReadInt32();
                    _JointMask = new Texture2D[lengthJointMaskArr];
                    for (int i = 0; i < lengthJointMaskArr; i++)
                    {
                        int TempLength = bReader.ReadInt32();

                        _JointMask[i] = new Texture2D(100, 100);
                        byte[] TempMaskArr = bReader.ReadBytes(TempLength);
                        _JointMask[i].LoadImage(TempMaskArr);
                    }

#endregion


#region "Retreive Pieces Metadata"

                    _CreatedImagePiecesData = new SPieceMetaData[_NoOfPiecesInCol, _NoOfPiecesInRow];

                    for (int RowTrav = 0; RowTrav < _NoOfPiecesInCol; RowTrav++)
                    {
                        for (int ColTrav = 0; ColTrav < _NoOfPiecesInRow; ColTrav++)
                        {
                            int pieceID = bReader.ReadInt32();

                            //Get joints info
                            int JointInfoLength = bReader.ReadInt32();
                            SPieceInfo TempSPieceInfo = new SPieceInfo(pieceID);

                            for (int i = 0; i < JointInfoLength; i++)
                            {
                                int jointType = bReader.ReadInt32();
                                int jointWidth = bReader.ReadInt32();
                                int jointHeight = bReader.ReadInt32();
                                int jointPosition = bReader.ReadInt32();


                                TempSPieceInfo.AddJoint(new SJointInfo((EJointType)jointType, (EJointPosition)jointPosition,
                                                        jointWidth, jointHeight));
                            }

                            //Get this piece image
                            int pieceImgArrLength = bReader.ReadInt32();
                            byte[] pieceTempArr = bReader.ReadBytes(pieceImgArrLength);
                            Texture2D pieceTempImage = new Texture2D(100, 100);
                            pieceTempImage.LoadImage(pieceTempArr);
                            pieceTempImage.wrapMode = TextureWrapMode.Clamp;

                            //Insert this piece data in list
                            _CreatedImagePiecesData[RowTrav, ColTrav] = new SPieceMetaData(TempSPieceInfo, pieceTempImage);

                        }
                    }

#endregion

                    bReader.Close();

                }
            }
            catch (System.Exception ex)
            {
                throw new System.Exception("Exception in load data 2: " + ex.Message);
                //Debug.LogError("Puzzle Maker LoadData Method: " + ex.Message);
            }

            return true;
        }