public async Task GenerateReducedResolutionLayerAsync(IRipperReducedResolutionGenerationReporter reporter, CancellationToken cancellationToken) { _fileReader = await TiffFileReader.OpenAsync(_stream, leaveOpen : true); TiffStreamOffset ifd = _fileReader.FirstImageFileDirectoryOffset; int width = _manifest.Width; int height = _manifest.Height; // Calculate layer count int outputTileSize = _options.OutputTileSize; int layerCount = 0; int calcWidth = width, calcHeight = height; while (Math.Min(calcWidth, calcHeight) > outputTileSize && Math.Min(calcWidth, calcHeight) >= 32) { calcWidth = calcWidth / 2; calcHeight = calcHeight / 2; layerCount++; } // Actually generate the layers int layer = 0; reporter?.ReportStartReducedResolutionGeneration(layerCount); while (Math.Min(width, height) > outputTileSize && Math.Min(width, height) >= 32) { cancellationToken.ThrowIfCancellationRequested(); ifd = await GenerateReducedResolutionLayerAsync(++layer, ifd, reporter, cancellationToken).ConfigureAwait(false); width = width / 2; height = height / 2; } reporter?.ReportCompleteReducedResolutionGeneration(layerCount); }
internal async Task <TiffStreamOffset> GenerateReducedResolutionLayerAsync(int layer, TiffStreamOffset ifdOffset, IRipperReducedResolutionGenerationReporter reporter, CancellationToken cancellationToken) { int outputTileSize = _options.OutputTileSize; int outputTileSize2 = 2 * outputTileSize; TiffImageFileDirectory ifd = await _fileReader.ReadImageFileDirectoryAsync(ifdOffset).ConfigureAwait(false); TiffImageDecoder image = await _fileReader.CreateImageDecoderAsync(ifd); int width = image.Width; int height = image.Height; int tiffRowCount = (width / 2 + outputTileSize - 1) / outputTileSize; int tiffColCount = (height / 2 + outputTileSize - 1) / outputTileSize; int index = 0; ulong[] offsets = new ulong[tiffRowCount * tiffColCount]; ulong[] byteCounts = new ulong[tiffRowCount * tiffColCount]; ulong totalByteCount = 0; reporter?.ReportStartReducedResolutionLayerGeneration(layer, offsets.Length, width / 2, height / 2); using (Image <Rgb24> canvas2 = new Image <Rgb24>(_configuration, outputTileSize2, outputTileSize2)) { for (int y = 0; y < height; y += outputTileSize2) { for (int x = 0; x < width; x += outputTileSize2) { cancellationToken.ThrowIfCancellationRequested(); MemoryMarshal.AsBytes(canvas2.GetPixelSpan()).Clear(); await image.DecodeAsync(new TiffPoint(x, y), canvas2).ConfigureAwait(false); using (Image <Rgb24> tile24 = canvas2.Clone(ctx => { ctx.Resize(outputTileSize, outputTileSize); })) { cancellationToken.ThrowIfCancellationRequested(); TiffStreamRegion region = await _encoder.EncodeAsync(_fileWriter, tile24).ConfigureAwait(false); offsets[index] = (ulong)region.Offset.Offset; byteCounts[index] = (uint)region.Length; totalByteCount += (uint)region.Length; index++; reporter?.ReportReducedResolutionLayerGenerationProgress(layer, index, offsets.Length); } } } } cancellationToken.ThrowIfCancellationRequested(); using (TiffImageFileDirectoryWriter ifdWriter = _fileWriter.CreateImageFileDirectory()) { await ifdWriter.WriteTagAsync(TiffTag.NewSubfileType, new TiffValueCollection <ushort>((ushort)TiffNewSubfileType.ReducedResolution)).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.PhotometricInterpretation, new TiffValueCollection <ushort>((ushort)TiffPhotometricInterpretation.YCbCr)).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.Compression, new TiffValueCollection <ushort>((ushort)TiffCompression.Jpeg)).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.SamplesPerPixel, new TiffValueCollection <ushort>((ushort)3)).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.TileWidth, new TiffValueCollection <ushort>((ushort)outputTileSize)).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.TileLength, new TiffValueCollection <ushort>((ushort)outputTileSize)).ConfigureAwait(false); //ifdWriter.AddTag(TiffTag.ResolutionUnit, (ushort)TiffResolutionUnit.Inch); //await ifdWriter.WriteTagAsync(TiffTag.XResolution, new TiffValueCollection<TiffRational>(new TiffRational(72, 1))); //await ifdWriter.WriteTagAsync(TiffTag.YResolution, new TiffValueCollection<TiffRational>(new TiffRational(72, 1))); await ifdWriter.WriteTagAsync(TiffTag.SampleFormat, new TiffValueCollection <ushort>(new ushort[] { 1, 1, 1 })).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.BitsPerSample, new TiffValueCollection <ushort>(new ushort[] { 8, 8, 8 })).ConfigureAwait(false); if (UseBigTiff) { await ifdWriter.WriteTagAsync(TiffTag.ImageWidth, new TiffValueCollection <ulong>((ulong)(width / 2))).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.ImageLength, new TiffValueCollection <ulong>((ulong)(height / 2))).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.TileOffsets, new TiffValueCollection <ulong>(offsets)).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.TileByteCounts, new TiffValueCollection <ulong>(byteCounts)).ConfigureAwait(false); } else { await ifdWriter.WriteTagAsync(TiffTag.ImageWidth, new TiffValueCollection <uint>((uint)(width / 2))).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.ImageLength, new TiffValueCollection <uint>((uint)(height / 2))).ConfigureAwait(false); uint[] tempArr = new uint[offsets.Length]; for (int i = 0; i < tempArr.Length; i++) { tempArr[i] = (uint)offsets[i]; } await ifdWriter.WriteTagAsync(TiffTag.TileOffsets, new TiffValueCollection <uint>(tempArr)).ConfigureAwait(false); for (int i = 0; i < tempArr.Length; i++) { tempArr[i] = (uint)byteCounts[i]; } await ifdWriter.WriteTagAsync(TiffTag.TileByteCounts, new TiffValueCollection <uint>(tempArr)).ConfigureAwait(false); } string software = Software; if (!string.IsNullOrEmpty(software)) { await ifdWriter.WriteTagAsync(TiffTag.Software, new TiffValueCollection <string>(software)); } ifdOffset = await ifdWriter.FlushAsync(ifdOffset).ConfigureAwait(false); } reporter?.ReportCompleteReducedResolutionLayerGeneration(layer, offsets.Length, (long)totalByteCount); return(ifdOffset); }