|  | @@ -85,7 +85,6 @@ namespace Jellyfin.Api.Controllers
 | 
	
		
			
				|  |  |          /// <response code="403">User does not have permission to delete the image.</response>
 | 
	
		
			
				|  |  |          /// <returns>A <see cref="NoContentResult"/>.</returns>
 | 
	
		
			
				|  |  |          [HttpPost("Users/{userId}/Images/{imageType}")]
 | 
	
		
			
				|  |  | -        [HttpPost("Users/{userId}/Images/{imageType}/{index?}", Name = "PostUserImage_2")]
 | 
	
		
			
				|  |  |          [Authorize(Policy = Policies.DefaultAuthorization)]
 | 
	
		
			
				|  |  |          [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
	
		
			
				|  |  |          [ProducesResponseType(StatusCodes.Status403Forbidden)]
 | 
	
	
		
			
				|  | @@ -94,7 +93,53 @@ namespace Jellyfin.Api.Controllers
 | 
	
		
			
				|  |  |          public async Task<ActionResult> PostUserImage(
 | 
	
		
			
				|  |  |              [FromRoute, Required] Guid userId,
 | 
	
		
			
				|  |  |              [FromRoute, Required] ImageType imageType,
 | 
	
		
			
				|  |  | -            [FromRoute] int? index = null)
 | 
	
		
			
				|  |  | +            [FromQuery] int? index = null)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true))
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return Forbid("User is not allowed to update the image.");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var user = _userManager.GetUserById(userId);
 | 
	
		
			
				|  |  | +            await using var memoryStream = await GetMemoryStream(Request.Body).ConfigureAwait(false);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // Handle image/png; charset=utf-8
 | 
	
		
			
				|  |  | +            var mimeType = Request.ContentType.Split(';').FirstOrDefault();
 | 
	
		
			
				|  |  | +            var userDataPath = Path.Combine(_serverConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath, user.Username);
 | 
	
		
			
				|  |  | +            if (user.ProfileImage != null)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                await _userManager.ClearProfileImageAsync(user).ConfigureAwait(false);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            user.ProfileImage = new Data.Entities.ImageInfo(Path.Combine(userDataPath, "profile" + MimeTypes.ToExtension(mimeType)));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            await _providerManager
 | 
	
		
			
				|  |  | +                .SaveImage(memoryStream, mimeType, user.ProfileImage.Path)
 | 
	
		
			
				|  |  | +                .ConfigureAwait(false);
 | 
	
		
			
				|  |  | +            await _userManager.UpdateUserAsync(user).ConfigureAwait(false);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return NoContent();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Sets the user image.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        /// <param name="userId">User Id.</param>
 | 
	
		
			
				|  |  | +        /// <param name="imageType">(Unused) Image type.</param>
 | 
	
		
			
				|  |  | +        /// <param name="index">(Unused) Image index.</param>
 | 
	
		
			
				|  |  | +        /// <response code="204">Image updated.</response>
 | 
	
		
			
				|  |  | +        /// <response code="403">User does not have permission to delete the image.</response>
 | 
	
		
			
				|  |  | +        /// <returns>A <see cref="NoContentResult"/>.</returns>
 | 
	
		
			
				|  |  | +        [HttpPost("Users/{userId}/Images/{imageType}/{index}")]
 | 
	
		
			
				|  |  | +        [Authorize(Policy = Policies.DefaultAuthorization)]
 | 
	
		
			
				|  |  | +        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
	
		
			
				|  |  | +        [ProducesResponseType(StatusCodes.Status403Forbidden)]
 | 
	
		
			
				|  |  | +        [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "imageType", Justification = "Imported from ServiceStack")]
 | 
	
		
			
				|  |  | +        [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "index", Justification = "Imported from ServiceStack")]
 | 
	
		
			
				|  |  | +        public async Task<ActionResult> PostUserImageByIndex(
 | 
	
		
			
				|  |  | +            [FromRoute, Required] Guid userId,
 | 
	
		
			
				|  |  | +            [FromRoute, Required] ImageType imageType,
 | 
	
		
			
				|  |  | +            [FromRoute] int index)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true))
 | 
	
		
			
				|  |  |              {
 | 
	
	
		
			
				|  | @@ -131,8 +176,7 @@ namespace Jellyfin.Api.Controllers
 | 
	
		
			
				|  |  |          /// <response code="204">Image deleted.</response>
 | 
	
		
			
				|  |  |          /// <response code="403">User does not have permission to delete the image.</response>
 | 
	
		
			
				|  |  |          /// <returns>A <see cref="NoContentResult"/>.</returns>
 | 
	
		
			
				|  |  | -        [HttpDelete("Users/{userId}/Images/{itemType}")]
 | 
	
		
			
				|  |  | -        [HttpDelete("Users/{userId}/Images/{itemType}/{index?}", Name = "DeleteUserImage_2")]
 | 
	
		
			
				|  |  | +        [HttpDelete("Users/{userId}/Images/{imageType}")]
 | 
	
		
			
				|  |  |          [Authorize(Policy = Policies.DefaultAuthorization)]
 | 
	
		
			
				|  |  |          [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "imageType", Justification = "Imported from ServiceStack")]
 | 
	
		
			
				|  |  |          [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "index", Justification = "Imported from ServiceStack")]
 | 
	
	
		
			
				|  | @@ -141,7 +185,46 @@ namespace Jellyfin.Api.Controllers
 | 
	
		
			
				|  |  |          public async Task<ActionResult> DeleteUserImage(
 | 
	
		
			
				|  |  |              [FromRoute, Required] Guid userId,
 | 
	
		
			
				|  |  |              [FromRoute, Required] ImageType imageType,
 | 
	
		
			
				|  |  | -            [FromRoute] int? index = null)
 | 
	
		
			
				|  |  | +            [FromQuery] int? index = null)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true))
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return Forbid("User is not allowed to delete the image.");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var user = _userManager.GetUserById(userId);
 | 
	
		
			
				|  |  | +            try
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                System.IO.File.Delete(user.ProfileImage.Path);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            catch (IOException e)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                _logger.LogError(e, "Error deleting user profile image:");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            await _userManager.ClearProfileImageAsync(user).ConfigureAwait(false);
 | 
	
		
			
				|  |  | +            return NoContent();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Delete the user's image.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        /// <param name="userId">User Id.</param>
 | 
	
		
			
				|  |  | +        /// <param name="imageType">(Unused) Image type.</param>
 | 
	
		
			
				|  |  | +        /// <param name="index">(Unused) Image index.</param>
 | 
	
		
			
				|  |  | +        /// <response code="204">Image deleted.</response>
 | 
	
		
			
				|  |  | +        /// <response code="403">User does not have permission to delete the image.</response>
 | 
	
		
			
				|  |  | +        /// <returns>A <see cref="NoContentResult"/>.</returns>
 | 
	
		
			
				|  |  | +        [HttpDelete("Users/{userId}/Images/{imageType}/{index}")]
 | 
	
		
			
				|  |  | +        [Authorize(Policy = Policies.DefaultAuthorization)]
 | 
	
		
			
				|  |  | +        [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "imageType", Justification = "Imported from ServiceStack")]
 | 
	
		
			
				|  |  | +        [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "index", Justification = "Imported from ServiceStack")]
 | 
	
		
			
				|  |  | +        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
	
		
			
				|  |  | +        [ProducesResponseType(StatusCodes.Status403Forbidden)]
 | 
	
		
			
				|  |  | +        public async Task<ActionResult> DeleteUserImageByIndex(
 | 
	
		
			
				|  |  | +            [FromRoute, Required] Guid userId,
 | 
	
		
			
				|  |  | +            [FromRoute, Required] ImageType imageType,
 | 
	
		
			
				|  |  | +            [FromRoute] int index)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true))
 | 
	
		
			
				|  |  |              {
 | 
	
	
		
			
				|  | @@ -172,14 +255,13 @@ namespace Jellyfin.Api.Controllers
 | 
	
		
			
				|  |  |          /// <response code="404">Item not found.</response>
 | 
	
		
			
				|  |  |          /// <returns>A <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if item not found.</returns>
 | 
	
		
			
				|  |  |          [HttpDelete("Items/{itemId}/Images/{imageType}")]
 | 
	
		
			
				|  |  | -        [HttpDelete("Items/{itemId}/Images/{imageType}/{imageIndex?}", Name = "DeleteItemImage_2")]
 | 
	
		
			
				|  |  |          [Authorize(Policy = Policies.RequiresElevation)]
 | 
	
		
			
				|  |  |          [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
	
		
			
				|  |  |          [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
	
		
			
				|  |  |          public async Task<ActionResult> DeleteItemImage(
 | 
	
		
			
				|  |  |              [FromRoute, Required] Guid itemId,
 | 
	
		
			
				|  |  |              [FromRoute, Required] ImageType imageType,
 | 
	
		
			
				|  |  | -            [FromRoute] int? imageIndex = null)
 | 
	
		
			
				|  |  | +            [FromQuery] int? imageIndex)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              var item = _libraryManager.GetItemById(itemId);
 | 
	
		
			
				|  |  |              if (item == null)
 | 
	
	
		
			
				|  | @@ -191,25 +273,83 @@ namespace Jellyfin.Api.Controllers
 | 
	
		
			
				|  |  |              return NoContent();
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Delete an item's image.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        /// <param name="itemId">Item id.</param>
 | 
	
		
			
				|  |  | +        /// <param name="imageType">Image type.</param>
 | 
	
		
			
				|  |  | +        /// <param name="imageIndex">The image index.</param>
 | 
	
		
			
				|  |  | +        /// <response code="204">Image deleted.</response>
 | 
	
		
			
				|  |  | +        /// <response code="404">Item not found.</response>
 | 
	
		
			
				|  |  | +        /// <returns>A <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if item not found.</returns>
 | 
	
		
			
				|  |  | +        [HttpDelete("Items/{itemId}/Images/{imageType}/{imageIndex}")]
 | 
	
		
			
				|  |  | +        [Authorize(Policy = Policies.RequiresElevation)]
 | 
	
		
			
				|  |  | +        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
	
		
			
				|  |  | +        [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
	
		
			
				|  |  | +        public async Task<ActionResult> DeleteItemImageByIndex(
 | 
	
		
			
				|  |  | +            [FromRoute, Required] Guid itemId,
 | 
	
		
			
				|  |  | +            [FromRoute, Required] ImageType imageType,
 | 
	
		
			
				|  |  | +            [FromRoute] int imageIndex)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var item = _libraryManager.GetItemById(itemId);
 | 
	
		
			
				|  |  | +            if (item == null)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return NotFound();
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            await item.DeleteImageAsync(imageType, imageIndex).ConfigureAwait(false);
 | 
	
		
			
				|  |  | +            return NoContent();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          /// <summary>
 | 
	
		
			
				|  |  |          /// Set item image.
 | 
	
		
			
				|  |  |          /// </summary>
 | 
	
		
			
				|  |  |          /// <param name="itemId">Item id.</param>
 | 
	
		
			
				|  |  |          /// <param name="imageType">Image type.</param>
 | 
	
		
			
				|  |  | -        /// <param name="imageIndex">(Unused) Image index.</param>
 | 
	
		
			
				|  |  |          /// <response code="204">Image saved.</response>
 | 
	
		
			
				|  |  |          /// <response code="404">Item not found.</response>
 | 
	
		
			
				|  |  |          /// <returns>A <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if item not found.</returns>
 | 
	
		
			
				|  |  |          [HttpPost("Items/{itemId}/Images/{imageType}")]
 | 
	
		
			
				|  |  | -        [HttpPost("Items/{itemId}/Images/{imageType}/{imageIndex?}", Name = "SetItemImage_2")]
 | 
	
		
			
				|  |  |          [Authorize(Policy = Policies.RequiresElevation)]
 | 
	
		
			
				|  |  |          [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
	
		
			
				|  |  |          [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
	
		
			
				|  |  |          [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "index", Justification = "Imported from ServiceStack")]
 | 
	
		
			
				|  |  |          public async Task<ActionResult> SetItemImage(
 | 
	
		
			
				|  |  | +            [FromRoute, Required] Guid itemId,
 | 
	
		
			
				|  |  | +            [FromRoute, Required] ImageType imageType)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var item = _libraryManager.GetItemById(itemId);
 | 
	
		
			
				|  |  | +            if (item == null)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return NotFound();
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // Handle image/png; charset=utf-8
 | 
	
		
			
				|  |  | +            var mimeType = Request.ContentType.Split(';').FirstOrDefault();
 | 
	
		
			
				|  |  | +            await _providerManager.SaveImage(item, Request.Body, mimeType, imageType, null, CancellationToken.None).ConfigureAwait(false);
 | 
	
		
			
				|  |  | +            await item.UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return NoContent();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Set item image.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        /// <param name="itemId">Item id.</param>
 | 
	
		
			
				|  |  | +        /// <param name="imageType">Image type.</param>
 | 
	
		
			
				|  |  | +        /// <param name="imageIndex">(Unused) Image index.</param>
 | 
	
		
			
				|  |  | +        /// <response code="204">Image saved.</response>
 | 
	
		
			
				|  |  | +        /// <response code="404">Item not found.</response>
 | 
	
		
			
				|  |  | +        /// <returns>A <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if item not found.</returns>
 | 
	
		
			
				|  |  | +        [HttpPost("Items/{itemId}/Images/{imageType}/{imageIndex}")]
 | 
	
		
			
				|  |  | +        [Authorize(Policy = Policies.RequiresElevation)]
 | 
	
		
			
				|  |  | +        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
	
		
			
				|  |  | +        [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
	
		
			
				|  |  | +        [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "index", Justification = "Imported from ServiceStack")]
 | 
	
		
			
				|  |  | +        public async Task<ActionResult> SetItemImageByIndex(
 | 
	
		
			
				|  |  |              [FromRoute, Required] Guid itemId,
 | 
	
		
			
				|  |  |              [FromRoute, Required] ImageType imageType,
 | 
	
		
			
				|  |  | -            [FromRoute] int? imageIndex = null)
 | 
	
		
			
				|  |  | +            [FromRoute] int imageIndex)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              var item = _libraryManager.GetItemById(itemId);
 | 
	
		
			
				|  |  |              if (item == null)
 | 
	
	
		
			
				|  | @@ -349,8 +489,6 @@ namespace Jellyfin.Api.Controllers
 | 
	
		
			
				|  |  |          /// </returns>
 | 
	
		
			
				|  |  |          [HttpGet("Items/{itemId}/Images/{imageType}")]
 | 
	
		
			
				|  |  |          [HttpHead("Items/{itemId}/Images/{imageType}", Name = "HeadItemImage")]
 | 
	
		
			
				|  |  | -        [HttpGet("Items/{itemId}/Images/{imageType}/{imageIndex?}", Name = "GetItemImage_2")]
 | 
	
		
			
				|  |  | -        [HttpHead("Items/{itemId}/Images/{imageType}/{imageIndex?}", Name = "HeadItemImage_2")]
 | 
	
		
			
				|  |  |          [ProducesResponseType(StatusCodes.Status200OK)]
 | 
	
		
			
				|  |  |          [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
	
		
			
				|  |  |          [ProducesImageFile]
 | 
	
	
		
			
				|  | @@ -371,7 +509,86 @@ namespace Jellyfin.Api.Controllers
 | 
	
		
			
				|  |  |              [FromQuery] int? blur,
 | 
	
		
			
				|  |  |              [FromQuery] string? backgroundColor,
 | 
	
		
			
				|  |  |              [FromQuery] string? foregroundLayer,
 | 
	
		
			
				|  |  | -            [FromRoute] int? imageIndex = null)
 | 
	
		
			
				|  |  | +            [FromQuery] int? imageIndex)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var item = _libraryManager.GetItemById(itemId);
 | 
	
		
			
				|  |  | +            if (item == null)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return NotFound();
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return await GetImageInternal(
 | 
	
		
			
				|  |  | +                    itemId,
 | 
	
		
			
				|  |  | +                    imageType,
 | 
	
		
			
				|  |  | +                    imageIndex,
 | 
	
		
			
				|  |  | +                    tag,
 | 
	
		
			
				|  |  | +                    format,
 | 
	
		
			
				|  |  | +                    maxWidth,
 | 
	
		
			
				|  |  | +                    maxHeight,
 | 
	
		
			
				|  |  | +                    percentPlayed,
 | 
	
		
			
				|  |  | +                    unplayedCount,
 | 
	
		
			
				|  |  | +                    width,
 | 
	
		
			
				|  |  | +                    height,
 | 
	
		
			
				|  |  | +                    quality,
 | 
	
		
			
				|  |  | +                    cropWhitespace,
 | 
	
		
			
				|  |  | +                    addPlayedIndicator,
 | 
	
		
			
				|  |  | +                    blur,
 | 
	
		
			
				|  |  | +                    backgroundColor,
 | 
	
		
			
				|  |  | +                    foregroundLayer,
 | 
	
		
			
				|  |  | +                    item,
 | 
	
		
			
				|  |  | +                    Request.Method.Equals(HttpMethods.Head, StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  | +                .ConfigureAwait(false);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Gets the item's image.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        /// <param name="itemId">Item id.</param>
 | 
	
		
			
				|  |  | +        /// <param name="imageType">Image type.</param>
 | 
	
		
			
				|  |  | +        /// <param name="imageIndex">Image index.</param>
 | 
	
		
			
				|  |  | +        /// <param name="maxWidth">The maximum image width to return.</param>
 | 
	
		
			
				|  |  | +        /// <param name="maxHeight">The maximum image height to return.</param>
 | 
	
		
			
				|  |  | +        /// <param name="width">The fixed image width to return.</param>
 | 
	
		
			
				|  |  | +        /// <param name="height">The fixed image height to return.</param>
 | 
	
		
			
				|  |  | +        /// <param name="quality">Optional. Quality setting, from 0-100. Defaults to 90 and should suffice in most cases.</param>
 | 
	
		
			
				|  |  | +        /// <param name="tag">Optional. Supply the cache tag from the item object to receive strong caching headers.</param>
 | 
	
		
			
				|  |  | +        /// <param name="cropWhitespace">Optional. Specify if whitespace should be cropped out of the image. True/False. If unspecified, whitespace will be cropped from logos and clear art.</param>
 | 
	
		
			
				|  |  | +        /// <param name="format">Optional. The <see cref="ImageFormat"/> of the returned image.</param>
 | 
	
		
			
				|  |  | +        /// <param name="addPlayedIndicator">Optional. Add a played indicator.</param>
 | 
	
		
			
				|  |  | +        /// <param name="percentPlayed">Optional. Percent to render for the percent played overlay.</param>
 | 
	
		
			
				|  |  | +        /// <param name="unplayedCount">Optional. Unplayed count overlay to render.</param>
 | 
	
		
			
				|  |  | +        /// <param name="blur">Optional. Blur image.</param>
 | 
	
		
			
				|  |  | +        /// <param name="backgroundColor">Optional. Apply a background color for transparent images.</param>
 | 
	
		
			
				|  |  | +        /// <param name="foregroundLayer">Optional. Apply a foreground layer on top of the image.</param>
 | 
	
		
			
				|  |  | +        /// <response code="200">Image stream returned.</response>
 | 
	
		
			
				|  |  | +        /// <response code="404">Item not found.</response>
 | 
	
		
			
				|  |  | +        /// <returns>
 | 
	
		
			
				|  |  | +        /// A <see cref="FileStreamResult"/> containing the file stream on success,
 | 
	
		
			
				|  |  | +        /// or a <see cref="NotFoundResult"/> if item not found.
 | 
	
		
			
				|  |  | +        /// </returns>
 | 
	
		
			
				|  |  | +        [HttpGet("Items/{itemId}/Images/{imageType}/{imageIndex}")]
 | 
	
		
			
				|  |  | +        [HttpHead("Items/{itemId}/Images/{imageType}/{imageIndex}", Name = "HeadItemImageByIndex")]
 | 
	
		
			
				|  |  | +        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
	
		
			
				|  |  | +        [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
	
		
			
				|  |  | +        [ProducesImageFile]
 | 
	
		
			
				|  |  | +        public async Task<ActionResult> GetItemImageByIndex(
 | 
	
		
			
				|  |  | +            [FromRoute, Required] Guid itemId,
 | 
	
		
			
				|  |  | +            [FromRoute, Required] ImageType imageType,
 | 
	
		
			
				|  |  | +            [FromRoute] int imageIndex,
 | 
	
		
			
				|  |  | +            [FromQuery] int? maxWidth,
 | 
	
		
			
				|  |  | +            [FromQuery] int? maxHeight,
 | 
	
		
			
				|  |  | +            [FromQuery] int? width,
 | 
	
		
			
				|  |  | +            [FromQuery] int? height,
 | 
	
		
			
				|  |  | +            [FromQuery] int? quality,
 | 
	
		
			
				|  |  | +            [FromQuery] string? tag,
 | 
	
		
			
				|  |  | +            [FromQuery] bool? cropWhitespace,
 | 
	
		
			
				|  |  | +            [FromQuery] ImageFormat? format,
 | 
	
		
			
				|  |  | +            [FromQuery] bool? addPlayedIndicator,
 | 
	
		
			
				|  |  | +            [FromQuery] double? percentPlayed,
 | 
	
		
			
				|  |  | +            [FromQuery] int? unplayedCount,
 | 
	
		
			
				|  |  | +            [FromQuery] int? blur,
 | 
	
		
			
				|  |  | +            [FromQuery] string? backgroundColor,
 | 
	
		
			
				|  |  | +            [FromQuery] string? foregroundLayer)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              var item = _libraryManager.GetItemById(itemId);
 | 
	
		
			
				|  |  |              if (item == null)
 | 
	
	
		
			
				|  | @@ -507,8 +724,8 @@ namespace Jellyfin.Api.Controllers
 | 
	
		
			
				|  |  |          /// A <see cref="FileStreamResult"/> containing the file stream on success,
 | 
	
		
			
				|  |  |          /// or a <see cref="NotFoundResult"/> if item not found.
 | 
	
		
			
				|  |  |          /// </returns>
 | 
	
		
			
				|  |  | -        [HttpGet("Artists/{name}/Images/{imageType}/{imageIndex?}")]
 | 
	
		
			
				|  |  | -        [HttpHead("Artists/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadArtistImage")]
 | 
	
		
			
				|  |  | +        [HttpGet("Artists/{name}/Images/{imageType}/{imageIndex}")]
 | 
	
		
			
				|  |  | +        [HttpHead("Artists/{name}/Images/{imageType}/{imageIndex}", Name = "HeadArtistImage")]
 | 
	
		
			
				|  |  |          [ProducesResponseType(StatusCodes.Status200OK)]
 | 
	
		
			
				|  |  |          [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
	
		
			
				|  |  |          [ProducesImageFile]
 | 
	
	
		
			
				|  | @@ -586,8 +803,8 @@ namespace Jellyfin.Api.Controllers
 | 
	
		
			
				|  |  |          /// A <see cref="FileStreamResult"/> containing the file stream on success,
 | 
	
		
			
				|  |  |          /// or a <see cref="NotFoundResult"/> if item not found.
 | 
	
		
			
				|  |  |          /// </returns>
 | 
	
		
			
				|  |  | -        [HttpGet("Genres/{name}/Images/{imageType}/{imageIndex?}")]
 | 
	
		
			
				|  |  | -        [HttpHead("Genres/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadGenreImage")]
 | 
	
		
			
				|  |  | +        [HttpGet("Genres/{name}/Images/{imageType}")]
 | 
	
		
			
				|  |  | +        [HttpHead("Genres/{name}/Images/{imageType}", Name = "HeadGenreImage")]
 | 
	
		
			
				|  |  |          [ProducesResponseType(StatusCodes.Status200OK)]
 | 
	
		
			
				|  |  |          [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
	
		
			
				|  |  |          [ProducesImageFile]
 | 
	
	
		
			
				|  | @@ -608,7 +825,7 @@ namespace Jellyfin.Api.Controllers
 | 
	
		
			
				|  |  |              [FromQuery] int? blur,
 | 
	
		
			
				|  |  |              [FromQuery] string? backgroundColor,
 | 
	
		
			
				|  |  |              [FromQuery] string? foregroundLayer,
 | 
	
		
			
				|  |  | -            [FromRoute] int? imageIndex = null)
 | 
	
		
			
				|  |  | +            [FromQuery] int? imageIndex)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              var item = _libraryManager.GetGenre(name);
 | 
	
		
			
				|  |  |              if (item == null)
 | 
	
	
		
			
				|  | @@ -640,10 +857,11 @@ namespace Jellyfin.Api.Controllers
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          /// <summary>
 | 
	
		
			
				|  |  | -        /// Get music genre image by name.
 | 
	
		
			
				|  |  | +        /// Get genre image by name.
 | 
	
		
			
				|  |  |          /// </summary>
 | 
	
		
			
				|  |  | -        /// <param name="name">Music genre name.</param>
 | 
	
		
			
				|  |  | +        /// <param name="name">Genre name.</param>
 | 
	
		
			
				|  |  |          /// <param name="imageType">Image type.</param>
 | 
	
		
			
				|  |  | +        /// <param name="imageIndex">Image index.</param>
 | 
	
		
			
				|  |  |          /// <param name="tag">Optional. Supply the cache tag from the item object to receive strong caching headers.</param>
 | 
	
		
			
				|  |  |          /// <param name="format">Determines the output format of the image - original,gif,jpg,png.</param>
 | 
	
		
			
				|  |  |          /// <param name="maxWidth">The maximum image width to return.</param>
 | 
	
	
		
			
				|  | @@ -658,21 +876,21 @@ namespace Jellyfin.Api.Controllers
 | 
	
		
			
				|  |  |          /// <param name="blur">Optional. Blur image.</param>
 | 
	
		
			
				|  |  |          /// <param name="backgroundColor">Optional. Apply a background color for transparent images.</param>
 | 
	
		
			
				|  |  |          /// <param name="foregroundLayer">Optional. Apply a foreground layer on top of the image.</param>
 | 
	
		
			
				|  |  | -        /// <param name="imageIndex">Image index.</param>
 | 
	
		
			
				|  |  |          /// <response code="200">Image stream returned.</response>
 | 
	
		
			
				|  |  |          /// <response code="404">Item not found.</response>
 | 
	
		
			
				|  |  |          /// <returns>
 | 
	
		
			
				|  |  |          /// A <see cref="FileStreamResult"/> containing the file stream on success,
 | 
	
		
			
				|  |  |          /// or a <see cref="NotFoundResult"/> if item not found.
 | 
	
		
			
				|  |  |          /// </returns>
 | 
	
		
			
				|  |  | -        [HttpGet("MusicGenres/{name}/Images/{imageType}/{imageIndex?}")]
 | 
	
		
			
				|  |  | -        [HttpHead("MusicGenres/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadMusicGenreImage")]
 | 
	
		
			
				|  |  | +        [HttpGet("Genres/{name}/Images/{imageType}/{imageIndex}")]
 | 
	
		
			
				|  |  | +        [HttpHead("Genres/{name}/Images/{imageType}/{imageIndex}", Name = "HeadGenreImageByIndex")]
 | 
	
		
			
				|  |  |          [ProducesResponseType(StatusCodes.Status200OK)]
 | 
	
		
			
				|  |  |          [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
	
		
			
				|  |  |          [ProducesImageFile]
 | 
	
		
			
				|  |  | -        public async Task<ActionResult> GetMusicGenreImage(
 | 
	
		
			
				|  |  | +        public async Task<ActionResult> GetGenreImageByIndex(
 | 
	
		
			
				|  |  |              [FromRoute, Required] string name,
 | 
	
		
			
				|  |  |              [FromRoute, Required] ImageType imageType,
 | 
	
		
			
				|  |  | +            [FromRoute, Required] int imageIndex,
 | 
	
		
			
				|  |  |              [FromQuery] string tag,
 | 
	
		
			
				|  |  |              [FromQuery] ImageFormat? format,
 | 
	
		
			
				|  |  |              [FromQuery] int? maxWidth,
 | 
	
	
		
			
				|  | @@ -686,10 +904,9 @@ namespace Jellyfin.Api.Controllers
 | 
	
		
			
				|  |  |              [FromQuery] bool? addPlayedIndicator,
 | 
	
		
			
				|  |  |              [FromQuery] int? blur,
 | 
	
		
			
				|  |  |              [FromQuery] string? backgroundColor,
 | 
	
		
			
				|  |  | -            [FromQuery] string? foregroundLayer,
 | 
	
		
			
				|  |  | -            [FromRoute] int? imageIndex = null)
 | 
	
		
			
				|  |  | +            [FromQuery] string? foregroundLayer)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            var item = _libraryManager.GetMusicGenre(name);
 | 
	
		
			
				|  |  | +            var item = _libraryManager.GetGenre(name);
 | 
	
		
			
				|  |  |              if (item == null)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  |                  return NotFound();
 | 
	
	
		
			
				|  | @@ -719,9 +936,9 @@ namespace Jellyfin.Api.Controllers
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          /// <summary>
 | 
	
		
			
				|  |  | -        /// Get person image by name.
 | 
	
		
			
				|  |  | +        /// Get music genre image by name.
 | 
	
		
			
				|  |  |          /// </summary>
 | 
	
		
			
				|  |  | -        /// <param name="name">Person name.</param>
 | 
	
		
			
				|  |  | +        /// <param name="name">Music genre name.</param>
 | 
	
		
			
				|  |  |          /// <param name="imageType">Image type.</param>
 | 
	
		
			
				|  |  |          /// <param name="tag">Optional. Supply the cache tag from the item object to receive strong caching headers.</param>
 | 
	
		
			
				|  |  |          /// <param name="format">Determines the output format of the image - original,gif,jpg,png.</param>
 | 
	
	
		
			
				|  | @@ -744,12 +961,12 @@ namespace Jellyfin.Api.Controllers
 | 
	
		
			
				|  |  |          /// A <see cref="FileStreamResult"/> containing the file stream on success,
 | 
	
		
			
				|  |  |          /// or a <see cref="NotFoundResult"/> if item not found.
 | 
	
		
			
				|  |  |          /// </returns>
 | 
	
		
			
				|  |  | -        [HttpGet("Persons/{name}/Images/{imageType}/{imageIndex?}")]
 | 
	
		
			
				|  |  | -        [HttpHead("Persons/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadPersonImage")]
 | 
	
		
			
				|  |  | +        [HttpGet("MusicGenres/{name}/Images/{imageType}")]
 | 
	
		
			
				|  |  | +        [HttpHead("MusicGenres/{name}/Images/{imageType}", Name = "HeadMusicGenreImage")]
 | 
	
		
			
				|  |  |          [ProducesResponseType(StatusCodes.Status200OK)]
 | 
	
		
			
				|  |  |          [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
	
		
			
				|  |  |          [ProducesImageFile]
 | 
	
		
			
				|  |  | -        public async Task<ActionResult> GetPersonImage(
 | 
	
		
			
				|  |  | +        public async Task<ActionResult> GetMusicGenreImage(
 | 
	
		
			
				|  |  |              [FromRoute, Required] string name,
 | 
	
		
			
				|  |  |              [FromRoute, Required] ImageType imageType,
 | 
	
		
			
				|  |  |              [FromQuery] string tag,
 | 
	
	
		
			
				|  | @@ -766,9 +983,9 @@ namespace Jellyfin.Api.Controllers
 | 
	
		
			
				|  |  |              [FromQuery] int? blur,
 | 
	
		
			
				|  |  |              [FromQuery] string? backgroundColor,
 | 
	
		
			
				|  |  |              [FromQuery] string? foregroundLayer,
 | 
	
		
			
				|  |  | -            [FromRoute] int? imageIndex = null)
 | 
	
		
			
				|  |  | +            [FromQuery] int? imageIndex)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            var item = _libraryManager.GetPerson(name);
 | 
	
		
			
				|  |  | +            var item = _libraryManager.GetMusicGenre(name);
 | 
	
		
			
				|  |  |              if (item == null)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  |                  return NotFound();
 | 
	
	
		
			
				|  | @@ -798,10 +1015,11 @@ namespace Jellyfin.Api.Controllers
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          /// <summary>
 | 
	
		
			
				|  |  | -        /// Get studio image by name.
 | 
	
		
			
				|  |  | +        /// Get music genre image by name.
 | 
	
		
			
				|  |  |          /// </summary>
 | 
	
		
			
				|  |  | -        /// <param name="name">Studio name.</param>
 | 
	
		
			
				|  |  | +        /// <param name="name">Music genre name.</param>
 | 
	
		
			
				|  |  |          /// <param name="imageType">Image type.</param>
 | 
	
		
			
				|  |  | +        /// <param name="imageIndex">Image index.</param>
 | 
	
		
			
				|  |  |          /// <param name="tag">Optional. Supply the cache tag from the item object to receive strong caching headers.</param>
 | 
	
		
			
				|  |  |          /// <param name="format">Determines the output format of the image - original,gif,jpg,png.</param>
 | 
	
		
			
				|  |  |          /// <param name="maxWidth">The maximum image width to return.</param>
 | 
	
	
		
			
				|  | @@ -816,23 +1034,23 @@ namespace Jellyfin.Api.Controllers
 | 
	
		
			
				|  |  |          /// <param name="blur">Optional. Blur image.</param>
 | 
	
		
			
				|  |  |          /// <param name="backgroundColor">Optional. Apply a background color for transparent images.</param>
 | 
	
		
			
				|  |  |          /// <param name="foregroundLayer">Optional. Apply a foreground layer on top of the image.</param>
 | 
	
		
			
				|  |  | -        /// <param name="imageIndex">Image index.</param>
 | 
	
		
			
				|  |  |          /// <response code="200">Image stream returned.</response>
 | 
	
		
			
				|  |  |          /// <response code="404">Item not found.</response>
 | 
	
		
			
				|  |  |          /// <returns>
 | 
	
		
			
				|  |  |          /// A <see cref="FileStreamResult"/> containing the file stream on success,
 | 
	
		
			
				|  |  |          /// or a <see cref="NotFoundResult"/> if item not found.
 | 
	
		
			
				|  |  |          /// </returns>
 | 
	
		
			
				|  |  | -        [HttpGet("Studios/{name}/Images/{imageType}/{imageIndex?}")]
 | 
	
		
			
				|  |  | -        [HttpHead("Studios/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadStudioImage")]
 | 
	
		
			
				|  |  | +        [HttpGet("MusicGenres/{name}/Images/{imageType}/{imageIndex}")]
 | 
	
		
			
				|  |  | +        [HttpHead("MusicGenres/{name}/Images/{imageType}/{imageIndex}", Name = "HeadMusicGenreImageByIndex")]
 | 
	
		
			
				|  |  |          [ProducesResponseType(StatusCodes.Status200OK)]
 | 
	
		
			
				|  |  |          [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
	
		
			
				|  |  |          [ProducesImageFile]
 | 
	
		
			
				|  |  | -        public async Task<ActionResult> GetStudioImage(
 | 
	
		
			
				|  |  | +        public async Task<ActionResult> GetMusicGenreImageByIndex(
 | 
	
		
			
				|  |  |              [FromRoute, Required] string name,
 | 
	
		
			
				|  |  |              [FromRoute, Required] ImageType imageType,
 | 
	
		
			
				|  |  | -            [FromRoute, Required] string tag,
 | 
	
		
			
				|  |  | -            [FromRoute, Required] ImageFormat format,
 | 
	
		
			
				|  |  | +            [FromRoute, Required] int imageIndex,
 | 
	
		
			
				|  |  | +            [FromQuery] string tag,
 | 
	
		
			
				|  |  | +            [FromQuery] ImageFormat? format,
 | 
	
		
			
				|  |  |              [FromQuery] int? maxWidth,
 | 
	
		
			
				|  |  |              [FromQuery] int? maxHeight,
 | 
	
		
			
				|  |  |              [FromQuery] double? percentPlayed,
 | 
	
	
		
			
				|  | @@ -844,10 +1062,9 @@ namespace Jellyfin.Api.Controllers
 | 
	
		
			
				|  |  |              [FromQuery] bool? addPlayedIndicator,
 | 
	
		
			
				|  |  |              [FromQuery] int? blur,
 | 
	
		
			
				|  |  |              [FromQuery] string? backgroundColor,
 | 
	
		
			
				|  |  | -            [FromQuery] string? foregroundLayer,
 | 
	
		
			
				|  |  | -            [FromRoute] int? imageIndex = null)
 | 
	
		
			
				|  |  | +            [FromQuery] string? foregroundLayer)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            var item = _libraryManager.GetStudio(name);
 | 
	
		
			
				|  |  | +            var item = _libraryManager.GetMusicGenre(name);
 | 
	
		
			
				|  |  |              if (item == null)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  |                  return NotFound();
 | 
	
	
		
			
				|  | @@ -877,9 +1094,9 @@ namespace Jellyfin.Api.Controllers
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          /// <summary>
 | 
	
		
			
				|  |  | -        /// Get user profile image.
 | 
	
		
			
				|  |  | +        /// Get person image by name.
 | 
	
		
			
				|  |  |          /// </summary>
 | 
	
		
			
				|  |  | -        /// <param name="userId">User id.</param>
 | 
	
		
			
				|  |  | +        /// <param name="name">Person name.</param>
 | 
	
		
			
				|  |  |          /// <param name="imageType">Image type.</param>
 | 
	
		
			
				|  |  |          /// <param name="tag">Optional. Supply the cache tag from the item object to receive strong caching headers.</param>
 | 
	
		
			
				|  |  |          /// <param name="format">Determines the output format of the image - original,gif,jpg,png.</param>
 | 
	
	
		
			
				|  | @@ -902,15 +1119,15 @@ namespace Jellyfin.Api.Controllers
 | 
	
		
			
				|  |  |          /// A <see cref="FileStreamResult"/> containing the file stream on success,
 | 
	
		
			
				|  |  |          /// or a <see cref="NotFoundResult"/> if item not found.
 | 
	
		
			
				|  |  |          /// </returns>
 | 
	
		
			
				|  |  | -        [HttpGet("Users/{userId}/Images/{imageType}/{imageIndex?}")]
 | 
	
		
			
				|  |  | -        [HttpHead("Users/{userId}/Images/{imageType}/{imageIndex?}", Name = "HeadUserImage")]
 | 
	
		
			
				|  |  | +        [HttpGet("Persons/{name}/Images/{imageType}")]
 | 
	
		
			
				|  |  | +        [HttpHead("Persons/{name}/Images/{imageType}", Name = "HeadPersonImage")]
 | 
	
		
			
				|  |  |          [ProducesResponseType(StatusCodes.Status200OK)]
 | 
	
		
			
				|  |  |          [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
	
		
			
				|  |  |          [ProducesImageFile]
 | 
	
		
			
				|  |  | -        public async Task<ActionResult> GetUserImage(
 | 
	
		
			
				|  |  | -            [FromRoute, Required] Guid userId,
 | 
	
		
			
				|  |  | +        public async Task<ActionResult> GetPersonImage(
 | 
	
		
			
				|  |  | +            [FromRoute, Required] string name,
 | 
	
		
			
				|  |  |              [FromRoute, Required] ImageType imageType,
 | 
	
		
			
				|  |  | -            [FromQuery] string? tag,
 | 
	
		
			
				|  |  | +            [FromQuery] string tag,
 | 
	
		
			
				|  |  |              [FromQuery] ImageFormat? format,
 | 
	
		
			
				|  |  |              [FromQuery] int? maxWidth,
 | 
	
		
			
				|  |  |              [FromQuery] int? maxHeight,
 | 
	
	
		
			
				|  | @@ -924,7 +1141,420 @@ namespace Jellyfin.Api.Controllers
 | 
	
		
			
				|  |  |              [FromQuery] int? blur,
 | 
	
		
			
				|  |  |              [FromQuery] string? backgroundColor,
 | 
	
		
			
				|  |  |              [FromQuery] string? foregroundLayer,
 | 
	
		
			
				|  |  | -            [FromRoute] int? imageIndex = null)
 | 
	
		
			
				|  |  | +            [FromQuery] int? imageIndex)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var item = _libraryManager.GetPerson(name);
 | 
	
		
			
				|  |  | +            if (item == null)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return NotFound();
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return await GetImageInternal(
 | 
	
		
			
				|  |  | +                    item.Id,
 | 
	
		
			
				|  |  | +                    imageType,
 | 
	
		
			
				|  |  | +                    imageIndex,
 | 
	
		
			
				|  |  | +                    tag,
 | 
	
		
			
				|  |  | +                    format,
 | 
	
		
			
				|  |  | +                    maxWidth,
 | 
	
		
			
				|  |  | +                    maxHeight,
 | 
	
		
			
				|  |  | +                    percentPlayed,
 | 
	
		
			
				|  |  | +                    unplayedCount,
 | 
	
		
			
				|  |  | +                    width,
 | 
	
		
			
				|  |  | +                    height,
 | 
	
		
			
				|  |  | +                    quality,
 | 
	
		
			
				|  |  | +                    cropWhitespace,
 | 
	
		
			
				|  |  | +                    addPlayedIndicator,
 | 
	
		
			
				|  |  | +                    blur,
 | 
	
		
			
				|  |  | +                    backgroundColor,
 | 
	
		
			
				|  |  | +                    foregroundLayer,
 | 
	
		
			
				|  |  | +                    item,
 | 
	
		
			
				|  |  | +                    Request.Method.Equals(HttpMethods.Head, StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  | +                .ConfigureAwait(false);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Get person image by name.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        /// <param name="name">Person name.</param>
 | 
	
		
			
				|  |  | +        /// <param name="imageType">Image type.</param>
 | 
	
		
			
				|  |  | +        /// <param name="imageIndex">Image index.</param>
 | 
	
		
			
				|  |  | +        /// <param name="tag">Optional. Supply the cache tag from the item object to receive strong caching headers.</param>
 | 
	
		
			
				|  |  | +        /// <param name="format">Determines the output format of the image - original,gif,jpg,png.</param>
 | 
	
		
			
				|  |  | +        /// <param name="maxWidth">The maximum image width to return.</param>
 | 
	
		
			
				|  |  | +        /// <param name="maxHeight">The maximum image height to return.</param>
 | 
	
		
			
				|  |  | +        /// <param name="percentPlayed">Optional. Percent to render for the percent played overlay.</param>
 | 
	
		
			
				|  |  | +        /// <param name="unplayedCount">Optional. Unplayed count overlay to render.</param>
 | 
	
		
			
				|  |  | +        /// <param name="width">The fixed image width to return.</param>
 | 
	
		
			
				|  |  | +        /// <param name="height">The fixed image height to return.</param>
 | 
	
		
			
				|  |  | +        /// <param name="quality">Optional. Quality setting, from 0-100. Defaults to 90 and should suffice in most cases.</param>
 | 
	
		
			
				|  |  | +        /// <param name="cropWhitespace">Optional. Specify if whitespace should be cropped out of the image. True/False. If unspecified, whitespace will be cropped from logos and clear art.</param>
 | 
	
		
			
				|  |  | +        /// <param name="addPlayedIndicator">Optional. Add a played indicator.</param>
 | 
	
		
			
				|  |  | +        /// <param name="blur">Optional. Blur image.</param>
 | 
	
		
			
				|  |  | +        /// <param name="backgroundColor">Optional. Apply a background color for transparent images.</param>
 | 
	
		
			
				|  |  | +        /// <param name="foregroundLayer">Optional. Apply a foreground layer on top of the image.</param>
 | 
	
		
			
				|  |  | +        /// <response code="200">Image stream returned.</response>
 | 
	
		
			
				|  |  | +        /// <response code="404">Item not found.</response>
 | 
	
		
			
				|  |  | +        /// <returns>
 | 
	
		
			
				|  |  | +        /// A <see cref="FileStreamResult"/> containing the file stream on success,
 | 
	
		
			
				|  |  | +        /// or a <see cref="NotFoundResult"/> if item not found.
 | 
	
		
			
				|  |  | +        /// </returns>
 | 
	
		
			
				|  |  | +        [HttpGet("Persons/{name}/Images/{imageType}/{imageIndex}")]
 | 
	
		
			
				|  |  | +        [HttpHead("Persons/{name}/Images/{imageType}/{imageIndex}", Name = "HeadPersonImageByIndex")]
 | 
	
		
			
				|  |  | +        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
	
		
			
				|  |  | +        [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
	
		
			
				|  |  | +        [ProducesImageFile]
 | 
	
		
			
				|  |  | +        public async Task<ActionResult> GetPersonImageByIndex(
 | 
	
		
			
				|  |  | +            [FromRoute, Required] string name,
 | 
	
		
			
				|  |  | +            [FromRoute, Required] ImageType imageType,
 | 
	
		
			
				|  |  | +            [FromRoute, Required] int imageIndex,
 | 
	
		
			
				|  |  | +            [FromQuery] string tag,
 | 
	
		
			
				|  |  | +            [FromQuery] ImageFormat? format,
 | 
	
		
			
				|  |  | +            [FromQuery] int? maxWidth,
 | 
	
		
			
				|  |  | +            [FromQuery] int? maxHeight,
 | 
	
		
			
				|  |  | +            [FromQuery] double? percentPlayed,
 | 
	
		
			
				|  |  | +            [FromQuery] int? unplayedCount,
 | 
	
		
			
				|  |  | +            [FromQuery] int? width,
 | 
	
		
			
				|  |  | +            [FromQuery] int? height,
 | 
	
		
			
				|  |  | +            [FromQuery] int? quality,
 | 
	
		
			
				|  |  | +            [FromQuery] bool? cropWhitespace,
 | 
	
		
			
				|  |  | +            [FromQuery] bool? addPlayedIndicator,
 | 
	
		
			
				|  |  | +            [FromQuery] int? blur,
 | 
	
		
			
				|  |  | +            [FromQuery] string? backgroundColor,
 | 
	
		
			
				|  |  | +            [FromQuery] string? foregroundLayer)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var item = _libraryManager.GetPerson(name);
 | 
	
		
			
				|  |  | +            if (item == null)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return NotFound();
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return await GetImageInternal(
 | 
	
		
			
				|  |  | +                    item.Id,
 | 
	
		
			
				|  |  | +                    imageType,
 | 
	
		
			
				|  |  | +                    imageIndex,
 | 
	
		
			
				|  |  | +                    tag,
 | 
	
		
			
				|  |  | +                    format,
 | 
	
		
			
				|  |  | +                    maxWidth,
 | 
	
		
			
				|  |  | +                    maxHeight,
 | 
	
		
			
				|  |  | +                    percentPlayed,
 | 
	
		
			
				|  |  | +                    unplayedCount,
 | 
	
		
			
				|  |  | +                    width,
 | 
	
		
			
				|  |  | +                    height,
 | 
	
		
			
				|  |  | +                    quality,
 | 
	
		
			
				|  |  | +                    cropWhitespace,
 | 
	
		
			
				|  |  | +                    addPlayedIndicator,
 | 
	
		
			
				|  |  | +                    blur,
 | 
	
		
			
				|  |  | +                    backgroundColor,
 | 
	
		
			
				|  |  | +                    foregroundLayer,
 | 
	
		
			
				|  |  | +                    item,
 | 
	
		
			
				|  |  | +                    Request.Method.Equals(HttpMethods.Head, StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  | +                .ConfigureAwait(false);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Get studio image by name.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        /// <param name="name">Studio name.</param>
 | 
	
		
			
				|  |  | +        /// <param name="imageType">Image type.</param>
 | 
	
		
			
				|  |  | +        /// <param name="tag">Optional. Supply the cache tag from the item object to receive strong caching headers.</param>
 | 
	
		
			
				|  |  | +        /// <param name="format">Determines the output format of the image - original,gif,jpg,png.</param>
 | 
	
		
			
				|  |  | +        /// <param name="maxWidth">The maximum image width to return.</param>
 | 
	
		
			
				|  |  | +        /// <param name="maxHeight">The maximum image height to return.</param>
 | 
	
		
			
				|  |  | +        /// <param name="percentPlayed">Optional. Percent to render for the percent played overlay.</param>
 | 
	
		
			
				|  |  | +        /// <param name="unplayedCount">Optional. Unplayed count overlay to render.</param>
 | 
	
		
			
				|  |  | +        /// <param name="width">The fixed image width to return.</param>
 | 
	
		
			
				|  |  | +        /// <param name="height">The fixed image height to return.</param>
 | 
	
		
			
				|  |  | +        /// <param name="quality">Optional. Quality setting, from 0-100. Defaults to 90 and should suffice in most cases.</param>
 | 
	
		
			
				|  |  | +        /// <param name="cropWhitespace">Optional. Specify if whitespace should be cropped out of the image. True/False. If unspecified, whitespace will be cropped from logos and clear art.</param>
 | 
	
		
			
				|  |  | +        /// <param name="addPlayedIndicator">Optional. Add a played indicator.</param>
 | 
	
		
			
				|  |  | +        /// <param name="blur">Optional. Blur image.</param>
 | 
	
		
			
				|  |  | +        /// <param name="backgroundColor">Optional. Apply a background color for transparent images.</param>
 | 
	
		
			
				|  |  | +        /// <param name="foregroundLayer">Optional. Apply a foreground layer on top of the image.</param>
 | 
	
		
			
				|  |  | +        /// <param name="imageIndex">Image index.</param>
 | 
	
		
			
				|  |  | +        /// <response code="200">Image stream returned.</response>
 | 
	
		
			
				|  |  | +        /// <response code="404">Item not found.</response>
 | 
	
		
			
				|  |  | +        /// <returns>
 | 
	
		
			
				|  |  | +        /// A <see cref="FileStreamResult"/> containing the file stream on success,
 | 
	
		
			
				|  |  | +        /// or a <see cref="NotFoundResult"/> if item not found.
 | 
	
		
			
				|  |  | +        /// </returns>
 | 
	
		
			
				|  |  | +        [HttpGet("Studios/{name}/Images/{imageType}")]
 | 
	
		
			
				|  |  | +        [HttpHead("Studios/{name}/Images/{imageType}", Name = "HeadStudioImage")]
 | 
	
		
			
				|  |  | +        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
	
		
			
				|  |  | +        [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
	
		
			
				|  |  | +        [ProducesImageFile]
 | 
	
		
			
				|  |  | +        public async Task<ActionResult> GetStudioImage(
 | 
	
		
			
				|  |  | +            [FromRoute, Required] string name,
 | 
	
		
			
				|  |  | +            [FromRoute, Required] ImageType imageType,
 | 
	
		
			
				|  |  | +            [FromQuery] string? tag,
 | 
	
		
			
				|  |  | +            [FromQuery] ImageFormat? format,
 | 
	
		
			
				|  |  | +            [FromQuery] int? maxWidth,
 | 
	
		
			
				|  |  | +            [FromQuery] int? maxHeight,
 | 
	
		
			
				|  |  | +            [FromQuery] double? percentPlayed,
 | 
	
		
			
				|  |  | +            [FromQuery] int? unplayedCount,
 | 
	
		
			
				|  |  | +            [FromQuery] int? width,
 | 
	
		
			
				|  |  | +            [FromQuery] int? height,
 | 
	
		
			
				|  |  | +            [FromQuery] int? quality,
 | 
	
		
			
				|  |  | +            [FromQuery] bool? cropWhitespace,
 | 
	
		
			
				|  |  | +            [FromQuery] bool? addPlayedIndicator,
 | 
	
		
			
				|  |  | +            [FromQuery] int? blur,
 | 
	
		
			
				|  |  | +            [FromQuery] string? backgroundColor,
 | 
	
		
			
				|  |  | +            [FromQuery] string? foregroundLayer,
 | 
	
		
			
				|  |  | +            [FromQuery] int? imageIndex)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var item = _libraryManager.GetStudio(name);
 | 
	
		
			
				|  |  | +            if (item == null)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return NotFound();
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return await GetImageInternal(
 | 
	
		
			
				|  |  | +                    item.Id,
 | 
	
		
			
				|  |  | +                    imageType,
 | 
	
		
			
				|  |  | +                    imageIndex,
 | 
	
		
			
				|  |  | +                    tag,
 | 
	
		
			
				|  |  | +                    format,
 | 
	
		
			
				|  |  | +                    maxWidth,
 | 
	
		
			
				|  |  | +                    maxHeight,
 | 
	
		
			
				|  |  | +                    percentPlayed,
 | 
	
		
			
				|  |  | +                    unplayedCount,
 | 
	
		
			
				|  |  | +                    width,
 | 
	
		
			
				|  |  | +                    height,
 | 
	
		
			
				|  |  | +                    quality,
 | 
	
		
			
				|  |  | +                    cropWhitespace,
 | 
	
		
			
				|  |  | +                    addPlayedIndicator,
 | 
	
		
			
				|  |  | +                    blur,
 | 
	
		
			
				|  |  | +                    backgroundColor,
 | 
	
		
			
				|  |  | +                    foregroundLayer,
 | 
	
		
			
				|  |  | +                    item,
 | 
	
		
			
				|  |  | +                    Request.Method.Equals(HttpMethods.Head, StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  | +                .ConfigureAwait(false);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Get studio image by name.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        /// <param name="name">Studio name.</param>
 | 
	
		
			
				|  |  | +        /// <param name="imageType">Image type.</param>
 | 
	
		
			
				|  |  | +        /// <param name="imageIndex">Image index.</param>
 | 
	
		
			
				|  |  | +        /// <param name="tag">Optional. Supply the cache tag from the item object to receive strong caching headers.</param>
 | 
	
		
			
				|  |  | +        /// <param name="format">Determines the output format of the image - original,gif,jpg,png.</param>
 | 
	
		
			
				|  |  | +        /// <param name="maxWidth">The maximum image width to return.</param>
 | 
	
		
			
				|  |  | +        /// <param name="maxHeight">The maximum image height to return.</param>
 | 
	
		
			
				|  |  | +        /// <param name="percentPlayed">Optional. Percent to render for the percent played overlay.</param>
 | 
	
		
			
				|  |  | +        /// <param name="unplayedCount">Optional. Unplayed count overlay to render.</param>
 | 
	
		
			
				|  |  | +        /// <param name="width">The fixed image width to return.</param>
 | 
	
		
			
				|  |  | +        /// <param name="height">The fixed image height to return.</param>
 | 
	
		
			
				|  |  | +        /// <param name="quality">Optional. Quality setting, from 0-100. Defaults to 90 and should suffice in most cases.</param>
 | 
	
		
			
				|  |  | +        /// <param name="cropWhitespace">Optional. Specify if whitespace should be cropped out of the image. True/False. If unspecified, whitespace will be cropped from logos and clear art.</param>
 | 
	
		
			
				|  |  | +        /// <param name="addPlayedIndicator">Optional. Add a played indicator.</param>
 | 
	
		
			
				|  |  | +        /// <param name="blur">Optional. Blur image.</param>
 | 
	
		
			
				|  |  | +        /// <param name="backgroundColor">Optional. Apply a background color for transparent images.</param>
 | 
	
		
			
				|  |  | +        /// <param name="foregroundLayer">Optional. Apply a foreground layer on top of the image.</param>
 | 
	
		
			
				|  |  | +        /// <response code="200">Image stream returned.</response>
 | 
	
		
			
				|  |  | +        /// <response code="404">Item not found.</response>
 | 
	
		
			
				|  |  | +        /// <returns>
 | 
	
		
			
				|  |  | +        /// A <see cref="FileStreamResult"/> containing the file stream on success,
 | 
	
		
			
				|  |  | +        /// or a <see cref="NotFoundResult"/> if item not found.
 | 
	
		
			
				|  |  | +        /// </returns>
 | 
	
		
			
				|  |  | +        [HttpGet("Studios/{name}/Images/{imageType}/{imageIndex}")]
 | 
	
		
			
				|  |  | +        [HttpHead("Studios/{name}/Images/{imageType}/{imageIndex}", Name = "HeadStudioImageByIndex")]
 | 
	
		
			
				|  |  | +        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
	
		
			
				|  |  | +        [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
	
		
			
				|  |  | +        [ProducesImageFile]
 | 
	
		
			
				|  |  | +        public async Task<ActionResult> GetStudioImageByIndex(
 | 
	
		
			
				|  |  | +            [FromRoute, Required] string name,
 | 
	
		
			
				|  |  | +            [FromRoute, Required] ImageType imageType,
 | 
	
		
			
				|  |  | +            [FromRoute, Required] int imageIndex,
 | 
	
		
			
				|  |  | +            [FromQuery] string? tag,
 | 
	
		
			
				|  |  | +            [FromQuery] ImageFormat? format,
 | 
	
		
			
				|  |  | +            [FromQuery] int? maxWidth,
 | 
	
		
			
				|  |  | +            [FromQuery] int? maxHeight,
 | 
	
		
			
				|  |  | +            [FromQuery] double? percentPlayed,
 | 
	
		
			
				|  |  | +            [FromQuery] int? unplayedCount,
 | 
	
		
			
				|  |  | +            [FromQuery] int? width,
 | 
	
		
			
				|  |  | +            [FromQuery] int? height,
 | 
	
		
			
				|  |  | +            [FromQuery] int? quality,
 | 
	
		
			
				|  |  | +            [FromQuery] bool? cropWhitespace,
 | 
	
		
			
				|  |  | +            [FromQuery] bool? addPlayedIndicator,
 | 
	
		
			
				|  |  | +            [FromQuery] int? blur,
 | 
	
		
			
				|  |  | +            [FromQuery] string? backgroundColor,
 | 
	
		
			
				|  |  | +            [FromQuery] string? foregroundLayer)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var item = _libraryManager.GetStudio(name);
 | 
	
		
			
				|  |  | +            if (item == null)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return NotFound();
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return await GetImageInternal(
 | 
	
		
			
				|  |  | +                    item.Id,
 | 
	
		
			
				|  |  | +                    imageType,
 | 
	
		
			
				|  |  | +                    imageIndex,
 | 
	
		
			
				|  |  | +                    tag,
 | 
	
		
			
				|  |  | +                    format,
 | 
	
		
			
				|  |  | +                    maxWidth,
 | 
	
		
			
				|  |  | +                    maxHeight,
 | 
	
		
			
				|  |  | +                    percentPlayed,
 | 
	
		
			
				|  |  | +                    unplayedCount,
 | 
	
		
			
				|  |  | +                    width,
 | 
	
		
			
				|  |  | +                    height,
 | 
	
		
			
				|  |  | +                    quality,
 | 
	
		
			
				|  |  | +                    cropWhitespace,
 | 
	
		
			
				|  |  | +                    addPlayedIndicator,
 | 
	
		
			
				|  |  | +                    blur,
 | 
	
		
			
				|  |  | +                    backgroundColor,
 | 
	
		
			
				|  |  | +                    foregroundLayer,
 | 
	
		
			
				|  |  | +                    item,
 | 
	
		
			
				|  |  | +                    Request.Method.Equals(HttpMethods.Head, StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  | +                .ConfigureAwait(false);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Get user profile image.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        /// <param name="userId">User id.</param>
 | 
	
		
			
				|  |  | +        /// <param name="imageType">Image type.</param>
 | 
	
		
			
				|  |  | +        /// <param name="tag">Optional. Supply the cache tag from the item object to receive strong caching headers.</param>
 | 
	
		
			
				|  |  | +        /// <param name="format">Determines the output format of the image - original,gif,jpg,png.</param>
 | 
	
		
			
				|  |  | +        /// <param name="maxWidth">The maximum image width to return.</param>
 | 
	
		
			
				|  |  | +        /// <param name="maxHeight">The maximum image height to return.</param>
 | 
	
		
			
				|  |  | +        /// <param name="percentPlayed">Optional. Percent to render for the percent played overlay.</param>
 | 
	
		
			
				|  |  | +        /// <param name="unplayedCount">Optional. Unplayed count overlay to render.</param>
 | 
	
		
			
				|  |  | +        /// <param name="width">The fixed image width to return.</param>
 | 
	
		
			
				|  |  | +        /// <param name="height">The fixed image height to return.</param>
 | 
	
		
			
				|  |  | +        /// <param name="quality">Optional. Quality setting, from 0-100. Defaults to 90 and should suffice in most cases.</param>
 | 
	
		
			
				|  |  | +        /// <param name="cropWhitespace">Optional. Specify if whitespace should be cropped out of the image. True/False. If unspecified, whitespace will be cropped from logos and clear art.</param>
 | 
	
		
			
				|  |  | +        /// <param name="addPlayedIndicator">Optional. Add a played indicator.</param>
 | 
	
		
			
				|  |  | +        /// <param name="blur">Optional. Blur image.</param>
 | 
	
		
			
				|  |  | +        /// <param name="backgroundColor">Optional. Apply a background color for transparent images.</param>
 | 
	
		
			
				|  |  | +        /// <param name="foregroundLayer">Optional. Apply a foreground layer on top of the image.</param>
 | 
	
		
			
				|  |  | +        /// <param name="imageIndex">Image index.</param>
 | 
	
		
			
				|  |  | +        /// <response code="200">Image stream returned.</response>
 | 
	
		
			
				|  |  | +        /// <response code="404">Item not found.</response>
 | 
	
		
			
				|  |  | +        /// <returns>
 | 
	
		
			
				|  |  | +        /// A <see cref="FileStreamResult"/> containing the file stream on success,
 | 
	
		
			
				|  |  | +        /// or a <see cref="NotFoundResult"/> if item not found.
 | 
	
		
			
				|  |  | +        /// </returns>
 | 
	
		
			
				|  |  | +        [HttpGet("Users/{userId}/Images/{imageType}")]
 | 
	
		
			
				|  |  | +        [HttpHead("Users/{userId}/Images/{imageType}", Name = "HeadUserImage")]
 | 
	
		
			
				|  |  | +        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
	
		
			
				|  |  | +        [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
	
		
			
				|  |  | +        [ProducesImageFile]
 | 
	
		
			
				|  |  | +        public async Task<ActionResult> GetUserImage(
 | 
	
		
			
				|  |  | +            [FromRoute, Required] Guid userId,
 | 
	
		
			
				|  |  | +            [FromRoute, Required] ImageType imageType,
 | 
	
		
			
				|  |  | +            [FromQuery] string? tag,
 | 
	
		
			
				|  |  | +            [FromQuery] ImageFormat? format,
 | 
	
		
			
				|  |  | +            [FromQuery] int? maxWidth,
 | 
	
		
			
				|  |  | +            [FromQuery] int? maxHeight,
 | 
	
		
			
				|  |  | +            [FromQuery] double? percentPlayed,
 | 
	
		
			
				|  |  | +            [FromQuery] int? unplayedCount,
 | 
	
		
			
				|  |  | +            [FromQuery] int? width,
 | 
	
		
			
				|  |  | +            [FromQuery] int? height,
 | 
	
		
			
				|  |  | +            [FromQuery] int? quality,
 | 
	
		
			
				|  |  | +            [FromQuery] bool? cropWhitespace,
 | 
	
		
			
				|  |  | +            [FromQuery] bool? addPlayedIndicator,
 | 
	
		
			
				|  |  | +            [FromQuery] int? blur,
 | 
	
		
			
				|  |  | +            [FromQuery] string? backgroundColor,
 | 
	
		
			
				|  |  | +            [FromQuery] string? foregroundLayer,
 | 
	
		
			
				|  |  | +            [FromQuery] int? imageIndex)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var user = _userManager.GetUserById(userId);
 | 
	
		
			
				|  |  | +            if (user == null)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return NotFound();
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var info = new ItemImageInfo
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                Path = user.ProfileImage.Path,
 | 
	
		
			
				|  |  | +                Type = ImageType.Profile,
 | 
	
		
			
				|  |  | +                DateModified = user.ProfileImage.LastModified
 | 
	
		
			
				|  |  | +            };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (width.HasValue)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                info.Width = width.Value;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (height.HasValue)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                info.Height = height.Value;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return await GetImageInternal(
 | 
	
		
			
				|  |  | +                    user.Id,
 | 
	
		
			
				|  |  | +                    imageType,
 | 
	
		
			
				|  |  | +                    imageIndex,
 | 
	
		
			
				|  |  | +                    tag,
 | 
	
		
			
				|  |  | +                    format,
 | 
	
		
			
				|  |  | +                    maxWidth,
 | 
	
		
			
				|  |  | +                    maxHeight,
 | 
	
		
			
				|  |  | +                    percentPlayed,
 | 
	
		
			
				|  |  | +                    unplayedCount,
 | 
	
		
			
				|  |  | +                    width,
 | 
	
		
			
				|  |  | +                    height,
 | 
	
		
			
				|  |  | +                    quality,
 | 
	
		
			
				|  |  | +                    cropWhitespace,
 | 
	
		
			
				|  |  | +                    addPlayedIndicator,
 | 
	
		
			
				|  |  | +                    blur,
 | 
	
		
			
				|  |  | +                    backgroundColor,
 | 
	
		
			
				|  |  | +                    foregroundLayer,
 | 
	
		
			
				|  |  | +                    null,
 | 
	
		
			
				|  |  | +                    Request.Method.Equals(HttpMethods.Head, StringComparison.OrdinalIgnoreCase),
 | 
	
		
			
				|  |  | +                    info)
 | 
	
		
			
				|  |  | +                .ConfigureAwait(false);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Get user profile image.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        /// <param name="userId">User id.</param>
 | 
	
		
			
				|  |  | +        /// <param name="imageType">Image type.</param>
 | 
	
		
			
				|  |  | +        /// <param name="imageIndex">Image index.</param>
 | 
	
		
			
				|  |  | +        /// <param name="tag">Optional. Supply the cache tag from the item object to receive strong caching headers.</param>
 | 
	
		
			
				|  |  | +        /// <param name="format">Determines the output format of the image - original,gif,jpg,png.</param>
 | 
	
		
			
				|  |  | +        /// <param name="maxWidth">The maximum image width to return.</param>
 | 
	
		
			
				|  |  | +        /// <param name="maxHeight">The maximum image height to return.</param>
 | 
	
		
			
				|  |  | +        /// <param name="percentPlayed">Optional. Percent to render for the percent played overlay.</param>
 | 
	
		
			
				|  |  | +        /// <param name="unplayedCount">Optional. Unplayed count overlay to render.</param>
 | 
	
		
			
				|  |  | +        /// <param name="width">The fixed image width to return.</param>
 | 
	
		
			
				|  |  | +        /// <param name="height">The fixed image height to return.</param>
 | 
	
		
			
				|  |  | +        /// <param name="quality">Optional. Quality setting, from 0-100. Defaults to 90 and should suffice in most cases.</param>
 | 
	
		
			
				|  |  | +        /// <param name="cropWhitespace">Optional. Specify if whitespace should be cropped out of the image. True/False. If unspecified, whitespace will be cropped from logos and clear art.</param>
 | 
	
		
			
				|  |  | +        /// <param name="addPlayedIndicator">Optional. Add a played indicator.</param>
 | 
	
		
			
				|  |  | +        /// <param name="blur">Optional. Blur image.</param>
 | 
	
		
			
				|  |  | +        /// <param name="backgroundColor">Optional. Apply a background color for transparent images.</param>
 | 
	
		
			
				|  |  | +        /// <param name="foregroundLayer">Optional. Apply a foreground layer on top of the image.</param>
 | 
	
		
			
				|  |  | +        /// <response code="200">Image stream returned.</response>
 | 
	
		
			
				|  |  | +        /// <response code="404">Item not found.</response>
 | 
	
		
			
				|  |  | +        /// <returns>
 | 
	
		
			
				|  |  | +        /// A <see cref="FileStreamResult"/> containing the file stream on success,
 | 
	
		
			
				|  |  | +        /// or a <see cref="NotFoundResult"/> if item not found.
 | 
	
		
			
				|  |  | +        /// </returns>
 | 
	
		
			
				|  |  | +        [HttpGet("Users/{userId}/Images/{imageType}/{imageIndex}")]
 | 
	
		
			
				|  |  | +        [HttpHead("Users/{userId}/Images/{imageType}/{imageIndex}", Name = "HeadUserImageByIndex")]
 | 
	
		
			
				|  |  | +        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
	
		
			
				|  |  | +        [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
	
		
			
				|  |  | +        [ProducesImageFile]
 | 
	
		
			
				|  |  | +        public async Task<ActionResult> GetUserImageByIndex(
 | 
	
		
			
				|  |  | +            [FromRoute, Required] Guid userId,
 | 
	
		
			
				|  |  | +            [FromRoute, Required] ImageType imageType,
 | 
	
		
			
				|  |  | +            [FromRoute, Required] int imageIndex,
 | 
	
		
			
				|  |  | +            [FromQuery] string? tag,
 | 
	
		
			
				|  |  | +            [FromQuery] ImageFormat? format,
 | 
	
		
			
				|  |  | +            [FromQuery] int? maxWidth,
 | 
	
		
			
				|  |  | +            [FromQuery] int? maxHeight,
 | 
	
		
			
				|  |  | +            [FromQuery] double? percentPlayed,
 | 
	
		
			
				|  |  | +            [FromQuery] int? unplayedCount,
 | 
	
		
			
				|  |  | +            [FromQuery] int? width,
 | 
	
		
			
				|  |  | +            [FromQuery] int? height,
 | 
	
		
			
				|  |  | +            [FromQuery] int? quality,
 | 
	
		
			
				|  |  | +            [FromQuery] bool? cropWhitespace,
 | 
	
		
			
				|  |  | +            [FromQuery] bool? addPlayedIndicator,
 | 
	
		
			
				|  |  | +            [FromQuery] int? blur,
 | 
	
		
			
				|  |  | +            [FromQuery] string? backgroundColor,
 | 
	
		
			
				|  |  | +            [FromQuery] string? foregroundLayer)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              var user = _userManager.GetUserById(userId);
 | 
	
		
			
				|  |  |              if (user == null)
 |