/// <summary> /// Creates an ePub file at the location specified by parameters /// </summary> /// <param name="parameters">BookPath and epubOutputPath should be set.</param> /// <param name="control">The epub code needs a control that goes back to the main thread, in order to run some tasks that need to be on the main thread</param> public static void CreateEpubArtifact(CreateArtifactsParameters parameters, Control control) { if (String.IsNullOrEmpty(parameters.EpubOutputPath)) { return; } string directoryName = Path.GetDirectoryName(parameters.EpubOutputPath); Directory.CreateDirectory(directoryName); // Ensures that the directory exists BookServer bookServer = _projectContext.BookServer; BookThumbNailer thumbNailer = _projectContext.ThumbNailer; var maker = new EpubMaker(thumbNailer, bookServer); maker.ControlForInvoke = control; maker.Book = _book; maker.Unpaginated = true; // so far they all are maker.OneAudioPerPage = true; // default used in EpubApi // Enhance: maybe we want book to have image descriptions on page? use reader font sizes? // Make the epub maker.SaveEpub(parameters.EpubOutputPath, new NullWebSocketProgress()); }
private static CreateArtifactsExitCode CreateArtifacts(CreateArtifactsParameters parameters) { var exitCode = CreateArtifactsExitCode.Success; LoadBook(parameters.BookPath); string zippedBloomPubOutputPath = parameters.BloomPubOutputPath; string unzippedBloomDigitalOutputPath = parameters.BloomDigitalOutputPath; string zippedBloomSourceOutputPath = parameters.BloomSourceOutputPath; bool isBloomDOrBloomDigitalRequested = !String.IsNullOrEmpty(zippedBloomPubOutputPath) || !String.IsNullOrEmpty(unzippedBloomDigitalOutputPath); if (isBloomDOrBloomDigitalRequested) { exitCode |= CreateBloomDigitalArtifacts(parameters.BookPath, parameters.Creator, zippedBloomPubOutputPath, unzippedBloomDigitalOutputPath); } if (!String.IsNullOrEmpty(zippedBloomSourceOutputPath)) { exitCode |= CreateBloomSourceArtifact(parameters.BookPath, parameters.Creator, zippedBloomSourceOutputPath); } Control control = new Control(); control.CreateControl(); using (var countdownEvent = new CountdownEvent(1)) { // Create the ePub in the background. (Some of the ePub work needs to happen off the main thread) ThreadPool.QueueUserWorkItem( x => { try { CreateEpubArtifact(parameters, control); } catch (Exception ex) { Console.WriteLine(ex.ToString()); exitCode = CreateArtifactsExitCode.EpubException; } countdownEvent.Signal(); // Decrement by one } ); // Wait around until the worker thread is done. while (!countdownEvent.IsSet) // Set = true if the count is down to 0. { Thread.Sleep(100); Application.DoEvents(); } } CreateThumbnailArtifact(parameters); return(exitCode); }
/// <summary> /// Calculates the perceptual hash of the first content image of the book and writes it to a file /// The perceptual hash may very well take on the value null. If so, the file will contain the literal string "null" (without the quotes) in it. /// </summary> /// <param name="parameters">parameters.PHashOutputInfoPath should contain the file path to which the create/write the PHash</param> public static void CreatePHashArtifact(CreateArtifactsParameters parameters) { if (String.IsNullOrWhiteSpace(parameters.PHashOutputInfoPath)) { return; } // This could take a second or more. string pHash = _book.ComputePHashOfFirstContentImage(); using (var writer = new StreamWriter(parameters.PHashOutputInfoPath, append: false)) { // Do note that the pHash may be null and it is expected that some books will legitimately have a null pHash // so we write this value explicitly so that consumers can explicitly detect this. writer.WriteLine(pHash ?? "null"); } }
public static int Handle(CreateArtifactsParameters options) { try { Console.Out.WriteLine(); Program.SetUpErrorHandling(); using (var applicationContainer = new ApplicationContainer()) { Program.SetUpLocalization(applicationContainer); Browser.SetUpXulRunner(); Browser.XulRunnerShutdown += Program.OnXulRunnerShutdown; LocalizationManager.SetUILanguage(Settings.Default.UserInterfaceLanguage, false); // Unclear if this line is needed or not. if (DesktopAnalytics.Analytics.AllowTracking) { throw new ApplicationException("Allow tracking is enabled but we don't want the Harvester to actually send analytics."); } Program.RunningHarvesterMode = true; string collectionFilePath = options.CollectionPath; using (_projectContext = applicationContainer.CreateProjectContext(collectionFilePath)) { Bloom.Program.SetProjectContext(_projectContext); // Make the .bloomd and /bloomdigital outputs var exitCode = CreateArtifacts(options); return((int)exitCode); } } } catch (Exception ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); return((int)CreateArtifactsExitCode.UnhandledException); } }
public static void CreateThumbnailArtifact(CreateArtifactsParameters parameters) { if (String.IsNullOrWhiteSpace(parameters.ThumbnailOutputInfoPath)) { return; } var outputPaths = new List <string>(); int[] requestedHeights = new int[2] { 256, 70 }; foreach (int height in requestedHeights) { // A potential "enhancement" is that we could try to re-use the thumbnail generated when making an ePUB. // That could be helpful if creating new thumbnails was a big enough cost // The ePub Path looks like this: $"%TEMP%\\ePUB_export\\{i}\\{book.Title}\\thumbnail-{height}.png" // (where i is an integer between 0-19. Depends on whether it's been locked or not.) // // For now, we'll just create the thumbnail every time // It makes the code simpler than having fallback logic not to mention the complications of determining which folder the ePub is in, whether it's really up-to-date, etc. string thumbnailPath = BookThumbNailer.GenerateCoverImageOfRequestedMaxSize(_book, height); AppendPathIfExists(thumbnailPath, outputPaths); } string shareThumbnail = BookThumbNailer.GenerateSocialMediaSharingThumbnail(_book); AppendPathIfExists(shareThumbnail, outputPaths); using (var writer = new StreamWriter(parameters.ThumbnailOutputInfoPath, append: false)) { foreach (var path in outputPaths) { writer.WriteLine(path); } } }