/// <summary> /// When images are copied from LibreOffice, images that were jpegs there are converted to bitmaps for the clipboard. /// So when we just saved them as bitmaps (pngs), we dramatically inflated the size of user's image files (and /// this then led to memory problems). /// So the idea here is just to try and detect that we should would be better off saving the image as a jpeg. /// Note that even at 100%, we're still going to lose some quality. So this method is only going to recommend /// doing that if the size would be at least 50% less. /// </summary> public static bool ShouldChangeFormatToJpeg(Image image) { try { using (var safetyImage = new Bitmap(image)) //nb: there are cases (notably http://jira.palaso.org/issues/browse/WS-34711, after cropping a jpeg) where we get out of memory if we are not operating on a copy { using (var jpegFile = new TempFile()) using (var pngFile = new TempFile()) { RobustImageIO.SaveImage(image, pngFile.Path, ImageFormat.Png); SaveAsTopQualityJpeg(safetyImage, jpegFile.Path); var jpegInfo = new FileInfo(jpegFile.Path); var pngInfo = new FileInfo(pngFile.Path); // this is just our heuristic. const double fractionOfTheOriginalThatWouldWarrantChangingToJpeg = .5; return(jpegInfo.Length < (pngInfo.Length * (1.0 - fractionOfTheOriginalThatWouldWarrantChangingToJpeg))); } } } catch (OutOfMemoryException e) { NonFatalProblem.Report(ModalIf.Alpha, PassiveIf.All, "Could not attempt conversion to jpeg.", "ref BL-3387", exception: e); return(false); } }
public void Setup() { _mediaFile = new Bitmap(10, 10); _tempFile = TempFile.WithExtension("png"); _mediaFile.Save(_tempFile.Path); _outgoing = Metadata.FromFile(_tempFile.Path); }
public void TypicalEmbedInMyXmlDocument() { var system = new OlacSystem(); var work = new Work(); work.Licenses.Add(License.CreativeCommons_Attribution_ShareAlike); work.Contributions.Add(new Contribution("Charlie Brown", system.GetRoleByCodeOrThrow("author"))); work.Contributions.Add(new Contribution("Linus", system.GetRoleByCodeOrThrow("editor"))); string metaData = system.GetXmlForWork(work); //Embed that data in our own file using (var f = new TempFile(@"<doc> <metadata>" + metaData + @"</metadata> <ourDocumentContents>blah blah<ourDocumentContents/></doc>")) { //Then when it comes time to read the file, we can extract out the work again var dom = new XmlDocument(); dom.Load(f.Path); var node = dom.SelectSingleNode("//metadata"); var work2 = new Work(); system.LoadWorkFromXml(work2, node.InnerXml); Assert.AreEqual(2,work2.Contributions.Count()); } }
public void LoadOrMakeNew_EmptyFile_GivesNewPrefs() { using (var t = new TempFile("")) { var up = UserPrefs.LoadOrMakeNew(t.Path); Assert.That(up.MostRecentPage == 0); } }
public void LoadOrMakeNew_MostRecentPage_ReadsCorrectly() { using (var t = new TempFile("{\"mostRecentPage\":3}")) { var up = UserPrefs.LoadOrMakeNew(t.Path); Assert.That(up.MostRecentPage == 3); } }
public void ValidateFile_IllFormedXml_ReturnsProblem() { var handler = new LiftFileHandler(); using (var file = new TempFile("<lift>")) { var result = handler.ValidateFile(file.Path, new ConsoleProgress()); Assert.IsNotNull(result); } }
public void ValidateFile_SimpleLift_ReturnsNull() { var handler = new LiftFileHandler(); using(var file = new TempFile("<lift/>")) { var result = handler.ValidateFile(file.Path, new ConsoleProgress()); Assert.IsNull(result); } }
/// <summary> /// Process the input PDF file by compressing images and/or by converting color to CMYK. The operations /// to perform are established by the constructor. /// </summary> public void ProcessPdfFile(string inputFile, string outputFile) { _inputPdfPath = inputFile; _outputPdfPath = outputFile; var exePath = "/usr/bin/gs"; if (SIL.PlatformUtilities.Platform.IsWindows) { exePath = FindGhostcriptOnWindows(); } if (!String.IsNullOrWhiteSpace(exePath) && File.Exists(exePath)) { if (_worker != null) { _worker.ReportProgress(0, GetSpecificStatus()); } using (var tempPdfFile = TempFile.WithExtension(".pdf")) { var runner = new CommandLineRunner(); var arguments = GetArguments(tempPdfFile.Path); var fromDirectory = String.Empty; var progress = new NullProgress(); // I can't figure out how to use any IProgress based code, but we show progress okay as is. var res = runner.Start(exePath, arguments, Encoding.UTF8, fromDirectory, 3600, progress, ProcessGhostcriptReporting); if (res.DidTimeOut || !RobustFile.Exists(tempPdfFile.Path)) { if (_inputPdfPath != _outputPdfPath) { RobustFile.Copy(_inputPdfPath, _outputPdfPath, true); } return; } // If the process made the file larger and didn't change the color scheme, ignore the result. var oldInfo = new FileInfo(_inputPdfPath); var newInfo = new FileInfo(tempPdfFile.Path); if (newInfo.Length < oldInfo.Length || _type == OutputType.Printshop) { RobustFile.Copy(tempPdfFile.Path, _outputPdfPath, true); } else if (_inputPdfPath != _outputPdfPath) { RobustFile.Copy(_inputPdfPath, _outputPdfPath, true); } } } else { // This shouldn't happen. Linux Bloom package depends on the ghostscript package, and we'll include // ghostscript files in our installer to ensure it's available on Windows. But we have this code here // as a failsafe fallback reminding the developers to ensure this installation work happens. Debug.WriteLine("ghostscript is not installed, so Bloom cannot process the PDF file."); if (_inputPdfPath != _outputPdfPath) { RobustFile.Copy(_inputPdfPath, _outputPdfPath, true); } } }
public IEnumerable<IChangeReport> DescribeInitialContents(FileInRevision fileInRevision, TempFile file) { var dom = new XmlDocument(); dom.Load(file.Path); foreach (XmlNode e in dom.SafeSelectNodes("notes/annotation")) { yield return new XmlAdditionChangeReport(fileInRevision, e); } }
public void GetFileVersion_StandardLdml_LatestVersion() { string xml = LdmlContentForTests.Version3("en", "Latn", "", ""); using (var file = new TempFile(xml)) { var silLdmlVersion = new SilLdmlVersion(); int result = silLdmlVersion.GetFileVersion(file.Path); Assert.That(result, Is.EqualTo(LdmlDataMapper.CurrentLdmlVersion)); } }
public void GetFileVersion_WithoutLdml_ReturnsBadVersion() { string xml = LdmlContentForTests.NoLdml; using (var file = new TempFile(xml)) { var silLdmlVersion = new SilLdmlVersion(); int result = silLdmlVersion.GetFileVersion(file.Path); Assert.That(result, Is.EqualTo(SilLdmlVersion.BadVersion)); } }
public void LiftSynchronizerReadsLift15VersionCorrectly() { // Setup using (var myfile = new TempFile(testLift15File)) { // SUT var syncAdjunct = new LiftSynchronizerAdjunct(myfile.Path); // Verification Assert.AreEqual("LIFT0.15", syncAdjunct.BranchName, "BranchName should be 'LIFT0.15'"); } }
public void GetFileVersion_SilIdentity_LatestVersion() { string xml = LdmlContentForTests.Version3Identity("en", "Latn", "", "", "123456", "abcd", "variantName", "US", "53d542ba498f40f437f7723e69dcf64dab6c9794"); using (var file = new TempFile(xml)) { var silLdmlVersion = new SilLdmlVersion(); int result = silLdmlVersion.GetFileVersion(file.Path); Assert.That(result, Is.EqualTo(LdmlDataMapper.CurrentLdmlVersion)); } }
public void GetFileVersion_NoVersion_ReturnsMinus1() { string xml = @"<?xml version='1.0' encoding='UTF-8' ?> <configuration noversion='x'> <blah /> </configuration> ".Replace("'", "\""); using (var file = new TempFile(xml)) { var xPathVersion = new XPathVersion(10, "/configuration/@version"); int result = xPathVersion.GetFileVersion(file.Path); Assert.That(result, Is.EqualTo(-1)); } }
public void GetFileVersion_WithVersionAttribute_CorrectVersion() { string xml = @"<?xml version='1.0' encoding='UTF-8' ?> <configuration version='3'> <blah /> </configuration> ".Replace("'", "\""); using (var file = new TempFile(xml)) { var xPathVersion = new XPathVersion(10, "/configuration/@version"); int result = xPathVersion.GetFileVersion(file.Path); Assert.That(result, Is.EqualTo(3)); } }
public void DeletionReport_Not_ProducedForDeletedAnnotationUsingNotesHandler() { const string parent = @"<?xml version='1.0' encoding='utf-8'?> <notes version='0'> <annotation guid='old1'/> <annotation guid='soonToBeGoner'/> </notes>"; const string child = @"<?xml version='1.0' encoding='utf-8'?> <notes version='0'> <annotation guid='old1'/> </notes>"; // Make sure the common differ code does produce the deletion report. using (var parentTempFile = new TempFile(parent)) using (var childTempFile = new TempFile(child)) { var listener = new ListenerForUnitTests(); var differ = Xml2WayDiffer.CreateFromFiles(parentTempFile.Path, childTempFile.Path, listener, null, "annotation", "guid"); differ.ReportDifferencesToListener(); listener.AssertExpectedChangesCount(1); listener.AssertFirstChangeType<XmlDeletionChangeReport>(); } // Now make sure the ChorusNotesFileHandler filters it out, and does not return it, // as per the original notes differ code. var notesHandler = (from handler in ChorusFileTypeHandlerCollection.CreateWithInstalledHandlers().Handlers where handler.GetType().Name == "ChorusNotesFileHandler" select handler).First(); using (var repositorySetup = new RepositorySetup("randy")) { repositorySetup.AddAndCheckinFile("notestest.ChorusNotes", parent); repositorySetup.ChangeFileAndCommit("notestest.ChorusNotes", child, "change it"); var hgRepository = repositorySetup.Repository; var allRevisions = (from rev in hgRepository.GetAllRevisions() orderby rev.Number.LocalRevisionNumber select rev).ToList(); var first = allRevisions[0]; var second = allRevisions[1]; var firstFiR = hgRepository.GetFilesInRevision(first).First(); var secondFiR = hgRepository.GetFilesInRevision(second).First(); var result = notesHandler.Find2WayDifferences(firstFiR, secondFiR, hgRepository); Assert.AreEqual(0, result.Count()); } }
public void ShowNotesBrowser_LargeNumber() { using (var f = new TempFile("<notes version='0'/>")) { var r = AnnotationRepository.FromFile("id", f.Path, new NullProgress()); for (int i = 0; i < 10000; i++) { var annotation = new Annotation("question", string.Format("nowhere://blah?id={0}&label={1}", Guid.NewGuid().ToString(), i.ToString()), f.Path); r.AddAnnotation(annotation); annotation.AddMessage("test", "open", "blah blah"); } ShowBrowser(new List<AnnotationRepository> {r}); } }
public void GetFileVersion_WithNameSpace_CorrectVersion() { string xml = @"<?xml version='1.0' encoding='utf-8'?> <ldml> <special xmlns:palaso='urn://palaso.org/ldmlExtensions/v1'> <palaso:version value='3' /> </special> </ldml> ".Replace("'", "\""); using (var file = new TempFile(xml)) { var xPathVersion = new XPathVersion(10, "/ldml/special/palaso:version/@value"); xPathVersion.NamespaceManager.AddNamespace("palaso", "urn://palaso.org/ldmlExtensions/v1"); int result = xPathVersion.GetFileVersion(file.Path); Assert.That(result, Is.EqualTo(3)); } }
public void GetFileVersion_WithVersionAsDoubleUsingDelegate_CorrectVersion() { string xml = @"<?xml version='1.0' encoding='UTF-8' ?> <configuration version='3.0'> <blah /> </configuration> ".Replace("'", "\""); using (var file = new TempFile(xml)) { var xPathVersion = new XPathVersion(10, "/configuration/@version"); xPathVersion.VersionParser = delegate(string version) { double v = double.Parse(version); return (int) v; }; int result = xPathVersion.GetFileVersion(file.Path); Assert.That(result, Is.EqualTo(3)); } }
public void GuidAttrBeforeIdAttrDoesNotGenerateReports() { const string parent = @"<?xml version='1.0' encoding='utf-8'?> <root> <item id='fuzz-old1' guid='old1'/> </root>"; const string child = @"<?xml version='1.0' encoding='utf-8'?> <root> <item guid='old1' id='fuzz-old1'/> </root>"; using (var parentTempFile = new TempFile(parent)) using (var childTempFile = new TempFile(child)) { var listener = new ListenerForUnitTests(); var differ = Xml2WayDiffer.CreateFromFiles(parentTempFile.Path, childTempFile.Path, listener, null, "item", "id"); differ.ReportDifferencesToListener(); listener.AssertExpectedChangesCount(0); listener.AssertExpectedConflictCount(0); } }
public void Deletion_WasTombstoneNowMissing_NoDeletionReport() { const string parent = @"<?xml version='1.0' encoding='utf-8'?> <lift version='0.10' producer='WeSay 1.0.0.0'> <item id='old1' dateDeleted='2009-06-16T06:14:20Z'/> <item id='old2'/> </lift>"; const string child = @"<?xml version='1.0' encoding='utf-8'?> <lift version='0.10' producer='WeSay 1.0.0.0'> <item id='old2'/> </lift>"; using (var parentTempFile = new TempFile(parent)) using (var childTempFile = new TempFile(child)) { var listener = new ListenerForUnitTests(); var differ = Xml2WayDiffer.CreateFromFiles(parentTempFile.Path, childTempFile.Path, listener, null, "item", "id"); differ.ReportDifferencesToListener(); listener.AssertExpectedChangesCount(0); listener.AssertExpectedConflictCount(0); } }
public void DeletionReport_Not_ProducedForDeletionInParentAndChild() { var parent = @"<?xml version='1.0' encoding='utf-8'?> <lift version='0.10' producer='WeSay 1.0.0.0'> <entry id='old1' dateDeleted='2009-06-16T06:14:20Z'/> <entry id='old2'/> </lift>"; var child = @"<?xml version='1.0' encoding='utf-8'?> <lift version='0.10' producer='WeSay 1.0.0.0'> <entry id='old1' dateDeleted='2009-06-16T06:14:20Z'/> <entry id='old2'/> </lift>"; using (var parentTempFile = new TempFile(parent)) using (var childTempFile = new TempFile(child)) { var listener = new ListenerForUnitTests(); var differ = Xml2WayDiffer.CreateFromFiles(parentTempFile.Path, childTempFile.Path, listener, "header", "entry", "id"); differ.ReportDifferencesToListener(); listener.AssertExpectedChangesCount(0); } }
/// <summary> /// Save the image (of any format) to a jpeg file with 100 quality /// Note that this is still going to introduce some errors if the input is a bitmap. /// </summary> /// <remarks>Will throw if the destination is locked and the user tells us to give up. </remarks> public static void SaveAsTopQualityJpeg(Image image, string destinationPath) { var jpgEncoder = ImageCodecInfo.GetImageDecoders().First(codec => codec.FormatID == ImageFormat.Jpeg.Guid); var encoder = Encoder.Quality; //nb: there are cases (notably http://jira.palaso.org/issues/browse/WS-34711, after cropping a jpeg) where we get out of memory if we are not operating on a copy // Use a temporary file pathname in the destination folder. This is needed to ensure proper permissions are granted // to the resulting file later after FileUtils.ReplaceFileWithUserInteractionIfNeeded is called. That method may call // RobustFile.Replace which replaces both the file content and the file metadata (permissions). The result of that if we use // the user's temp directory is described in http://issues.bloomlibrary.org/youtrack/issue/BL-3954. using (var temp = TempFile.InFolderOf(destinationPath)) using (var safetyImage = new Bitmap(image)) { using (var parameters = new EncoderParameters(1)) { //0 = max compression, 100 = least parameters.Param[0] = new EncoderParameter(encoder, 100L); RobustImageIO.SaveImage(safetyImage, temp.Path, jpgEncoder, parameters); } SIL.IO.FileUtils.ReplaceFileWithUserInteractionIfNeeded(temp.Path, destinationPath, null); } }
/// <summary> /// Process the input PDF file by compressing images and/or by converting color to CMYK. The operations /// to perform are established by the constructor. /// </summary> public void ProcessPdfFile(string inputFile, string outputFile, bool removeEvenPages = false) { _inputPdfPath = inputFile; _outputPdfPath = outputFile; var exePath = "/usr/bin/gs"; if (SIL.PlatformUtilities.Platform.IsWindows) { exePath = FindGhostcriptOnWindows(); } if (!String.IsNullOrWhiteSpace(exePath) && File.Exists(exePath)) { if (_worker != null) { _worker.ReportProgress(0, GetSpecificStatus()); } using (var tempPdfFile = TempFile.WithExtension(".pdf")) { var runner = new CommandLineRunner(); var arguments = GetArguments(tempPdfFile.Path, null, removeEvenPages); var fromDirectory = String.Empty; var progress = new NullProgress(); // I can't figure out how to use any IProgress based code, but we show progress okay as is. var res = runner.Start(exePath, arguments, Encoding.UTF8, fromDirectory, 3600, progress, ProcessGhostcriptReporting); if (res.ExitCode != 0) { // On Linux, ghostscript doesn't deal well with some Unicode filenames. Try renaming the input // file temporarily to something innocuous to see if this makes the ghostscript process succeed. // See https://issues.bloomlibrary.org/youtrack/issue/BL-7177. using (var tempInputFile = TempFile.WithExtension(".pdf")) { RobustFile.Delete(tempInputFile.Path); // Move won't replace even empty files. RobustFile.Move(_inputPdfPath, tempInputFile.Path); arguments = GetArguments(tempPdfFile.Path, tempInputFile.Path, removeEvenPages); res = runner.Start(exePath, arguments, Encoding.UTF8, fromDirectory, 3600, progress, ProcessGhostcriptReporting); RobustFile.Move(tempInputFile.Path, _inputPdfPath); } } if (res.ExitCode != 0 || res.DidTimeOut || !RobustFile.Exists(tempPdfFile.Path)) { if (_inputPdfPath != _outputPdfPath) { RobustFile.Copy(_inputPdfPath, _outputPdfPath, true); } return; } // If the process made the file larger and didn't change the color scheme and we're not removing blank pages, ignore the result. var oldInfo = new FileInfo(_inputPdfPath); var newInfo = new FileInfo(tempPdfFile.Path); if (newInfo.Length < oldInfo.Length || _type == OutputType.Printshop || removeEvenPages) { RobustFile.Copy(tempPdfFile.Path, _outputPdfPath, true); } else if (_inputPdfPath != _outputPdfPath) { RobustFile.Copy(_inputPdfPath, _outputPdfPath, true); } } } else { // This shouldn't happen. Linux Bloom package depends on the ghostscript package, and we'll include // ghostscript files in our installer to ensure it's available on Windows. But we have this code here // as a failsafe fallback reminding the developers to ensure this installation work happens. Debug.WriteLine("ghostscript is not installed, so Bloom cannot process the PDF file."); if (_inputPdfPath != _outputPdfPath) { RobustFile.Copy(_inputPdfPath, _outputPdfPath, true); } } }
/// <summary> /// This is like a diff, but for when the file is first checked in. So, for example, a dictionary /// handler might list any the words that were already in the dictionary when it was first checked in. /// </summary> public IEnumerable<IChangeReport> DescribeInitialContents(FileInRevision fileInRevision, TempFile file) { throw new NotImplementedException(); }
public IEnumerable<IChangeReport> DescribeInitialContents(FileInRevision fileInRevision, TempFile file) { return new IChangeReport[] { new DefaultChangeReport(fileInRevision, "Added") }; }
public void SimpleChangeGeneratesReport() { const string parent = @"<?xml version='1.0' encoding='utf-8'?> <root> <item id='old1'/> </root>"; const string child = @"<?xml version='1.0' encoding='utf-8'?> <root> <item id='old1' newAttr='newValue' /> </root>"; using (var parentTempFile = new TempFile(parent)) using (var childTempFile = new TempFile(child)) { var listener = new ListenerForUnitTests(); var differ = Xml2WayDiffer.CreateFromFiles(parentTempFile.Path, childTempFile.Path, listener, null, "item", "id"); differ.ReportDifferencesToListener(); listener.AssertExpectedChangesCount(1); listener.AssertFirstChangeType<XmlChangedRecordReport>(); listener.AssertExpectedConflictCount(0); } }
public void Setup() { _tempFolder = new TemporaryFolder("ChorusSystemUsage"); _dataFolderRoot = _tempFolder.Path; _someDataFile = new TempFileFromFolder(_tempFolder, "test.txt", "hello"); _someDataFilePath = _someDataFile.Path; _chorusSystem = new ChorusSystem(_dataFolderRoot); _chorusSystem.Init("john"); }
public void Setup() { _folder = new TemporaryFolder("ChorusSystemTests"); _targetFile1 = new TempFileFromFolder(_folder, "one.txt", "just a pretend file"); _existingNotesFile = new TempFileFromFolder(_folder, "one.txt." + AnnotationRepository.FileExtension, @"<notes version='0'> <annotation ref='somwhere://foo?id=x' class='mergeConflict'> <message guid='123' author='merger' status='open' date='2009-07-18T23:53:04Z'> some description of the conflict </message> </annotation> </notes>"); _system = new ChorusSystem(_folder.Path); _system.Init(string.Empty); }
public void DuplicateIdInParentEntry_EmitsWarning() { var parent = @"<?xml version='1.0' encoding='utf-8'?> <lift version='0.10' producer='WeSay 1.0.0.0'> <entry id='old1'/> <entry id='old1'/> </lift>"; var child = @"<?xml version='1.0' encoding='utf-8'?> <lift version='0.10' producer='WeSay 1.0.0.0'> <entry id='old1' dateDeleted='2009-06-16T06:14:20Z'/> <entry id='old2'/> </lift>"; using (var parentTempFile = new TempFile(parent)) using (var childTempFile = new TempFile(child)) { var listener = new ListenerForUnitTests(); var differ = Xml2WayDiffer.CreateFromFiles(parentTempFile.Path, childTempFile.Path, listener, "header", "entry", "id"); differ.ReportDifferencesToListener(); Assert.AreEqual(1, listener.Warnings.Count); } }
public void GuidAttrBeforeIdAttrDoesNotGenerateReports() { var parent = @"<?xml version='1.0' encoding='utf-8'?> <lift version='0.10' producer='WeSay 1.0.0.0'> <entry id='fuzz-old1' guid='old1'/> </lift>"; var child = @"<?xml version='1.0' encoding='utf-8'?> <lift version='0.10' producer='WeSay 1.0.0.0'> <entry guid='old1' id='fuzz-old1'/> </lift>"; using (var parentTempFile = new TempFile(parent)) using (var childTempFile = new TempFile(child)) { var listener = new ListenerForUnitTests(); var differ = Xml2WayDiffer.CreateFromFiles(parentTempFile.Path, childTempFile.Path, listener, "header", "entry", "id"); differ.ReportDifferencesToListener(); listener.AssertExpectedChangesCount(0); } }
public void IdHasEntityDoesNotGenerateReports() { var parent = @"<?xml version='1.0' encoding='utf-8'?> <lift version='0.10' producer='WeSay 1.0.0.0'> <entry id=""Id'dPrematurely_18d66025-59bc-4bd0-b59c-0f01ae09dede"" dateCreated='2009-09-14T10:02:26Z' dateModified='2009-09-14T10:26:21Z' guid='18d66025-59bc-4bd0-b59c-0f01ae09dede'> </entry> </lift>"; var child = @"<?xml version='1.0' encoding='utf-8'?> <lift version='0.10' producer='WeSay 1.0.0.0'> <entry dateCreated='2009-09-14T10:02:26Z' dateModified='2009-09-14T10:26:21Z' guid='18d66025-59bc-4bd0-b59c-0f01ae09dede' id=""Id'dPrematurely_18d66025-59bc-4bd0-b59c-0f01ae09dede""> </entry> </lift>"; using (var parentTempFile = new TempFile(parent)) using (var childTempFile = new TempFile(child)) { var listener = new ListenerForUnitTests(); var differ = Xml2WayDiffer.CreateFromFiles(parentTempFile.Path, childTempFile.Path, listener, "header", "entry", "id"); differ.ReportDifferencesToListener(); listener.AssertExpectedChangesCount(0); } }
/// <summary> /// When images are copied from LibreOffice, images that were jpegs there are converted to bitmaps for the clipboard. /// So when we just saved them as bitmaps (pngs), we dramatically inflated the size of user's image files (and /// this then led to memory problems). /// So the idea here is just to try and detect that we should would be better off saving the image as a jpeg. /// Note that even at 100%, we're still going to lose some quality. So this method is only going to recommend /// doing that if the size would be at least 50% less. /// </summary> public static bool ShouldChangeFormatToJpeg(Image image) { try { using(var safetyImage = new Bitmap(image)) //nb: there are cases (notably http://jira.palaso.org/issues/browse/WS-34711, after cropping a jpeg) where we get out of memory if we are not operating on a copy { using(var jpegFile = new TempFile()) using(var pngFile = new TempFile()) { SIL.IO.RobustIO.SaveImage(image, pngFile.Path, ImageFormat.Png); SaveAsTopQualityJpeg(safetyImage, jpegFile.Path); var jpegInfo = new FileInfo(jpegFile.Path); var pngInfo = new FileInfo(pngFile.Path); // this is just our heuristic. const double fractionOfTheOriginalThatWouldWarrantChangingToJpeg = .5; return jpegInfo.Length < (pngInfo.Length*(1.0 - fractionOfTheOriginalThatWouldWarrantChangingToJpeg)); } } } catch(OutOfMemoryException e) { NonFatalProblem.Report(ModalIf.Alpha, PassiveIf.All,"Could not attempt conversion to jpeg.", "ref BL-3387", exception: e); return false; } }
public void WeRemovedEntry_Reported() { var child = @"<?xml version='1.0' encoding='utf-8'?> <lift version='0.10' producer='WeSay 1.0.0.0'> <entry id='old1'/> </lift>"; var parent = @"<?xml version='1.0' encoding='utf-8'?> <lift version='0.10' producer='WeSay 1.0.0.0'> <entry id='old1'/> <entry id='old2'/> </lift>"; using (var parentTempFile = new TempFile(parent)) using (var childTempFile = new TempFile(child)) { var listener = new ListenerForUnitTests(); var differ = Xml2WayDiffer.CreateFromFiles(parentTempFile.Path, childTempFile.Path, listener, "header", "entry", "id"); differ.ReportDifferencesToListener(); listener.AssertExpectedChangesCount(1); listener.AssertFirstChangeType<XmlDeletionChangeReport>(); } }