public string Execute(FileItem item, string infile, string dest, ValuePairEnumerator configData) { try { var conf = new ChromakeyViewModel(configData); dest = Path.Combine(Path.GetDirectoryName(dest), Path.GetFileNameWithoutExtension(dest) + ".jpg"); KalikoImage image = new KalikoImage(infile); var x = (System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString(conf.BackgroundColor); var filter = new ChromaKeyFilter(); filter.KeyColor = Color.FromArgb(x.R, x.G, x.B); filter.ToleranceHue = conf.Hue; filter.ToleranceSaturnation = conf.Saturnation / 100f; filter.ToleranceBrightness = conf.Brigthness / 100f; image.ApplyFilter(filter); var res = image.Clone(); if (conf.UnsharpMask) { res.ApplyFilter(new UnsharpMaskFilter(1.4f, 1.32f, 5)); } var backdrop = new KalikoImage(conf.BackgroundFile); backdrop = backdrop.Scale(new FitScaling(image.Width, image.Height)); backdrop.BlitImage(res); backdrop.SaveJpg(dest, 90); return(dest); } catch (Exception e) { Log.Debug("Chromakey error", e); } return(null); }
private void AddWaterMarking(WaterMarkingPosition?position, string waterMarkingPath, KalikoImage imageThumb) { if (!position.HasValue || string.IsNullOrEmpty(waterMarkingPath)) { return; } //需要打上水印 var waterMarkingImgage = new KalikoImage(waterMarkingPath); var waterMarkingWidth = (int)(imageThumb.Width / 4.8); var waterMarkingHeight = (int)(waterMarkingImgage.Height * waterMarkingWidth / waterMarkingImgage.Width); var waterScalingBase = new FitScaling(waterMarkingWidth, waterMarkingHeight); var waterThumb = waterMarkingImgage.Scale(waterScalingBase); //计算距离 var waterX = 0; var waterY = 0; const int edgeWidth = 40; switch (position.Value) { case WaterMarkingPosition.Center: waterX = (imageThumb.Width - waterThumb.Width) / 2; waterY = (imageThumb.Height - waterThumb.Height) / 2; break; case WaterMarkingPosition.LeftBottom: waterX = edgeWidth; waterY = imageThumb.Height - waterThumb.Height - edgeWidth; break; case WaterMarkingPosition.LeftTop: waterX = edgeWidth; waterY = edgeWidth; break; case WaterMarkingPosition.RightBottom: waterX = imageThumb.Width - waterThumb.Width - edgeWidth; waterY = imageThumb.Height - waterThumb.Height - edgeWidth; break; case WaterMarkingPosition.RightTop: waterX = imageThumb.Width - waterThumb.Width - edgeWidth; waterY = edgeWidth; break; } imageThumb.BlitImage(waterThumb, waterX, waterY); }
// WARNING: Very ugly code ahead, quick and dirty method to generate an image private Dictionary <string, string> BuildCDMBar(string barName, string barNameBackgroundColour, string ingredient1, string ingredient2, string ingredient3, string directoryId, string userImagesPath) { // Locate base directory for CDM bar assets string cdmBarAssetsPath = Path.Combine(GetRequestApplicationPath(), "App_Data", "cdm_bar"); var fileId = Guid.NewGuid().ToString("N"); string imageFilePath = $"{directoryId}/{fileId}-1.jpg"; //string imageShareFilePath = $"{directoryId}/{fileId}-2.jpg"; string imageShareWideFilePath = $"{directoryId}/{fileId}-3.jpg"; // Count the amount of ingredients int ingredientAmount = 0; ingredientAmount += !String.IsNullOrEmpty(ingredient1) ? 1 : 0; ingredientAmount += !String.IsNullOrEmpty(ingredient2) ? 1 : 0; ingredientAmount += !String.IsNullOrEmpty(ingredient3) ? 1 : 0; // Create a new canvas based on background image (helps in getting a dynamic dimension also) String backgroundImagePath = Path.Combine(cdmBarAssetsPath, "background.png"); using (var image = new KalikoImage(backgroundImagePath)) { // Composite the image with ingredients by blitting, yeah too many nested IFs if (ingredientAmount > 0) { var ingredient1ImagePath = Path.Combine(cdmBarAssetsPath, ingredient1.ToLower()); using (var ingredientImage = new KalikoImage(ingredient1ImagePath)) { // Very important to set the image to the same resolution as the exported file, else proportions won't be maintained ingredientImage.SetResolution(96, 96); image.BlitImage(ingredientImage, 2596, 1090); } if (ingredientAmount > 1) { var ingredient2ImagePath = Path.Combine(cdmBarAssetsPath, ingredient2.ToLower()); using (var ingredientImage = new KalikoImage(ingredient2ImagePath)) { // Very important to set the image to the same resolution as the exported file, else proportions won't be maintained ingredientImage.SetResolution(96, 96); image.BlitImage(ingredientImage, 2646, 698); } if (ingredientAmount > 2) { var ingredient3ImagePath = Path.Combine(cdmBarAssetsPath, ingredient3.ToLower()); using (var ingredientImage = new KalikoImage(ingredient3ImagePath)) { // Very important to set the image to the same resolution as the exported file, else proportions won't be maintained ingredientImage.SetResolution(96, 96); image.BlitImage(ingredientImage, 2390, 392); } } } } // Overlay the CDM Bar with "masking" holes var cdmBarImagePath = Path.Combine(cdmBarAssetsPath, $"bar-ingredient-x{ingredientAmount.ToString()}.png"); using (var cdmBarImage = new KalikoImage(cdmBarImagePath)) { cdmBarImage.SetResolution(96, 96); image.BlitImage(cdmBarImage); } GC.Collect(); GC.WaitForPendingFinalizers(); // Overlay the text background if any if (!(String.IsNullOrEmpty(barNameBackgroundColour) || barNameBackgroundColour.ToLower().Equals("transparent"))) { var barNameBackgroundImagePath = Path.Combine(cdmBarAssetsPath, $"back-{barNameBackgroundColour.ToLower()}.png"); using (var barNameBackgroundImage = new KalikoImage(barNameBackgroundImagePath)) { barNameBackgroundImage.SetResolution(96, 96); image.BlitImage(barNameBackgroundImage); } } // Add the final touch, the "pièce de résistance", the centered angled text! var fontPath = Path.Combine(cdmBarAssetsPath, "MonkyBasicRegular.ttf"); image.SetFont(fontPath, 110, FontStyle.Regular); var text = new TextField(barName.ToUpper()); text.Rotation = -14.1f; text.TextColor = Color.White; text.Alignment = StringAlignment.Center; text.VerticalAlignment = StringAlignment.Center; text.TargetArea = new Rectangle(900, 1231, 1800, 618); image.DrawText(text); // Create destination directory if it doesn't already exist String destinationDirectoryPath = Path.Combine(userImagesPath, directoryId); System.IO.Directory.CreateDirectory(destinationDirectoryPath); // Create the share image (square aspect ratio) /* * String backgroundShareImagePath = Path.Combine(cdmBarAssetsPath, "background-share.png"); * using (var shareImage = new KalikoImage(backgroundShareImagePath)) * { * shareImage.SetResolution(96, 96); * shareImage.BlitImage(image); * * // Save the square share image * String destinationShareFilePath = Path.Combine(userImagesPath, imageShareFilePath); * // Resize it for front-end display * shareImage.Resize(1200, 1200); * shareImage.SaveJpg(destinationShareFilePath, 90, true); * } */ // Create the share image (wide aspect ratio) String backgroundShareImageWidePath = Path.Combine(cdmBarAssetsPath, "background-share-wide.png"); using (var shareImageWide = new KalikoImage(backgroundShareImageWidePath)) { shareImageWide.SetResolution(96, 96); shareImageWide.BlitImage(image, 1286, -68); // Compose the text onto the image String textShareImageWidePath = Path.Combine(cdmBarAssetsPath, "text-share-wide.png"); using (var shareTextWide = new KalikoImage(textShareImageWidePath)) { shareTextWide.SetResolution(96, 96); shareImageWide.BlitImage(shareTextWide); } // Save the wide share image String destinationShareWideFilePath = Path.Combine(userImagesPath, imageShareWideFilePath); // Resize it for front-end display shareImageWide.Resize(1200, 630); shareImageWide.SaveJpg(destinationShareWideFilePath, 90, true); } GC.Collect(); GC.WaitForPendingFinalizers(); // Save the composited image String destinationFilePath = Path.Combine(userImagesPath, imageFilePath); image.SetResolution(96, 96); // Resize it for front-end display image.Resize(520, 360); image.SaveJpg(destinationFilePath, 90, true); } GC.Collect(); GC.WaitForPendingFinalizers(); return(new Dictionary <string, string> { { "FileId", fileId }, { "CompositedImage", imageFilePath }, { "CompositedImageShare", imageShareWideFilePath }, { "CompositedImageShareWide", imageShareWideFilePath } }); }