public void EnsureSameTileNotRenderedTwice_ForWeirdlyOrderedResultsReversed() { ISuperTile[] testCases = { new TimeOffsetSingleLayerSuperTile(TimeSpan.Zero, SpectrogramType.Index, 0.16.Seconds(), Image.Load <Rgba32>(PathHelper.ResolveAssetPath("[email protected]_0.png")), TimeSpan.FromMinutes(0)), new TimeOffsetSingleLayerSuperTile(TimeSpan.Zero, SpectrogramType.Index, 0.16.Seconds(), Image.Load <Rgba32>(PathHelper.ResolveAssetPath("[email protected]_1.png")), TimeSpan.FromMinutes(1)), }; // scale size results in two images drawn var singleScaleTiler = new Tiler( this.outputDirectory, this.tilingProfile, new SortedSet <double>() { 0.16 }, 60.0, 1440, new SortedSet <double>() { 1 }, 1.0, 300); // test // super tile 2 -> image b , c // super tile 1 -> image a , b // second super tile call fails because duplicate b singleScaleTiler.Tile(testCases[1]); TestHelper.ExceptionMatches <DuplicateTileException>( () => { singleScaleTiler.Tile(testCases[0]); }, "Tile 'panojstile_00000_00001_00000' has already been created."); }
public void EnsureSameThreeTilesWrittenForTwoOddlySizedSuperTiles() { ISuperTile[] testCases = { new TimeOffsetSingleLayerSuperTile(TimeSpan.Zero, SpectrogramType.Index, 0.16.Seconds(), Image.Load <Rgba32>(PathHelper.ResolveAssetPath("[email protected]_0.png")), TimeSpan.FromMinutes(0)), new TimeOffsetSingleLayerSuperTile(TimeSpan.Zero, SpectrogramType.Index, 0.16.Seconds(), Image.Load <Rgba32>(PathHelper.ResolveAssetPath("[email protected]_1.png")), TimeSpan.FromMinutes(1)), }; var singleScaleTiler = new Tiler( this.outputDirectory.ToDirectoryEntry(), this.tilingProfile, new SortedSet <double>() { 0.16 }, 60.0, 1440, new SortedSet <double>() { 1 }, 1.0, 300); // test // super tile 1 -> image a , b // super tile 2 -> image c singleScaleTiler.Tile(null, testCases[0], testCases[1]); singleScaleTiler.Tile(testCases[0], testCases[1], null); var producedFiles = this.outputDirectory.GetFiles().OrderBy(x => x.Name).ToArray(); Assert.AreEqual(3, producedFiles.Length); var expectedImages = new[] { "panojstile_00000_00000_00000.png", "panojstile_00000_00001_00000.png", "panojstile_00000_00002_00000.png", } .OrderBy(x => x) .Select(x => PathHelper.ResolveAssetPath(x)) .ToArray(); var loadedImages = expectedImages.Select(Image.Load <Rgba32>).ToArray(); for (int i = 0; i < loadedImages.Length; i++) { var producedImage = Image.Load <Rgba32>(producedFiles[i].FullName); var areEqual = BitmapEquals(loadedImages[i], (producedImage)); Assert.IsTrue(areEqual, "Bitmaps were not equal {0}, {1}", expectedImages[i], producedFiles[i].Name); } }
private static void TileOutput(DirectoryInfo outputDirectory, string fileStem, string analysisTag, FileSegment fileSegment, Image <Rgb24> image) { const int TileHeight = 256; const int TileWidth = 60; // seconds per pixel const double Scale = 60.0; TimeSpan scale = Scale.Seconds(); if (image.Height != TileHeight) { throw new InvalidOperationException("Expecting images exactly the same height as the defined tile height"); } // if recording does not start on an absolutely aligned hour of the day // align it, then adjust where the tiling starts from, and calculate the offset for the super tile (the gap) var recordingStartDate = fileSegment.TargetFileStartDate.Value; // TODO: begin remove duplicate code var timeOfDay = recordingStartDate.TimeOfDay; var previousAbsoluteHour = TimeSpan.FromSeconds(Math.Floor(timeOfDay.TotalSeconds / (Scale * TileWidth)) * (Scale * TileWidth)); var gap = timeOfDay - previousAbsoluteHour; var tilingStartDate = recordingStartDate - gap; var tilingStartDate2 = ZoomTiledSpectrograms.GetPreviousTileBoundary(TileWidth, Scale, recordingStartDate); var padding = recordingStartDate - tilingStartDate2; Debug.Assert(tilingStartDate == tilingStartDate2, "tilingStartDate != tilingStartDate2: these methods should be equivalent"); // TODO: end remove duplicate code var tilingProfile = new AbsoluteDateTilingProfile(fileStem, analysisTag, tilingStartDate, TileHeight, TileWidth); // pad out image so it produces a whole number of tiles // this solves the asymmetric right padding of short audio files var width = (int)(Math.Ceiling(image.Width / Scale) * Scale); var tiler = new Tiler(outputDirectory, tilingProfile, Scale, width, 1.0, image.Height); // prepare super tile var tile = new TimeOffsetSingleLayerSuperTile( padding, SpectrogramType.Index, scale, image.CloneAs <Rgba32>(), fileSegment.SegmentStartOffset ?? TimeSpan.Zero); tiler.Tile(tile); }
public void TestLeftPaddingInLowerLayers() { const int TileWidth = 180; var startDate = new DateTimeOffset(2014, 05, 29, 08, 13, 58, TimeSpan.FromHours(10)); var boundary = ZoomTiledSpectrograms.GetPreviousTileBoundary(TileWidth, 0.1, startDate); var padding = startDate - boundary; var profile = new AbsoluteDateTilingProfile( "Filename", "Tile", boundary, 256, TileWidth); var tiler = new Tiler( this.outputDirectory.ToDirectoryEntry(), profile, new SortedSet <double>() { 60.0, 0.1 }, 60.0, 1440, new SortedSet <double>() { 1, 1 }, 1.0, 256); var testBitmap = new Bitmap(1200, 256); using (var graphics = Graphics.FromImage(testBitmap)) { var points = new[] { new Point(0, 0), new Point(180, 256), new Point(360, 0), new Point(540, 256), new Point(720, 0), new Point(900, 256), new Point(1080, 0), new Point(1260, 256), }; graphics.DrawLines( Pens.Red, points); } var superTile = new TimeOffsetSingleLayerSuperTile( padding, SpectrogramType.Index, 0.1.Seconds(), testBitmap, 0.Seconds()); tiler.Tile(superTile); ////Debug.WriteLine(this.outputDirectory.FullName); ////Debug.WriteLine(this.outputDirectory.GetFiles().Length); var actualFiles = this.outputDirectory.GetFiles().OrderBy(x => x.Name).ToArray(); Assert.AreEqual(8, actualFiles.Length); var expectedFiles = new[] { "Filename__Tile_20140528T221348Z_0.1.png", "Filename__Tile_20140528T221406Z_0.1.png", "Filename__Tile_20140528T221424Z_0.1.png", "Filename__Tile_20140528T221442Z_0.1.png", "Filename__Tile_20140528T221500Z_0.1.png", "Filename__Tile_20140528T221518Z_0.1.png", "Filename__Tile_20140528T221536Z_0.1.png", "Filename__Tile_20140528T221554Z_0.1.png", }; var expectedImages = expectedFiles .OrderBy(x => x) .Select((x, i) => testBitmap.Crop(new Rectangle((i * TileWidth) - 100, 0, TileWidth, 256))) .ToArray(); for (var i = 0; i < expectedImages.Length; i++) { Assert.AreEqual(expectedFiles[i], actualFiles[i].Name); var expectedImage = expectedImages[i]; var actualImage = Image.FromFile(actualFiles[i].FullName); var areEqual = TilerTests.BitmapEquals(expectedImage, (Bitmap)actualImage); Assert.IsTrue(areEqual, "Bitmaps were not equal {0}, {1}", expectedFiles[i], actualFiles[i]); } }
private static void GenerateStandardSpectrogramTiles( Dictionary <string, double[, ]> spectra, IndexGenerationData indexGeneration, LdSpectrogramConfig ldsConfig, Dictionary <string, IndexProperties> filteredIndexProperties, SpectrogramZoomingConfig zoomConfig, double[] standardScales, string fileStem, TilingProfile namingPattern, Tiler tiler, TimeSpan alignmentPadding) { Log.Info("START DRAWING ZOOMED-IN FRAME SPECTROGRAMS"); TimeSpan dataDuration = TimeSpan.FromTicks(spectra["PMN"].GetLength(1) * indexGeneration.IndexCalculationDuration.Ticks); TimeSpan duration = indexGeneration.RecordingDuration; Contract.Requires( (dataDuration - duration).Absolute() < indexGeneration.IndexCalculationDuration, "The expected amount of data was not supplied"); var minuteCount = (int)Math.Ceiling(dataDuration.TotalMinutes); // window the standard spectrogram generation so that we can provide adjacent supertiles to the // tiler, so that bordering / overlapping tiles (for cases where tile size != multiple of supertile size) // don't render partial tiles (i.e. bad/partial rendering of image) // this is the function generator // use of Lazy means results will only be evaluated once // and only when needed. This is useful for sliding window. Lazy <TimeOffsetSingleLayerSuperTile[]> GenerateStandardSpectrogramGenerator(int minuteToLoad) { return(new Lazy <TimeOffsetSingleLayerSuperTile[]>( () => { Log.Info("Starting generation for minute: " + minuteToLoad); var superTilingResults = DrawSuperTilesFromSingleFrameSpectrogram( null /*inputDirectory*/, //TODO:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ldsConfig, filteredIndexProperties, zoomConfig, minuteToLoad, standardScales, fileStem, indexGeneration, namingPattern.ChromeOption, alignmentPadding); return superTilingResults; })); } Lazy <TimeOffsetSingleLayerSuperTile[]> previous = null; Lazy <TimeOffsetSingleLayerSuperTile[]> current = null; Lazy <TimeOffsetSingleLayerSuperTile[]> next = null; for (int minute = 0; minute < minuteCount; minute++) { Log.Trace("Starting loop for minute" + minute); // shift each value back previous = current; current = next ?? GenerateStandardSpectrogramGenerator(minute); next = minute + 1 < minuteCount?GenerateStandardSpectrogramGenerator(minute + 1) : null; // for each scale level of the results for (int i = 0; i < current.Value.Length; i++) { // finally tile the output Log.Debug("Begin tile production for minute: " + minute); tiler.Tile(previous?.Value[i], current.Value[i], next?.Value[i]); Log.Debug("Begin tile production for minute: " + minute); } } }
public void TestLeftPaddingInLowerLayers() { const int TileWidth = 180; var startDate = new DateTimeOffset(2014, 05, 29, 08, 13, 58, TimeSpan.FromHours(10)); var boundary = ZoomTiledSpectrograms.GetPreviousTileBoundary(TileWidth, 0.1, startDate); var padding = startDate - boundary; var profile = new AbsoluteDateTilingProfile( "Filename", "Tile", boundary, 256, TileWidth); var tiler = new Tiler( this.outputDirectory, profile, new SortedSet <double>() { 60.0, 0.1 }, 60.0, 1440, new SortedSet <double>() { 1, 1 }, 1.0, 256); var testBitmap = new Image <Rgba32>(1200, 256); testBitmap.Mutate(graphics => { var points = new[] { new PointF(0, 0), new Point(180, 256), new Point(360, 0), new Point(540, 256), new Point(720, 0), new PointF(900, 256), new Point(1080, 0), new Point(1260, 256), }; graphics.DrawLines( new GraphicsOptions(), Brushes.Solid(Color.Red), 1, points); }); var superTile = new TimeOffsetSingleLayerSuperTile( padding, SpectrogramType.Index, 0.1.Seconds(), testBitmap, 0.Seconds()); tiler.Tile(superTile); ////Trace.WriteLine(this.outputDirectory.FullName); ////Trace.WriteLine(this.outputDirectory.GetFiles().Length); var actualFiles = this.outputDirectory.GetFiles().OrderBy(x => x.Name).ToArray(); Assert.AreEqual(8, actualFiles.Length); var expectedFiles = new[] { "Filename__Tile_20140528T221348Z_0.1.png", "Filename__Tile_20140528T221406Z_0.1.png", "Filename__Tile_20140528T221424Z_0.1.png", "Filename__Tile_20140528T221442Z_0.1.png", "Filename__Tile_20140528T221500Z_0.1.png", "Filename__Tile_20140528T221518Z_0.1.png", "Filename__Tile_20140528T221536Z_0.1.png", "Filename__Tile_20140528T221554Z_0.1.png", }; var expectedImages = expectedFiles .OrderBy(x => x) .Select((x, i) => testBitmap.CropInverse(new Rectangle((i * TileWidth) - 100, 0, TileWidth, 256))) .ToArray(); for (var i = 0; i < expectedImages.Length; i++) { Assert.AreEqual(expectedFiles[i], actualFiles[i].Name); var expectedImage = expectedImages[i]; var actualImage = Image.Load <Rgba32>(actualFiles[i].FullName); Assert.That.ImageMatches(expectedImages[i], actualImage, message: $"Bitmaps were not equal {expectedImages[i]}, {actualFiles[i]}"); } }