public static void CopyImageMetadataToWholeBook(string folderPath, HtmlDom dom, Metadata metadata, IProgress progress) { progress.WriteStatus("Starting..."); //First update the images themselves int completed = 0; var imgElements = GetImagePaths(folderPath); foreach (string path in imgElements) { progress.ProgressIndicator.PercentCompleted = (int)(100.0 * (float)completed / imgElements.Count()); progress.WriteStatus("Copying to " + Path.GetFileName(path)); using (var image = PalasoImage.FromFile(path)) { image.Metadata = metadata; image.SaveUpdatedMetadataIfItMakesSense(); } ++completed; } //Now update the html attributes which echo some of it, and is used by javascript to overlay displays related to //whether the info is there or missing or whatever. foreach (XmlElement img in dom.SafeSelectNodes("//img")) { UpdateImgMetdataAttributesToMatchImage(folderPath, img, progress, metadata); } }
private PalasoImage MakeSampleTifImage(string path) { var x = new Bitmap(kSampleImageDimension, kSampleImageDimension); x.Save(path, ImageFormat.Tiff); return(PalasoImage.FromFile(path)); }
public void ShouldChangeFormatToJpeg_OneColor_False() { var path = FileLocationUtilities.GetFileDistributedWithApplication(_pathToTestImages, "bird.png"); string jpegPath = Path.Combine(Path.GetTempPath(), Path.GetTempFileName() + ".jpg"); Assert.IsFalse(ImageUtils.TryChangeFormatToJpegIfHelpful(PalasoImage.FromFile(path), jpegPath)); Assert.IsFalse(File.Exists(jpegPath)); }
private PalasoImage MakeSampleJpegImage(string path) { var x = new Bitmap(kSampleImageDimension, kSampleImageDimension); x.Save(path, ImageFormat.Jpeg); //nb: even if we reload the image from the file, the rawformat will be memory bitmap, not jpg as we'd wish return(PalasoImage.FromFile(path)); }
private PalasoImage MakeSamplePngImage(string path) { var x = new Bitmap(kSampleImageDimension, kSampleImageDimension); x.Save(path, ImageFormat.Png); x.Dispose(); return(PalasoImage.FromFile(path)); }
/// <summary> /// Creates a thumbnail of just the cover image (no title, language name, etc.) /// </summary> /// <returns>Returns true if successful; false otherwise. </returns> internal static bool CreateThumbnailOfCoverImage(Book.Book book, HtmlThumbNailer.ThumbnailOptions options, Action <Image> callback = null) { var imageSrc = book.GetCoverImagePath(); if (!IsCoverImageSrcValid(imageSrc, options)) { Debug.WriteLine(book.StoragePageFolder + " does not have a cover image."); return(false); } var size = Math.Max(options.Width, options.Height); var destFilePath = Path.Combine(book.StoragePageFolder, options.FileName); // Writing a transparent image to a file, then reading it in again appears to be the only // way to get the thumbnail image to draw with the book's cover color background reliably. var transparentImageFile = Path.Combine(Path.GetTempPath(), "Bloom", "Transparent", Path.GetFileName(imageSrc)); Directory.CreateDirectory(Path.GetDirectoryName(transparentImageFile)); try { if (RuntimeImageProcessor.MakePngBackgroundTransparent(imageSrc, transparentImageFile)) { imageSrc = transparentImageFile; } using (var coverImage = PalasoImage.FromFile(imageSrc)) { if (imageSrc == transparentImageFile) { coverImage.Image = MakeImageOpaque(coverImage.Image, book.GetCoverColor()); } var shouldAddDashedBorder = options.BorderStyle == HtmlThumbNailer.ThumbnailOptions.BorderStyles.Dashed; coverImage.Image = options.CenterImageUsingTransparentPadding ? ImageUtils.CenterImageIfNecessary(new Size(size, size), coverImage.Image, shouldAddDashedBorder) : ImageUtils.ResizeImageIfNecessary(new Size(size, size), coverImage.Image, shouldAddDashedBorder); switch (Path.GetExtension(destFilePath).ToLowerInvariant()) { case ".jpg": case ".jpeg": ImageUtils.SaveAsTopQualityJpeg(coverImage.Image, destFilePath); break; default: PalasoImage.SaveImageRobustly(coverImage, destFilePath); break; } if (callback != null) { callback(coverImage.Image.Clone() as Image); // don't leave GC to chance } } } finally { if (File.Exists(transparentImageFile)) { SIL.IO.RobustFile.Delete(transparentImageFile); } } return(true); }
public void FromFile_HugeJPEG_DoesNotCrash() { //nb: trying to reproduce a problem that came up in bloom with this very image, but //i never did get this to crash here PalasoImage.FromFile(@"C:\Users\John\Desktop\hugetestimage.jpg"); PalasoImage.FromFile(@"C:\Users\John\Desktop\hugetestimage.jpg"); PalasoImage.FromFile(@"C:\Users\John\Desktop\hugetestimage.jpg"); PalasoImage.FromFile(@"C:\Users\John\Desktop\hugetestimage.jpg"); }
public void FromFile_DoesNotLockFile() { using (Bitmap bitmap = new Bitmap(10, 10)) using (var temp = TempFile.CreateAndGetPathButDontMakeTheFile()) { bitmap.Save(temp.Path); PalasoImage.FromFile(temp.Path); Assert.DoesNotThrow(() => File.Delete(temp.Path)); } }
public void Image_FromFile_GivesImage() { using (Bitmap bitmap = new Bitmap(10, 10)) using (var temp = TempFile.CreateAndGetPathButDontMakeTheFile()) { bitmap.Save(temp.Path); var pi = PalasoImage.FromFile(temp.Path); Assert.AreEqual(10, pi.Image.Width); } }
private void OnEditImageMetdata(DomEventArgs ge) { var imageElement = GetImageNode(ge); if (imageElement == null) { return; } string fileName = imageElement.GetAttribute("src").Replace("%20", " "); var path = Path.Combine(_model.CurrentBook.FolderPath, fileName); using (var imageInfo = PalasoImage.FromFile(path)) { bool looksOfficial = imageInfo.Metadata != null && !string.IsNullOrEmpty(imageInfo.Metadata.CollectionUri); if (looksOfficial) { MessageBox.Show(imageInfo.Metadata.GetSummaryParagraph("en")); return; } Logger.WriteEvent("Showing Metadata Editor For Image"); using (var dlg = new Palaso.UI.WindowsForms.ClearShare.WinFormsUI.MetadataEditorDialog(imageInfo.Metadata)) { if (DialogResult.OK == dlg.ShowDialog()) { imageInfo.Metadata = dlg.Metadata; imageInfo.SaveUpdatedMetadataIfItMakesSense(); imageInfo.Metadata.StoreAsExemplar(Metadata.FileCategory.Image); //update so any overlays on the image are brough up to data var editor = new PageEditingModel(); editor.UpdateMetdataAttributesOnImgElement(imageElement, imageInfo); var answer = MessageBox.Show(LocalizationManager.GetString("EditTab.copyImageIPMetdataQuestion", "Copy this information to all other pictures in this book?", "get this after you edit the metadata of an image"), LocalizationManager.GetString("EditTab.titleOfCopyIPToWholeBooksDialog", "Picture Intellectual Property Information"), MessageBoxButtons.YesNo); if (answer == DialogResult.Yes) { Cursor = Cursors.WaitCursor; try { _model.CopyImageMetadataToWholeBook(dlg.Metadata); // There might be more than one image on this page. Update overlays. _model.RefreshDisplayOfCurrentPage(); } catch (Exception e) { ErrorReport.NotifyUserOfProblem(e, "There was a problem copying the metadata to all the images."); } Cursor = Cursors.Default; } } } } //_model.SaveNow(); //doesn't work: _browser1.WebBrowser.Reload(); }
public void Locked_LoadedButImageHasNoMetadata_False() { var png = new Bitmap(10, 10); using (var temp = new TempFile(false)) { png.Save(temp.Path); var pi = PalasoImage.FromFile(temp.Path); Assert.IsFalse(pi.MetadataLocked); } }
private void MakeSamplePngImageWithMetadata(string path) { var x = new Bitmap(10, 10); x.Save(path, ImageFormat.Png); x.Dispose(); using (var img = PalasoImage.FromFile(path)) { img.Metadata.Creator = "joe"; img.Metadata.CopyrightNotice = "Copyright 1999 by me"; img.SaveUpdatedMetadataIfItMakesSense(); } }
public void LoadAndSave_DeleteAfter_NothingLocked() { var png = new Bitmap(10, 10); using (var temp = new TempFile(false)) { png.Save(temp.Path); var pi = PalasoImage.FromFile(temp.Path); pi.Metadata.CopyrightNotice = "Copyright 2011 me"; Assert.DoesNotThrow(() => pi.Save(temp.Path)); Assert.DoesNotThrow(() => File.Delete(temp.Path)); } }
protected void MakeSamplePngImageWithMetadata(string path) { var x = new Bitmap(10, 10); x.Save(path, ImageFormat.Png); x.Dispose(); using (var img = PalasoImage.FromFile(path)) { img.Metadata.Creator = "joe"; img.Metadata.CopyrightNotice = "Copyright 1999 by me"; img.Metadata.License = new CreativeCommonsLicense(true, true, CreativeCommonsLicense.DerivativeRules.NoDerivatives); img.SaveUpdatedMetadataIfItMakesSense(); } }
public void FromFileTwiceMaintainsCorrectPath() { using (var bitmap1 = new Bitmap(10, 10)) using (var bitmap2 = new Bitmap(10, 10)) using (var tf1 = TempFile.WithExtension(".png")) using (var tf2 = TempFile.WithExtension(".png")) { bitmap1.Save(tf1.Path); bitmap2.Save(tf2.Path); using (var pi1 = PalasoImage.FromFile(tf1.Path)) using (var pi2 = PalasoImage.FromFile(tf2.Path)) Assert.AreNotEqual(pi1.OriginalFilePath, pi2.OriginalFilePath); } }
public PalasoImage GetImage() { if (ChosenPath != null && File.Exists(ChosenPath)) { try { return(PalasoImage.FromFile(ChosenPath)); } catch (Exception error) { ErrorReport.ReportNonFatalExceptionWithMessage(error, "There was a problem choosing that image."); return(_previousImage); } } return(_previousImage); }
public static void UpdateImgMetdataAttributesToMatchImage(string folderPath, XmlElement imgElement, IProgress progress, Metadata metadata) { //see also PageEditingModel.UpdateMetadataAttributesOnImage(), which does the same thing but on the browser dom var fileName = imgElement.GetOptionalStringAttribute("src", string.Empty).ToLower(); var end = fileName.IndexOf('?'); if (end > 0) { fileName = fileName.Substring(0, end); } if (fileName == "placeholder.png" || fileName == "license.png") { return; } if (string.IsNullOrEmpty(fileName)) { Logger.WriteEvent("Book.UpdateImgMetdataAttributesToMatchImage() Warning: img has no or empty src attribute"); //Debug.Fail(" (Debug only) img has no or empty src attribute"); return; // they have bigger problems, which aren't appropriate to deal with here. } if (metadata == null) { progress.WriteStatus("Reading metadata from " + fileName); var path = folderPath.CombineForPath(fileName); if (!File.Exists(path)) // they have bigger problems, which aren't appropriate to deal with here. { imgElement.RemoveAttribute("data-copyright"); imgElement.RemoveAttribute("data-creator"); imgElement.RemoveAttribute("data-license"); Logger.WriteEvent("Book.UpdateImgMetdataAttributesToMatchImage() Image " + path + " is missing"); //Debug.Fail(" (Debug only) Image " + path + " is missing"); return; } using (var image = PalasoImage.FromFile(path)) { metadata = image.Metadata; } } progress.WriteStatus("Writing metadata to HTML for " + fileName); imgElement.SetAttribute("data-copyright", String.IsNullOrEmpty(metadata.CopyrightNotice) ? "" : metadata.CopyrightNotice); imgElement.SetAttribute("data-creator", String.IsNullOrEmpty(metadata.Creator) ? "" : metadata.Creator); imgElement.SetAttribute("data-license", metadata.License == null ? "" : metadata.License.ToString()); }
public void ShouldChangeFormatToJpeg_Photo_True() { var path = FileLocationUtilities.GetFileDistributedWithApplication(_pathToTestImages, "man.png"); string jpegPath = Path.Combine(Path.GetTempPath(), Path.GetTempFileName() + ".jpg"); try { Assert.IsTrue(ImageUtils.TryChangeFormatToJpegIfHelpful(PalasoImage.FromFile(path), jpegPath)); Assert.IsTrue(File.Exists(jpegPath)); } finally { if (File.Exists(jpegPath)) { File.Delete(jpegPath); } } }
private static void RoundTripImageThenCheckPixelFormat(string extension, ImageFormat imageFormat, PixelFormat pixelFormat) { using (var originalBitmap = new Bitmap(10, 10, pixelFormat)) using (var saved = TempFile.WithExtension(extension)) { using (var palasoImageToSave = PalasoImage.FromImage(originalBitmap)) { palasoImageToSave.Save(saved.Path); } using (var palasoImageToSave = PalasoImage.FromFile(saved.Path)) { Assert.AreEqual(pixelFormat, palasoImageToSave.Image.PixelFormat, "Format was lost when loading into palaso image"); } using (var loaded = Image.FromFile(saved.Path)) { Assert.AreEqual(pixelFormat, loaded.PixelFormat, "Format was lost when loading into plain .net Image"); } } }
private void OnChangeImage(GeckoDomEventArgs ge) { var imageElement = GetImageNode(ge); if (imageElement == null) { return; } string currentPath = imageElement.GetAttribute("src").Replace("%20", " "); //TODO: this would let them set it once without us bugging them, but after that if they //go to change it, we would bug them because we don't have a way of knowing that it was a placeholder before. if (!currentPath.ToLower().Contains("placeholder") && //always alow them to put in something over a placeholder !_model.CanChangeImages()) { if (DialogResult.Cancel == MessageBox.Show(LocalizationManager.GetString("EditTab.ImageChangeWarning", "This book is locked down as shell. Are you sure you want to change the picture?"), LocalizationManager.GetString("EditTab.ChangeImage", "Change Image"), MessageBoxButtons.OKCancel)) { return; } } if (ge.Target.ClassName.Contains("licenseImage")) { return; } Cursor = Cursors.WaitCursor; var imageInfo = new PalasoImage(); var existingImagePath = Path.Combine(_model.CurrentBook.FolderPath, currentPath); //don't send the placeholder to the imagetoolbox... we get a better user experience if we admit we don't have an image yet. if (!currentPath.ToLower().Contains("placeholder") && File.Exists(existingImagePath)) { try { imageInfo = PalasoImage.FromFile(existingImagePath); } catch (Exception) { //todo: log this } } ; Logger.WriteEvent("Showing ImageToolboxDialog Editor Dialog"); using (var dlg = new ImageToolboxDialog(imageInfo, null)) { if (DialogResult.OK == dlg.ShowDialog()) { // var path = MakePngOrJpgTempFileForImage(dlg.ImageInfo.Image); try { _model.ChangePicture(imageElement, dlg.ImageInfo, new NullProgress()); } catch (System.IO.IOException error) { Palaso.Reporting.ErrorReport.NotifyUserOfProblem(error, error.Message); } catch (ApplicationException error) { Palaso.Reporting.ErrorReport.NotifyUserOfProblem(error, error.Message); } catch (Exception error) { Palaso.Reporting.ErrorReport.NotifyUserOfProblem(error, "Bloom had a problem including that image"); } } } Logger.WriteMinorEvent("Emerged from ImageToolboxDialog Editor Dialog"); Cursor = Cursors.Default; }
private void OnChangeImage(DomEventArgs ge) { var imageElement = GetImageNode(ge); if (imageElement == null) { return; } string currentPath = imageElement.GetAttribute("src").Replace("%20", " "); if (!CheckIfLockedAndWarn(currentPath)) { return; } var target = (GeckoHtmlElement)ge.Target.CastToGeckoElement(); if (target.ClassName.Contains("licenseImage")) { return; } Cursor = Cursors.WaitCursor; var imageInfo = new PalasoImage(); var existingImagePath = Path.Combine(_model.CurrentBook.FolderPath, currentPath); //don't send the placeholder to the imagetoolbox... we get a better user experience if we admit we don't have an image yet. if (!currentPath.ToLower().Contains("placeholder") && File.Exists(existingImagePath)) { try { imageInfo = PalasoImage.FromFile(existingImagePath); } catch (Exception) { //todo: log this } } ; Logger.WriteEvent("Showing ImageToolboxDialog Editor Dialog"); using (var dlg = new ImageToolboxDialog(imageInfo, null)) { if (DialogResult.OK == dlg.ShowDialog()) { // var path = MakePngOrJpgTempFileForImage(dlg.ImageInfo.Image); try { _model.ChangePicture(imageElement, dlg.ImageInfo, new NullProgress()); } catch (System.IO.IOException error) { Palaso.Reporting.ErrorReport.NotifyUserOfProblem(error, error.Message); } catch (ApplicationException error) { Palaso.Reporting.ErrorReport.NotifyUserOfProblem(error, error.Message); } catch (Exception error) { Palaso.Reporting.ErrorReport.NotifyUserOfProblem(error, "Bloom had a problem including that image"); } } } Logger.WriteMinorEvent("Emerged from ImageToolboxDialog Editor Dialog"); Cursor = Cursors.Default; }
private void OnPasteImage(DomEventArgs ge) { if (!_model.CanChangeImages()) { MessageBox.Show( LocalizationManager.GetString("EditTab.CantPasteImageLocked", "Sorry, this book is locked down so that images cannot be changed.")); return; } Image clipboardImage = null; try { clipboardImage = GetImageFromClipboard(); if (clipboardImage == null) { MessageBox.Show( LocalizationManager.GetString("EditTab.NoImageFoundOnClipboard", "Before you can paste an image, copy one onto your 'clipboard', from another program.")); return; } var target = (GeckoHtmlElement)ge.Target.CastToGeckoElement(); if (target.ClassName.Contains("licenseImage")) { return; } var imageElement = GetImageNode(ge); if (imageElement == null) { return; } Cursor = Cursors.WaitCursor; //nb: later, code closer to the the actual book folder will //improve this file name. Taglib# requires an extension that matches the file content type, however. using (var temp = TempFile.WithExtension("png")) { clipboardImage.Save(temp.Path, ImageFormat.Png); // using (var progressDialog = new ProgressDialogBackground()) // { // progressDialog.ShowAndDoWork((progress, args) => // { // ImageUpdater.CompressImage(temp.Path, progress); // }); // } using (var palasoImage = PalasoImage.FromFile(temp.Path)) { _model.ChangePicture(imageElement, palasoImage, new NullProgress()); } } } catch (Exception error) { Palaso.Reporting.ErrorReport.NotifyUserOfProblem(error, "The program had trouble getting an image from the clipboard."); } finally { if (clipboardImage != null) { clipboardImage.Dispose(); } } Cursor = Cursors.Default; }
private void OnSearchGalleryLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { Cursor = Cursors.WaitCursor; var searchString = SearchTermProvider == null ? string.Empty : SearchTermProvider.SearchString; PalasoImage currentImage = null; try { if (!string.IsNullOrEmpty(_relativePathToImage) && File.Exists(GetPathToImage())) { currentImage = PalasoImage.FromFile(GetPathToImage()); } } catch (Exception) { //if we couldn't load it (like if it's missing), best to carry on and let them pick a new one } using (var dlg = new Palaso.UI.WindowsForms.ImageToolbox.ImageToolboxDialog(currentImage ?? new PalasoImage(), searchString)) { if (DialogResult.OK == dlg.ShowDialog(this.ParentForm)) { try { if (File.Exists(GetPathToImage())) { File.Delete(GetPathToImage()); } string fileName = CheckFileName(searchString); if (string.IsNullOrEmpty(fileName)) { fileName = DateTime.UtcNow.ToFileTimeUtc().ToString(); } string fileExt; if ((!String.IsNullOrEmpty(dlg.ImageInfo.FileName)) && (!String.IsNullOrEmpty(dlg.ImageInfo.FileName.Split('.').Last()))) { fileExt = "." + dlg.ImageInfo.FileName.Split('.').Last(); } else { // If no file name or extension, default to png fileExt = ".png"; } fileExt = PalasoImage.FileExtForWebFormat(fileExt); //NB: we have very possible collision if use a real word "bird". //Less so with a time "3409343839", which this only uses if we don't have a file name (e.g. if it came from a scanner) //so this will add to the name if what we have is not unique. if (File.Exists(Path.Combine(_storageFolderPath, fileName + fileExt))) { fileName += "-" + DateTime.UtcNow.ToFileTimeUtc(); } fileName += fileExt; var fullDestPath = Path.Combine(_storageFolderPath, fileName); _relativePathToImage = fullDestPath.Replace(_pathToReferingFile, ""); _relativePathToImage = _relativePathToImage.Trim(Path.DirectorySeparatorChar); dlg.ImageInfo.Save(GetPathToImage()); UpdateDisplay(); NotifyChanged(); } catch (Exception error) { ErrorReport.NotifyUserOfProblem("WeSay was not able to save the picture file.\r\n{0}", error.Message); } } } }
public string GetPathToResizedImage(string originalPath) { //don't mess with Bloom UI images if (new[] { "/img/", "placeHolder", "Button" }.Any(s => originalPath.Contains(s))) { return(originalPath); } string resizedPath; if (_paths.TryGetValue(originalPath, out resizedPath)) { if (File.Exists(resizedPath) && new FileInfo(originalPath).LastWriteTimeUtc <= new FileInfo(resizedPath).LastWriteTimeUtc) { return(resizedPath); } else { _paths.Remove(originalPath); } } using (var originalImage = PalasoImage.FromFile(originalPath)) { if (!originalPath.Contains("Button") && !ImageUtils.AppearsToBeJpeg(originalImage)) { ((Bitmap)originalImage.Image).MakeTransparent(Color.White); //instead of white, show the background color } if (originalImage.Image.Width > TargetDimension || originalImage.Image.Height > TargetDimension) { var maxDimension = Math.Max(originalImage.Image.Width, originalImage.Image.Height); double shrinkFactor = (TargetDimension / (double)maxDimension); var destWidth = (int)(shrinkFactor * originalImage.Image.Width); var destHeight = (int)(shrinkFactor * originalImage.Image.Height); using (var b = new Bitmap(destWidth, destHeight)) { using (Graphics g = Graphics.FromImage((Image)b)) { //in version 1.0, we used .NearestNeighbor. But if there is a border line down the right size (as is common for thumbnails that, //are, for example, re-inserted into Teacher's Guides), then the line gets cut off. So I switched it to HighQualityBicubic g.InterpolationMode = InterpolationMode.HighQualityBicubic; //.NearestNeighbor;//or smooth it: HighQualityBicubic g.DrawImage(originalImage.Image, 0, 0, destWidth, destHeight); } var temp = Path.Combine(_cacheFolder, Path.GetRandomFileName() + Path.GetExtension(originalPath)); //Hatton July 2012: //Once or twice I saw a GDI+ error on the Save below, when the app 1st launched. //I verified that if there is an IO error, that's what it you get (a GDI+ error). //I looked once, and the %temp%/Bloom directory wasn't there, so that's what I think caused the error. //It's not clear why the temp/bloom directory isn't there... possibly it was there a moment ago //but then some startup thread cleared and deleted it? (we are now running on a thread responding to the http request) Exception error = null; for (int i = 0; i < 5; i++) //try up to five times, a second apart { try { error = null; if (!Directory.Exists(Path.GetDirectoryName(temp))) { Directory.CreateDirectory(Path.GetDirectoryName(temp)); } b.Save(temp, originalImage.Image.RawFormat); break; } catch (Exception e) { Logger.WriteEvent("Error in LowResImage while trying to write image."); Logger.WriteEvent(e.Message); error = e; Thread.Sleep(1000); //wait a second before trying again } } if (error != null) { //NB: this will be on a non-UI thread, so it probably won't work well! ErrorReport.NotifyUserOfProblem(error, "Bloom is having problem saving a low-res version to your temp directory, at " + temp + "\r\n\r\nYou might want to quit and restart Bloom. In the meantime, Bloom will try to use the full-res images."); return(originalPath); } try { _paths.Add(originalPath, temp); //remember it so we can reuse if they show it again, and later delete } catch (Exception) { // it happens sometimes that though it wasn't in the _paths when we entered, it is now // I haven't tracked it down... possibly we get a new request for the image while we're busy compressing it? } return(temp); } } else { return(originalPath); } } }
public void Constructor_CreatedWithFileThatDoesNotExist_Throws() { Assert.Throws <FileNotFoundException>( () => PalasoImage.FromFile("not going to find me")); }