Example #1
0
        /// <summary>
        /// Imports the given <paramref name="rawBytes"/> as rgb image.
        /// </summary>
        /// <param name="rawBytes">The raw bytes to use for the image.</param>
        /// <param name="imageSize">Size of the resulting image.</param>
        /// <param name="fill">Pixel value used as a fill when no raw bytes are left.</param>
        /// <param name="rgbMode">Read-in mode of the rgb bytes.</param>
        /// <returns>Imported rgb image.</returns>
        public static Image ImportAsRGB(IEnumerable <byte> rawBytes, Size2D imageSize, byte fill, RGBMode rgbMode)
        {
            if (rawBytes == null)
            {
                throw new ArgumentNullException(nameof(rawBytes));
            }

            var queue = new Queue <byte>(rawBytes);
            var img   = new Image(imageSize, 3);

            if (rgbMode == RGBMode.RGBRGB)
            {
                ImportRGBAsRGBRGB(queue, img, fill);
            }
            else
            {
                ImportRGBAsRRGGBB(queue, img, fill);
            }

            return(img);
        }
        /// <summary>
        /// Generates a distance texture from the alpha channel of a source texture.
        /// </summary>
        /// <param name="source">
        /// Source texture. Alpha values of 1 are considered inside, values of 0 are considered outside, and any other values are considered
        /// to be on the edge. Must be readable.
        /// </param>
        /// <param name="destination">
        /// Destination texture. Must be the same size as the source texture. Must be readable.
        /// The texture change does not get applied automatically, you need to do that yourself.
        /// </param>
        /// <param name="maxInside">
        /// Maximum pixel distance measured inside the edge, resulting in an alpha value of 1.
        /// If set to or below 0, everything inside will have an alpha value of 1.
        /// </param>
        /// <param name="maxOutside">
        /// Maximum pixel distance measured outside the edge, resulting in an alpha value of 0.
        /// If set to or below 0, everything outside will have an alpha value of 0.
        /// </param>
        /// <param name="postProcessDistance">
        /// Pixel distance from the edge within which pixels will be post-processed using the edge gradient.
        /// </param>
        /// <param name="rgbMode">
        /// How to fill the destination texture's RGB channels.
        /// </param>
        public static void Generate(Texture2D source, Texture2D destination, float maxInside, float maxOutside, float postProcessDistance,
                                    RGBMode rgbMode)
        {
            if (source.height != destination.height || source.width != destination.width)
            {
                Debug.LogError("Source and destination textures must be the same size.");
                return;
            }
            string          sourcePath = AssetDatabase.GetAssetPath(source);
            TextureImporter importer   = AssetImporter.GetAtPath(sourcePath) as TextureImporter;

            if (importer != null && !importer.isReadable)
            {
                AssetDatabase.StartAssetEditing();
                importer.textureType = TextureImporterType.Default;
                importer.isReadable  = true;
                AssetDatabase.StopAssetEditing();
                AssetDatabase.ImportAsset(sourcePath);
            }
            try{
                source.GetPixel(0, 0);
            }
            catch {
                Debug.LogError("Source texture is not read/write enabled.");
                return;
            }
            try{
                destination.GetPixel(0, 0);
            }
            catch {
                Debug.LogError("Destination texture is not read/write enabled.");
                return;
            }

            width  = source.width;
            height = source.height;
            pixels = new Pixel[width, height];
            int   x, y;
            float scale;
            Color c = rgbMode == RGBMode.White ? Color.white : Color.black;

            for (y = 0; y < height; y++)
            {
                for (x = 0; x < width; x++)
                {
                    pixels[x, y] = new Pixel();
                }
            }
            if (maxInside > 0f)
            {
                for (y = 0; y < height; y++)
                {
                    for (x = 0; x < width; x++)
                    {
                        pixels[x, y].alpha = 1f - source.GetPixel(x, y).a;
                    }
                }
                ComputeEdgeGradients();
                GenerateDistanceTransform();
                if (postProcessDistance > 0f)
                {
                    PostProcess(postProcessDistance);
                }
                scale = 1f / maxInside;
                for (y = 0; y < height; y++)
                {
                    for (x = 0; x < width; x++)
                    {
                        c.a = Mathf.Clamp01(pixels[x, y].distance * scale);
                        destination.SetPixel(x, y, c);
                    }
                }
            }
            if (maxOutside > 0f)
            {
                for (y = 0; y < height; y++)
                {
                    for (x = 0; x < width; x++)
                    {
                        pixels[x, y].alpha = source.GetPixel(x, y).a;
                    }
                }
                ComputeEdgeGradients();
                GenerateDistanceTransform();
                if (postProcessDistance > 0f)
                {
                    PostProcess(postProcessDistance);
                }
                scale = 1f / maxOutside;
                if (maxInside > 0f)
                {
                    for (y = 0; y < height; y++)
                    {
                        for (x = 0; x < width; x++)
                        {
                            c.a = 0.5f + (destination.GetPixel(x, y).a - Mathf.Clamp01(pixels[x, y].distance * scale)) * 0.5f;
                            destination.SetPixel(x, y, c);
                        }
                    }
                }
                else
                {
                    for (y = 0; y < height; y++)
                    {
                        for (x = 0; x < width; x++)
                        {
                            c.a = Mathf.Clamp01(1f - pixels[x, y].distance * scale);
                            destination.SetPixel(x, y, c);
                        }
                    }
                }
            }

            if (rgbMode == RGBMode.Distance)
            {
                for (y = 0; y < height; y++)
                {
                    for (x = 0; x < width; x++)
                    {
                        c   = destination.GetPixel(x, y);
                        c.r = c.a;
                        c.g = c.a;
                        c.b = c.a;
                        destination.SetPixel(x, y, c);
                    }
                }
            }
            else if (rgbMode == RGBMode.Source)
            {
                for (y = 0; y < height; y++)
                {
                    for (x = 0; x < width; x++)
                    {
                        c   = source.GetPixel(x, y);
                        c.a = destination.GetPixel(x, y).a;
                        destination.SetPixel(x, y, c);
                    }
                }
            }
            pixels = null;
        }
	/// <summary>
	/// Generates a distance texture from the alpha channel of a source texture.
	/// </summary>
	/// <param name="source">
	/// Source texture. Alpha values of 1 are considered inside, values of 0 are considered outside, and any other values are considered
	/// to be on the edge. Must be readable.
	/// </param>
	/// <param name="destination">
	/// Destination texture. Must be the same size as the source texture. Must be readable.
	/// The texture change does not get applied automatically, you need to do that yourself.
	/// </param>
	/// <param name="maxInside">
	/// Maximum pixel distance measured inside the edge, resulting in an alpha value of 1.
	/// If set to or below 0, everything inside will have an alpha value of 1.
	/// </param>
	/// <param name="maxOutside">
	/// Maximum pixel distance measured outside the edge, resulting in an alpha value of 0.
	/// If set to or below 0, everything outside will have an alpha value of 0.
	/// </param>
	/// <param name="postProcessDistance">
	/// Pixel distance from the edge within which pixels will be post-processed using the edge gradient.
	/// </param>
	/// <param name="rgbMode">
	/// How to fill the destination texture's RGB channels.
	/// </param>
	public static void Generate (Texture2D source, Texture2D destination, float maxInside, float maxOutside, float postProcessDistance,
	                             RGBMode rgbMode) {
		if(source.height != destination.height || source.width != destination.width){
			Debug.LogError("Source and destination textures must be the same size.");
			return;
		}
		try{
			source.GetPixel(0, 0);
		}
		catch{
			Debug.LogError("Source texture is not read/write enabled.");
			return;
		}
		try{
			destination.GetPixel(0, 0);
		}
		catch{
			Debug.LogError("Destination texture is not read/write enabled.");
			return;
		}
		
		width = source.width;
		height = source.height;
		pixels = new Pixel[width, height];
		int x, y;
		float scale;
		Color c = rgbMode == RGBMode.White ? Color.white : Color.black;
		for(y = 0; y < height; y++){
			for(x = 0; x < width; x++){
				pixels[x, y] = new Pixel();
			}
		}
		if(maxInside > 0f){
			for(y = 0; y < height; y++){
				for(x = 0; x < width; x++){
					pixels[x, y].alpha = 1f - source.GetPixel(x, y).a;
				}
			}
			ComputeEdgeGradients();
			GenerateDistanceTransform();
			if(postProcessDistance > 0f){
				PostProcess(postProcessDistance);
			}
			scale = 1f / maxInside;
			for(y = 0; y < height; y++){
				for(x = 0; x < width; x++){
					c.a = Mathf.Clamp01(pixels[x, y].distance * scale);
					destination.SetPixel(x, y, c);
				}
			}
		}
		if(maxOutside > 0f){
			for(y = 0; y < height; y++){
				for(x = 0; x < width; x++){
					pixels[x, y].alpha = source.GetPixel(x, y).a;
				}
			}
			ComputeEdgeGradients();
			GenerateDistanceTransform();
			if(postProcessDistance > 0f){
				PostProcess(postProcessDistance);
			}
			scale = 1f / maxOutside;
			if(maxInside > 0f){
				for(y = 0; y < height; y++){
					for(x = 0; x < width; x++){
						c.a = 0.5f + (destination.GetPixel(x, y).a - Mathf.Clamp01(pixels[x, y].distance * scale)) * 0.5f;
						destination.SetPixel(x, y, c);
					}
				}
			}
			else{
				for(y = 0; y < height; y++){
					for(x = 0; x < width; x++){
						c.a = Mathf.Clamp01(1f - pixels[x, y].distance * scale);
						destination.SetPixel(x, y, c);
					}
				}
			}
		}
		
		if(rgbMode == RGBMode.Distance){
			for(y = 0; y < height; y++){
				for(x = 0; x < width; x++){
					c = destination.GetPixel(x, y);
					c.r = c.a;
					c.g = c.a;
					c.b = c.a;
					destination.SetPixel(x, y, c);
				}
			}
		}
		else if(rgbMode == RGBMode.Source){
			for(y = 0; y < height; y++){
				for(x = 0; x < width; x++){
					c = source.GetPixel(x, y);
					c.a = destination.GetPixel(x, y).a;
					destination.SetPixel(x, y, c);
				}
			}
		}
		pixels = null;
	}