private Image <Rgba32> Reproject(Registration registration) { var definition = registration.Definition; // Preserve 2:1 equirectangular aspect ratio var maxWidth = _options.ImageSize * 2; var maxHeight = _options.ImageSize; // Determine pixel ranges of projected image so we can limit our processing to longitudes visible to satellite // Unwrap the longitude range to simplify maths var longitudeRange = new Range( definition.LongitudeRange.Start, definition.LongitudeRange.End).UnwrapLongitude(); var latitudeRange = new Range(definition.LatitudeRange.Start, definition.LatitudeRange.End); _logger.LogInformation("{definition:l0} latitude range {startRange:F2} to {endRange:F2} degrees", definition.DisplayName, Angle.FromRadians(latitudeRange.Start).Degrees, Angle.FromRadians(latitudeRange.End).Degrees); _logger.LogInformation("{definition:l0} unwrapped longitude range {startRange:F2} to {endRange:F2} degrees", definition.DisplayName, Angle.FromRadians(longitudeRange.Start).Degrees, Angle.FromRadians(longitudeRange.End).Degrees); // Get size of projection in pixels var xRange = new PixelRange(longitudeRange, a => a.ScaleToWidth(maxWidth)); // Restrict height of image to the visible range if we are not performing explicit cropping or no cropping var yRange = _options.EquirectangularRender?.NoCrop == true || _options.EquirectangularRender?.ExplicitCrop == true ? new PixelRange(0, maxHeight) : new PixelRange(latitudeRange, a => a.ScaleToHeight(maxHeight)); _logger.LogInformation("{definition:l0} pixel range X: {minX} - {maxX} px", definition.DisplayName, xRange.Start, xRange.End); _logger.LogInformation("{definition:l0} pixel range Y: {minY} - {maxY} px", definition.DisplayName, yRange.Start, yRange.End); _logger.LogInformation("{definition:l0} width: {targetWidth} px", definition.DisplayName, xRange.Range); _logger.LogInformation("{definition:l0} height: {targetWidth} px", definition.DisplayName, yRange.Range); // Create target image with the correct dimensions for the projected satellite image var target = new Image <Rgba32>(xRange.Range, yRange.Range); _logger.LogInformation("{definition:l0} Reprojecting", definition.DisplayName); // Perform reprojection var operation = new ReprojectRowOperation(registration, SourceImage !, target, xRange.Start, yRange.Start, _options); ParallelRowIterator.IterateRows(Configuration.Default, target.Bounds(), in operation); return(target); }
/// <summary> /// Converts an angle range to a X pixel range, assuming the target image has X pixel coordinates mapping from -180 to 180 degrees. /// </summary> public static PixelRange ToPixelRangeX(this Range range, int width) => new(range, angle => angle.ToX(width));
/// <summary> /// Converts an angle range to a Y pixel range, assuming the target image has Y pixel coordinates mapping from -90 to 90 degrees. /// </summary> public static PixelRange ToPixelRangeY(this Range range, int height) => new PixelRange(range, angle => ToY(angle, height));
/// <summary> /// Converts an angle range to a X pixel range, assuming the target image has X pixel coordinates mapping from -180 to 180 degrees. /// </summary> public static PixelRange ToPixelRangeX(this Range range, int width) => new PixelRange(range, angle => ToX(angle, width));