public QueryContext(JP2Codestream cs, ushort tileIdx) { if (cs == null || !cs.IsOpened) { throw new ArgumentNullException("cs null or not opened"); } if (tileIdx >= (cs.TileCount.Width * cs.TileCount.Height)) { throw new ArgumentOutOfRangeException("tileIdx"); } Codestream = cs; TileIdx = tileIdx; Image = new Rectangle(Codestream.ImageOffset, Codestream.ImageSize); Tile = new Rectangle[Codestream.DecompositionLevels + 1]; Precincts = new Size[Codestream.DecompositionLevels + 1]; CodMarker cod = Codestream.Markers[MarkerType.COD] as CodMarker; Log2Partitions = cod.PrecinctPartitions; for (int r = 0; r <= Codestream.DecompositionLevels; r++) { Tile[r] = CalculateTileRect(TileIdx, r); Precincts[r] = CalculatePrecinctCount(TileIdx, r); } }
private void Run() { ThrowIfHasInnerTiles(_firstCodestream); ThrowIfTooManyTiles(); SizMarker siz = GetDestSiz(); // Lets generate a tile-part for each tile-resolution in the source images int tiles = _imageCount.Width * _imageCount.Height; int expectedTileParts = tiles * (_firstCodestream.DecompositionLevels + 1); CodMarker cod = _firstCodestream.Markers[MarkerType.COD] as CodMarker; QcdMarker qcd = _firstCodestream.Markers[MarkerType.QCD] as QcdMarker; WarnIfClipped(_firstCodestream, cod); ComMarker com = new ComMarker("https://github.com/plroit/Skyreach"); var markers = new List <MarkerSegment>() { siz, cod, qcd, com }; Jp2File dst = Jp2File.Create( markers, expectedTileParts, false, _dest); for (ushort tIdx = 0; tIdx < tiles; tIdx++) { CopyTile(tIdx, dst); } dst.Flush(); }
private static void WarnIfClipped(JP2Codestream src, CodMarker cod) { bool tileSizePow2 = true; bool isClippedCodeblock = false; int diffTileCblk; tileSizePow2 &= BitHacks.IsPowerOf2((uint)src.TileSize.Width); tileSizePow2 &= BitHacks.IsPowerOf2((uint)src.TileSize.Height); diffTileCblk = BitHacks.LogFloor2((uint)src.TileSize.Width); diffTileCblk -= cod.CodeblockWidth; isClippedCodeblock |= diffTileCblk < cod.DecompositionLevels; diffTileCblk = BitHacks.LogFloor2((uint)src.TileSize.Height); diffTileCblk -= cod.CodeblockHeight; isClippedCodeblock |= diffTileCblk < cod.DecompositionLevels; if (isClippedCodeblock && !tileSizePow2) { var sb = new StringBuilder(); Console.WriteLine(sb .AppendLine( "Codeblock in one of the subbands is clipped by the ") .AppendLine( "actual subband dimensions, to perform merging well ") .AppendLine( "input origin must be aligned at the same position ") .AppendLine( "as their output coordinates") .ToString()); } }
/// <summary> /// Creates from scratch a JPEG2000 conforming file /// with a JPEG2000 codestream skeleton. /// /// </summary> /// <param name="siz"></param> /// <param name="cod"></param> /// <param name="qcd"></param> /// <param name="reservedTileparts"></param> /// <param name="stream"></param> /// <returns></returns> public static Jp2File Create( IEnumerable <MarkerSegment> markers, int reservedTileparts, bool hasPropertyRights, Stream stream) { var sizs = markers.Where(mrk => mrk.Type == MarkerType.SIZ); var cods = markers.Where(mrk => mrk.Type == MarkerType.SIZ); var qcds = markers.Where(mrk => mrk.Type == MarkerType.QCD); if (!sizs.Any() || !cods.Any() || !qcds.Any()) { throw new ArgumentException( "Must supply SIZ, COD and QCD markers"); } SizMarker siz = sizs.First() as SizMarker; CodMarker cod = cods.First() as CodMarker; QcdMarker qcd = qcds.First() as QcdMarker; ColorSpace colorspace = GetColorspace(siz); Jp2Box signBox = new Jp2SignatureBox(); Jp2Box ftypBox = new FileTypeBox(); Jp2Box jp2hBox = new Jp2Box((uint)BoxTypes.JP2HeaderBox); ImageHeaderBox ihdrBox = new ImageHeaderBox(siz, hasPropertyRights); Jp2Box colrBox = new ColorspaceSpecificationBox(colorspace); var codestream = new JP2Codestream(markers, reservedTileparts); var csBox = new ContiguousCodestreamBox(codestream); if (ihdrBox.BitsPerComponent == ImageHeaderBox.USE_BPC_BOX) { throw new NotSupportedException( "Create image with bit per component specification box"); } jp2hBox.Add(new List <Jp2Box> { ihdrBox, colrBox }); Jp2File jp2File = new Jp2File(stream, new List <Jp2Box> { signBox, ftypBox, jp2hBox, csBox }); return(jp2File); }
private int GetPrecinctsInResolution(int r, CodMarker cod) { Assert.AreEqual(_tileIdx, 1); Assert.AreEqual(_rpclCodestream.TileSize, new Size(200, 200)); Assert.AreEqual(_rpclCodestream.ImageSize, new Size(968, 648)); // image size (968,648) tile size: (200,200) // precinct sizes: (128,128),(128,128),(64,64),(64,64),(64,64) int precinctsInResolution = 0; Point ppxy = cod.PrecinctPartitions[r]; switch (r) { case 0: { // tile TopLeft (13,0) W/H (13,13), // precincts: (64,64) precinctsInResolution = 1; Assert.AreEqual(ppxy, new Point(6, 6)); } break; case 1: { Assert.AreEqual(ppxy, new Point(6, 6)); // tile TopLeft (25,0) W/H (25,25), // precincts: (64,64) precinctsInResolution = 1; } break; case 2: { Assert.AreEqual(ppxy, new Point(6, 6)); // tile TopLeft (50,0) W/H (50,50), // precincts (64,64) // horizontal: 0-64,64-128 // vertical: 0-64 // total 2 precincts precinctsInResolution = 2; } break; case 3: { Assert.AreEqual(ppxy, new Point(7, 7)); // tile TopLeft: (100,0), W/H (100,100) // precincts(128,128) // horizontal: 0-128,128-256 // vertical: 0-128 // total 2 precincts precinctsInResolution = 2; } break; case 4: { Assert.AreEqual(ppxy, new Point(7, 7)); // tile TopLeft: (200,0), W/H (200,200) // precincts (128,128) // horizontal: 128-256, 256-384, 384-512 // vertical: 0-128, 128-256 // total 6 precincts precinctsInResolution = 6; } break; } return(precinctsInResolution); }