/// <summary> /// Takes an array of bytes representing RGB pixels and outputs the data into a Color32 array. /// </summary> public static void BytesToColor32(TiffMetadata metadata, byte[] bytes, Color32[] buf) { short samplesPerPixel = metadata.SamplesPerPixel; if (bytes.Length % samplesPerPixel != 0) { // TODO Throw exception return; } int length = bytes.Length / samplesPerPixel; if (buf.Length != length) { // TODO Throw exception return; } // 8 bits per color sample, this will include blank and UNIT formats. if (metadata.BitsPerSample == 8) { Color32 color; for (int i = 0; i < length; i++) { // Greyscale image (1 sample per pixel). if (samplesPerPixel == 1) { color = new Color32(bytes[i], bytes[i], bytes[i], 255); } // Color image, either with alpha (4 samples per pixel) or no alpha (3 samples per pixel). else { int j = i * samplesPerPixel; color = new Color32(bytes[j], bytes[j + 1], bytes[j + 2], (samplesPerPixel == 4) ? bytes[j + 3] : (byte)255); } buf[i] = color; } } // TODO Add support for sample rates other than 8 bits per sample. }
public TiffImage(string filePath) { // Store and check the filepath. _filePath = filePath; if (string.IsNullOrEmpty(_filePath)) { throw new FileNotSpecifiedException("No file specified."); } // Attempt to open the TIFF image file. _tiff = Tiff.Open(_filePath, "r"); if (_tiff == null) { throw new FileReadException($"Error reading TIFF from {filePath}"); } // Extract the necessary metadata if the image was loaded sucessfully. Metadata = new TiffMetadata(_tiff); PrintInfo(); }
public static T ToColorImage <T>(TiffImage tiff) where T : ColorImage { TiffMetadata metadata = tiff.Metadata; // Check image format. if (metadata.BitsPerSample != 8) { // TODO Add support for sample rates other than 8 bits per sample. throw new Exception($"Conversion from {metadata.BitsPerSample} bits per sample to color image is currently not supported"); } // Create an Image object to store the result. T result = (T)Activator.CreateInstance(typeof(T), metadata.Width, metadata.Height); // Tiled encoding... if (metadata.Tiled) { Vector2Int tilesAcrossImage = new Vector2Int( Mathf.CeilToInt(metadata.Width / (float)metadata.TileWidth), Mathf.CeilToInt(metadata.Height / (float)metadata.TileHeight) ); // Byte array for buffering the bytes read from each tile. byte[] tileBytes = new byte[metadata.TileSize]; // Color32 array for buffering the intensity values of each tile. Color32[] values = new Color32[metadata.TileWidth * metadata.TileHeight]; // Iterate through each tile. for (int ty = 0; ty < tilesAcrossImage.y; ty++) { // The y-coordinate of the tile's top row of pixels on the image. int y = ty * metadata.TileHeight; for (int tx = 0; tx < tilesAcrossImage.x; tx++) { // The x-coordinate of the tile's left column of pixels on the image. int x = tx * metadata.TileWidth; // Read bytes from tile and convert them to pixel values. tiff.ReadTile(tileBytes, 0, x, y, 0, 0); TiffUtils.BytesToColor32(metadata, tileBytes, values); // Iterate through the intensity values in the tile. for (int i = 0; i < values.Length; i++) { // Calculate the x and y coordinate relative to the tile // based on the index of the pixel within the tile. Vector2Int tilePixel = ImageUtils.IndexToCoordinates(i, metadata.TileWidth); // Update the Image object with the pixel value. result.SetPixel(tilePixel.x + x, tilePixel.y + y, values[i]); } } } } // Scanline encoding... else { // Byte array for buffering the bytes read from each scanline. byte[] scanlineBytes = new byte[metadata.ScanlineSize]; // Color32 array for buffering the intensity values of each pixels in a scanline. Color32[] values = new Color32[metadata.Width]; // Iterate through all the scanlines. for (int y = 0; y < metadata.Height; y++) { // Read bytes from scanline and convert them to pixel values. tiff.ReadScanline(scanlineBytes, y); TiffUtils.BytesToColor32(metadata, scanlineBytes, values); // Iterate through all the pixel values in the scanline. for (int x = 0; x < metadata.Width; x++) { // Update the Image object with the pixel value. result.SetPixel(x, y, values[x]); } } } return(result); }
public static IntensityImage ToIntensityImage(TiffImage tiff) { TiffMetadata metadata = tiff.Metadata; // Check image format. if (metadata.SamplesPerPixel != 1) { throw new Exception("Color source cannot be converted into intensity image. Use ToRGBAImage() instead."); } // Create an Image object to store the result. IntensityImage result = new IntensityImage(metadata.Width, metadata.Height); // Tiled encoding... if (metadata.Tiled) { Vector2Int tilesAcrossImage = new Vector2Int( Mathf.CeilToInt(metadata.Width / (float)metadata.TileWidth), Mathf.CeilToInt(metadata.Height / (float)metadata.TileHeight) ); // Byte array for buffering the bytes read from each tile. byte[] tileBytes = new byte[metadata.TileSize]; // Float array for buffering the intensity values of each tile. float[] values = new float[metadata.TileWidth * metadata.TileHeight]; // Iterate through each tile. for (int ty = 0; ty < tilesAcrossImage.y; ty++) { // The y-coordinate of the tile's top row of pixels on the image. int y = ty * metadata.TileHeight; for (int tx = 0; tx < tilesAcrossImage.x; tx++) { // The x-coordinate of the tile's left column of pixels on the image. int x = tx * metadata.TileWidth; // Read bytes from tile and convert them to pixel values. tiff.ReadTile(tileBytes, 0, x, y, 0, 0); TiffUtils.BytesToFloat(tileBytes, values); // Iterate through the intensity values in the tile. for (int i = 0; i < values.Length; i++) { // Calculate the x and y coordinate relative to the tile // based on the index of the pixel within the tile. Vector2Int tilePixel = ImageUtils.IndexToCoordinates(i, metadata.TileWidth); // Update the Image object with the pixel value. result.SetPixel(tilePixel.x + x, tilePixel.y + y, values[i]); } } } } // Scanline encoding... else { // Byte array for buffering the bytes read from each scanline. byte[] scanlineBytes = new byte[metadata.ScanlineSize]; // Float array for buffering the intensity values of each pixels in a scanline. float[] values = new float[metadata.Width]; // Iterate through all the scanlines. for (int y = 0; y < metadata.Height; y++) { // Read bytes from scanline and convert them to pixel values. tiff.ReadScanline(scanlineBytes, y); TiffUtils.BytesToFloat(scanlineBytes, values); // Iterate through all the pixel values in the scanline. for (int x = 0; x < metadata.Width; x++) { // Update the Image object with the pixel value. result.SetPixel(x, y, values[x]); } } } return(result); }