public static Image LoadImageFromIcon(this ResourceManager resourceManager, string path) { return(resourceManager.LoadImage(path, textureLoader => new LazyImage(resourceManager.DefaultImage, () => { var _log = Log.Get <ResourceManager>(); try { // Normalize path path = Path.GetFullPath(path); _log.Info($"Loading image from icon at path '{path}'..."); using (var bmpStream = new MemoryStream()) { var bmp = ThumbnailLoader.GetThumbnail(path, 50, 50, ThumbnailOptions.None); bmp.Save(bmpStream, System.Drawing.Imaging.ImageFormat.Bmp); // Convert to texture return textureLoader.Load(bmpStream.ToArray()); } } catch (Exception ex) { _log.Error($"Could not load image from icon: '{ex.Message}'.", ex); return ResourceManager.Instance.DefaultImage; } }))); }
public void Setup() { _fileSystem = new Mock <IFileSystem>(); _imageLoader = new Mock <IImageLoader>(); _storage = new Mock <IAttributeStorage>(); _loader = new ThumbnailLoader(_imageLoader.Object, _storage.Object, _fileSystem.Object); }
public string Generate(IYoutubeJob job) { var tags = ""; if (job.Video.Tags.Count > 0) { tags = job.Video.Tags.First(); } for (int i = 1; i < job.Video.Tags.Count; i++) { tags = $"{tags},{job.Video.Tags.ElementAt(i)}"; } var privacy = string.Empty; switch (job.Video.Privacy) { case Youtube.Interfaces.Model.Enums.PrivacyStatus.Public: privacy = "Öffentlich"; break; case Youtube.Interfaces.Model.Enums.PrivacyStatus.Unlisted: privacy = "Nicht gelistet"; break; case Youtube.Interfaces.Model.Enums.PrivacyStatus.Private: privacy = "Privat"; break; } return(string.Format( template, HttpUtility.HtmlEncode(job.Video.Title), HttpUtility.HtmlEncode(job.Account.Title), HttpUtility.HtmlEncode(job.Video.Privacy.ToString()), job.Video.PublishAt != null ? job.Video.PublishAt.Value.ToString("dd.MM.yyyy HH:mm") : "keine Veröffentlichung geplant", job.Video.Description.Length <= 500 ? job.Video.Description : $"{job.Video.Description.Substring(0, 497)}...", tags, ThumbnailLoader.LoadAsBase64(job.Video.ThumbnailPath, 192, 108) )); }
public string Generate(IYoutubeJob job) { var tags = ""; if (job.Video.Tags.Count > 0) { tags = job.Video.Tags.First(); } for (int i = 1; i < job.Video.Tags.Count; i++) { tags = $"{tags},{job.Video.Tags.ElementAt(i)}"; } var privacy = string.Empty; switch (job.Video.Privacy) { case Youtube.Interfaces.Model.Enums.PrivacyStatus.Public: privacy = "Öffentlich"; break; case Youtube.Interfaces.Model.Enums.PrivacyStatus.Unlisted: privacy = "Nicht gelistet"; break; case Youtube.Interfaces.Model.Enums.PrivacyStatus.Private: privacy = "Privat"; break; } return(string.Format( template, HttpUtility.HtmlEncode(job.Video.Title), HttpUtility.HtmlEncode(job.Account.Title), ThumbnailLoader.LoadAsBase64(job.Video.ThumbnailPath, 192, 108) )); }
public static IEnumerator MakeThumbnail(IEnumerable <ItemInfo> itemList, string outputDirectory, bool manualMode, bool dark) { Texture2D thumbBackground; try { if (manualMode && !Chainloader.PluginInfos.ContainsKey("KK_OrthographicCamera")) { throw new ArgumentException("Manual mode needs the OrthographicCamera plugin to work"); } if (itemList == null) { throw new ArgumentNullException(nameof(itemList)); } if (outputDirectory == null) { throw new ArgumentNullException(nameof(outputDirectory)); } if (!Directory.Exists(outputDirectory)) { throw new DirectoryNotFoundException("Output directory was not found: " + outputDirectory); } thumbBackground = ResourceUtils.GetEmbeddedResource(dark ? "thumb_background_dark.png" : "thumb_background.png").LoadTexture(); } catch (Exception ex) { QuickAccessBox.Logger.Log(LogLevel.Message | LogLevel.Error, "Failed to make thumbs: " + ex.Message); yield break; } RemoveAllItems(); yield return(null); // Spawn new image board > rectangle Singleton <Studio.Studio> .Instance.AddItem(1, 38, 671); yield return(null); var root = GameObject.Find("CommonSpace").transform; // Setup thumbnail pane var origPlane = root.Find("p_koi_stu_plane00_00"); foreach (var component in origPlane.GetComponents <MonoBehaviour>()) { // Needed to prevent kkpe from crashing the Object.Instantiate call below if (component.GetType().Name == "PoseController") { Object.DestroyImmediate(component); } } var copyPlane = Object.Instantiate(origPlane); copyPlane.gameObject.SetActive(true); RemoveAllItems(); var mat = copyPlane.GetComponent <MeshRenderer>().material; mat.mainTexture = thumbBackground; var camera = Camera.main; var cameraControl = camera.GetComponent <Studio.CameraControl>(); var alphaShot = camera.GetComponent <AlphaShot2>(); camera.orthographic = true; cameraControl.enabled = false; var createdCount = 0; foreach (var itemInfo in itemList) { if (itemInfo.IsSFX) { continue; } var thumbPath = Path.Combine(outputDirectory, itemInfo.CacheId + ".png"); if (File.Exists(thumbPath)) { continue; } if (ThumbnailLoader.CustomThumbnailAvailable(itemInfo)) { continue; } yield return(null); Console.WriteLine($"Spawning: FullName={itemInfo.FullName} FileName={itemInfo.FileName}"); itemInfo.AddItem(); createdCount++; yield return(null); var targets = root.Children(); var b = Utils.CalculateBounds(targets); if (b != null) { var bounds = b.Value; const float objectSizeAdjust = 0.5f; var objectSize = bounds.size.magnitude; var targetObj = targets.First(); if (_shootFromFrontGroups.Contains(itemInfo.GroupNo)) { // Look at the object from front, better for flat effects // Move the camera a long way away from the objects to avoid clipping // todo anything better? Not reliable camera.transform.position = (targetObj.position + targetObj.forward * objectSize) * 8; } else { // Use isometric angle since it has best chance of showing the object in an usable way // Move the camera a long way away from the objects to avoid clipping camera.transform.position = (bounds.center - targetObj.forward * objectSize - targetObj.right * objectSize + targetObj.up * objectSize) * 8; } camera.transform.LookAt(bounds.center); camera.orthographicSize = objectSize * objectSizeAdjust; void UpdateBackgroundPlane() { // Move the thumbnail pane in the opposite way from the camera and scale/align it so that it fills the camera view behind the item copyPlane.position = camera.transform.position + camera.transform.forward * (camera.transform.position - bounds.center).magnitude * 2; copyPlane.LookAt(camera.transform); copyPlane.localScale = new Vector3(objectSize / (16 / 9f) * 1.325F, objectSize * 1.325F, 1) * objectSizeAdjust; } if (manualMode) { cameraControl.enabled = true; yield return(new WaitUntil(() => { // Adjust for the new camera position objectSize = camera.orthographicSize / objectSizeAdjust; UpdateBackgroundPlane(); return Input.GetKeyDown(KeyCode.LeftShift) || Input.GetKey(KeyCode.Escape); })); cameraControl.enabled = false; } UpdateBackgroundPlane(); var result = alphaShot.Capture(64, 64, 1, true); try { File.WriteAllBytes(thumbPath, result); } catch (SystemException ex) { QuickAccessBox.Logger.Log(LogLevel.Message | LogLevel.Error, "Failed to write thumbnail file - " + ex.Message); } } else { QuickAccessBox.Logger.Log(LogLevel.Info, "No renderers to take capture of - " + itemInfo.FullName); } yield return(null); RemoveAllItems(); if (createdCount % 400 == 0) { Resources.UnloadUnusedAssets(); } if (Input.GetKey(KeyCode.Escape)) { break; } } cameraControl.enabled = true; camera.orthographic = false; Object.Destroy(thumbBackground); Object.Destroy(copyPlane.gameObject); QuickAccessBox.Logger.Log(LogLevel.Message, "Finished taking thumbnails!"); }
public static IEnumerator MakeThumbnail(IEnumerable <ItemInfo> itemList, string outputDirectory, bool manualMode, bool dark) { Texture2D thumbBackground; try { if (manualMode && !(Chainloader.PluginInfos.TryGetValue("KK_OrthographicCamera", out var plug) && plug.Metadata.Version >= new Version("1.1.1"))) { throw new ArgumentException("Manual mode needs the OrthographicCamera plugin (at least v1.1.1) to work"); } if (itemList == null) { throw new ArgumentNullException(nameof(itemList)); } if (outputDirectory == null) { throw new ArgumentNullException(nameof(outputDirectory)); } if (!Directory.Exists(outputDirectory)) { throw new DirectoryNotFoundException("Output directory was not found: " + outputDirectory); } thumbBackground = ResourceUtils.GetEmbeddedResource(dark ? "thumb_background_dark.png" : "thumb_background.png").LoadTexture(); } catch (Exception ex) { QuickAccessBox.Logger.Log(BepInEx.Logging.LogLevel.Message | BepInEx.Logging.LogLevel.Error, "Failed to make thumbs: " + ex.Message); yield break; } RemoveAllItems(); yield return(null); // Spawn new image board > rectangle Singleton <Studio.Studio> .Instance.AddItem(0, 18, 636); yield return(null); var root = GameObject.Find("CommonSpace").transform; // Setup thumbnail pane var origPlane = root.Find("p_ai_stu_kihon14_00alfa"); foreach (var component in origPlane.GetComponents <MonoBehaviour>()) { // Needed to prevent kkpe from crashing the Object.Instantiate call below if (component.GetType().Name == "PoseController") { Object.DestroyImmediate(component); } } var copyPlane = Object.Instantiate(origPlane, null); copyPlane.gameObject.SetActive(true); copyPlane.gameObject.name = "thumb_background"; var thumbRend = copyPlane.GetComponent <MeshRenderer>(); thumbRend.sortingOrder = -10; var thumbMat = thumbRend.material; thumbMat.mainTexture = thumbBackground; Object.DestroyImmediate(copyPlane.gameObject.GetComponent <ItemComponent>()); RemoveAllItems(); var camera = Camera.main; var cameraControl = camera.GetComponent <Cinemachine.CinemachineBrain>(); cameraControl.enabled = false; camera.orthographic = true; camera.farClipPlane = 1500000; var postProcessing = camera.GetComponent <PostProcessLayer>(); var screencap = (Screencap.ScreenshotManager)Chainloader.PluginInfos[Screencap.ScreenshotManager.GUID].Instance; byte[] RunCapture() { postProcessing.enabled = false; RenderSettings.ambientSkyColor = Color.white; RenderSettings.ambientEquatorColor = Color.white; RenderSettings.ambientGroundColor = Color.white; var cap = screencap.Capture(64, 64, 1, true); var cap2D = cap.ToTexture2D(); var bytes = cap2D.EncodeToPNG(); RenderTexture.ReleaseTemporary(cap); Object.Destroy(cap2D); return(bytes); } var createdCount = 0; foreach (var itemInfo in itemList) { if (itemInfo.IsSFX) { continue; } var thumbPath = Path.Combine(outputDirectory, itemInfo.CacheId + ".png"); if (File.Exists(thumbPath)) { continue; } if (ThumbnailLoader.CustomThumbnailAvailable(itemInfo)) { continue; } yield return(null); Console.WriteLine($"Spawning: FullName={itemInfo.FullName} FileName={itemInfo.FileName}"); itemInfo.AddItem(); createdCount++; yield return(null); var targets = root.Children(); var b = Utils.CalculateBounds(targets); if (b != null) { var bounds = b.Value; const float objectSizeAdjust = 0.5f; var objectSize = bounds.size.magnitude; var targetObj = targets.First(); if (_shootFromFrontGroups.Contains(itemInfo.GroupNo)) { // Look at the object from front, better for flat effects // Move the camera a long way away from the objects to avoid clipping // todo anything better? Not reliable camera.transform.position = (targetObj.position + targetObj.forward * objectSize) * 8; } else { // Use isometric angle since it has best chance of showing the object in an usable way // Move the camera a long way away from the objects to avoid clipping camera.transform.position = (bounds.center - targetObj.forward * objectSize - targetObj.right * objectSize + targetObj.up * objectSize) * 8; } camera.transform.LookAt(bounds.center); camera.orthographicSize = objectSize * objectSizeAdjust; void UpdateBackgroundPlane() { // Move the thumbnail pane in the opposite way from the camera and scale/align it so that it fills the camera view behind the item copyPlane.position = camera.transform.position + camera.transform.forward * (camera.transform.position - bounds.center).magnitude * 2; copyPlane.LookAt(camera.transform); copyPlane.Rotate(90, 0, 0); copyPlane.localScale = new Vector3(objectSize * 0.508f, 1, objectSize * 0.508f) * objectSizeAdjust; } if (manualMode) { cameraControl.enabled = true; yield return(new WaitUntil(() => { // Adjust for the new camera position objectSize = camera.orthographicSize / objectSizeAdjust; UpdateBackgroundPlane(); return Input.GetKeyDown(KeyCode.LeftShift) || Input.GetKey(KeyCode.Escape); })); cameraControl.enabled = false; } UpdateBackgroundPlane(); var result = RunCapture(); try { File.WriteAllBytes(thumbPath, result); } catch (SystemException ex) { QuickAccessBox.Logger.Log(BepInEx.Logging.LogLevel.Message | BepInEx.Logging.LogLevel.Error, "Failed to write thumbnail file - " + ex.Message); } } else { QuickAccessBox.Logger.LogInfo($"No renderers to take capture of for {itemInfo.FullName} - GroupNo:{itemInfo.GroupNo} CategoryNo:{itemInfo.CategoryNo} ItemNo:{itemInfo.ItemNo}"); } yield return(null); RemoveAllItems(); if (createdCount % 400 == 0) { Resources.UnloadUnusedAssets(); } if (Input.GetKey(KeyCode.Escape)) { break; } } cameraControl.enabled = true; camera.orthographic = false; Object.Destroy(thumbBackground); Object.Destroy(copyPlane.gameObject); QuickAccessBox.Logger.LogMessage("Finished taking thumbnails!"); }