private void GenerateGenericThumbnailImage(string newFilePath, IGallerySettings gallerySetting) { // Build a generic thumbnail. var sourceFilePath = GetGenericThumbnailFilePath(GalleryObject.MimeType); var size = ImageHelper.SaveImageFileAsJpeg(sourceFilePath, newFilePath, gallerySetting.MaxThumbnailLength, true, gallerySetting.ThumbnailImageJpegQuality); GalleryObject.Thumbnail.Width = size.Width; GalleryObject.Thumbnail.Height = size.Height; }
/// <summary> /// Creates an image file having a max length of <paramref name="maxLength" /> and JPEG quality of /// <paramref name="jpegQuality" /> from the original file of <see cref="GalleryObject" />. The file is saved to the location /// <paramref name="newFilePath" />. The width and height of the generated image is returned as a <see cref="ISize" /> instance. /// </summary> /// <param name="newFilePath">The full path where the image will be saved.</param> /// <param name="maxLength">The maximum length of one side of the image.</param> /// <param name="jpegQuality">The JPEG quality.</param> /// <returns>Returns a <see cref="ISize" /> instance containing the width and height of the generated image.</returns> /// <exception cref="UnsupportedImageTypeException">Thrown when Gallery Server cannot process the image, /// most likely because it is corrupt or an unsupported image type. /// </exception> protected ISize GenerateImageUsingDotNet(string newFilePath, int maxLength, int jpegQuality) { try { var newSize = ImageHelper.SaveImageFileAsJpeg(GalleryObject.Original.FileInfo.FullName, newFilePath, maxLength, false, jpegQuality); var rotatedSize = ExecuteAutoRotation(newFilePath, jpegQuality); return rotatedSize.IsEmpty ? newSize : rotatedSize; } catch (ArgumentException ex) { throw new UnsupportedImageTypeException(GalleryObject, ex); } catch (ExternalException ex) { throw new UnsupportedImageTypeException(GalleryObject, ex); } catch (OutOfMemoryException ex) { throw new UnsupportedImageTypeException(GalleryObject, ex); } }
/// <summary> /// Generate the thumbnail image for this display object and save it to the file system. The routine may decide that /// a file does not need to be generated, usually because it already exists. However, it will always be /// created if the relevant flag is set on the parent <see cref="IGalleryObject" />. (Example: If /// <see cref="IGalleryObject.RegenerateThumbnailOnSave" /> = true, the thumbnail file will always be created.) No data is /// persisted to the data store. /// </summary> public override void GenerateAndSaveFile() { // If necessary, generate and save the thumbnail version of the original image. if (!(IsThumbnailImageRequired())) { return; // No thumbnail image required. } IGallerySettings gallerySetting = Factory.LoadGallerySetting(GalleryObject.GalleryId); // Determine file name and path of the thumbnail image. If a file name has already been previously // calculated for this media object, re-use it. Otherwise generate a unique name. var newFilename = GalleryObject.Thumbnail.FileName; var newFilePath = GalleryObject.Thumbnail.FileNamePhysicalPath; if (String.IsNullOrEmpty(newFilePath)) { var thumbnailPath = HelperFunctions.MapAlbumDirectoryStructureToAlternateDirectory(this.GalleryObject.Parent.FullPhysicalPath, gallerySetting.FullThumbnailPath, gallerySetting.FullMediaObjectPath); newFilename = HelperFunctions.ValidateFileName(thumbnailPath, GenerateNewFilename(gallerySetting.ThumbnailFileNamePrefix)); newFilePath = Path.Combine(thumbnailPath, newFilename); } // Get reference to the bitmap from which the thumbnail image will be generated. var sourceFilePath = GetGenericThumbnailFilePath(GalleryObject.MimeType); var size = ImageHelper.SaveImageFileAsJpeg(sourceFilePath, newFilePath, gallerySetting.MaxThumbnailLength, true, gallerySetting.ThumbnailImageJpegQuality); GalleryObject.Thumbnail.Width = size.Width; GalleryObject.Thumbnail.Height = size.Height; GalleryObject.Thumbnail.FileName = newFilename; GalleryObject.Thumbnail.FileNamePhysicalPath = newFilePath; int fileSize = (int)(GalleryObject.Thumbnail.FileInfo.Length / 1024); GalleryObject.Thumbnail.FileSizeKB = (fileSize < 1 ? 1 : fileSize); // Very small files should be 1, not 0. }
private void GenerateThumbnailImageUsingImageMagick(string newFilePath, IGallerySettings gallerySetting) { // Generate a temporary filename to store the thumbnail created by ImageMagick. string tmpImageThumbnailPath = Path.Combine(AppSetting.Instance.TempUploadDirectory, String.Concat(Guid.NewGuid().ToString(), ".jpg")); // Request that ImageMagick create the thumbnail. If successful, the file will be created. If not, it fails silently. ImageMagick.GenerateImage(GalleryObject.Original.FileNamePhysicalPath, tmpImageThumbnailPath, GalleryObject.GalleryId); if (File.Exists(tmpImageThumbnailPath)) { try { // ImageMagick successfully created a thumbnail image. Now resize it to the width and height we need. var size = ImageHelper.SaveImageFileAsJpeg(tmpImageThumbnailPath, newFilePath, gallerySetting.MaxThumbnailLength, false, gallerySetting.ThumbnailImageJpegQuality); GalleryObject.Thumbnail.Width = size.Width; GalleryObject.Thumbnail.Height = size.Height; //using (var originalBitmap = new Bitmap(tmpImageThumbnailPath)) //{ // var newSize = CalculateWidthAndHeight(new Size(originalBitmap.Width, originalBitmap.Height), gallerySetting.MaxThumbnailLength, false); // // Get JPEG quality value (0 - 100). This is ignored if imgFormat = GIF. // int jpegQuality = gallerySetting.ThumbnailImageJpegQuality; // // Generate the new image and save to disk. // var size = ImageHelper.SaveImageFile(originalBitmap, newFilePath, ImageFormat.Jpeg, newSize.Width, newSize.Height, jpegQuality); // GalleryObject.Thumbnail.Width = (int)size.Width; // GalleryObject.Thumbnail.Height = (int)size.Height; //} } catch (Exception ex) { ex.Data.Add("GSP Info", String.Format("This error occurred while trying to process the ImageMagick-generated file {0}. The original file is {1}. A generic thumbnail image will be created instead.", tmpImageThumbnailPath, GalleryObject.Original.FileNamePhysicalPath)); Events.EventController.RecordError(ex, AppSetting.Instance, GalleryObject.GalleryId, Factory.LoadGallerySettings()); // Default to a generic thumbnail image. GenerateGenericThumbnailImage(newFilePath, gallerySetting); } try { // Now delete the thumbnail image created by FFmpeg, but no worries if an error happens. The file is in the temp directory // which is cleaned out each time the app starts anyway. File.Delete(tmpImageThumbnailPath); } catch (IOException ex) { ex.Data.Add("GSP Info", "This error was handled and did not interfere with the user experience."); Events.EventController.RecordError(ex, AppSetting.Instance, GalleryObject.GalleryId, Factory.LoadGallerySettings()); } catch (UnauthorizedAccessException ex) { ex.Data.Add("GSP Info", "This error was handled and did not interfere with the user experience."); Events.EventController.RecordError(ex, AppSetting.Instance, GalleryObject.GalleryId, Factory.LoadGallerySettings()); } catch (NotSupportedException ex) { ex.Data.Add("GSP Info", "This error was handled and did not interfere with the user experience."); Events.EventController.RecordError(ex, AppSetting.Instance, GalleryObject.GalleryId, Factory.LoadGallerySettings()); } } else { // ImageMagick didn't create an image, so default to a generic one. GenerateGenericThumbnailImage(newFilePath, gallerySetting); } }
/// <summary> /// Generate the thumbnail image for this display object and save it to the file system. The routine may decide that /// a file does not need to be generated, usually because it already exists. However, it will always be /// created if the relevant flag is set on the parent <see cref="IGalleryObject" />. (Example: If /// <see cref="IGalleryObject.RegenerateThumbnailOnSave" /> = true, the thumbnail file will always be created.) No data is /// persisted to the data store. /// </summary> public override void GenerateAndSaveFile() { // If necessary, generate and save the thumbnail version of the video. if (!(IsThumbnailImageRequired())) { return; // No thumbnail image required. } IGallerySettings gallerySetting = Factory.LoadGallerySetting(GalleryObject.GalleryId); // Generate a temporary filename to store the thumbnail created by FFmpeg. string tmpVideoThumbnailPath = Path.Combine(AppSetting.Instance.TempUploadDirectory, String.Concat(Guid.NewGuid().ToString(), ".jpg")); // Request that FFmpeg create the thumbnail. If successful, the file will be created. FFmpeg.GenerateThumbnail(GalleryObject.Original.FileNamePhysicalPath, tmpVideoThumbnailPath, gallerySetting.VideoThumbnailPosition, GalleryObject.GalleryId); // Verify image was created from video, trying again using a different video position setting if necessary. ValidateVideoThumbnail(tmpVideoThumbnailPath, gallerySetting.VideoThumbnailPosition); // Determine file name and path of the thumbnail image. If a file name has already been previously // calculated for this media object, re-use it. Otherwise generate a unique name. var newFilename = GalleryObject.Thumbnail.FileName; var newFilePath = GalleryObject.Thumbnail.FileNamePhysicalPath; if (String.IsNullOrEmpty(newFilePath)) { var thumbnailPath = HelperFunctions.MapAlbumDirectoryStructureToAlternateDirectory(this.GalleryObject.Original.FileInfo.DirectoryName, gallerySetting.FullThumbnailPath, gallerySetting.FullMediaObjectPath); newFilename = GenerateJpegFilename(thumbnailPath, gallerySetting.ThumbnailFileNamePrefix); newFilePath = Path.Combine(thumbnailPath, newFilename); } if (File.Exists(tmpVideoThumbnailPath)) { // FFmpeg successfully created a thumbnail image the same size as the video. Now resize it to the width and height we need. var size = ImageHelper.SaveImageFileAsJpeg(tmpVideoThumbnailPath, newFilePath, gallerySetting.MaxThumbnailLength, false, gallerySetting.ThumbnailImageJpegQuality); var rotatedSize = ExecuteAutoRotation(newFilePath, gallerySetting.ThumbnailImageJpegQuality); if (!rotatedSize.IsEmpty) { size = rotatedSize; } GalleryObject.Thumbnail.Width = (int)size.Width; GalleryObject.Thumbnail.Height = (int)size.Height; //using (Bitmap originalBitmap = new Bitmap(tmpVideoThumbnailPath)) //{ // var newSize = CalculateWidthAndHeight(new Size(originalBitmap.Width, originalBitmap.Height), gallerySetting.MaxThumbnailLength, false); // // Get JPEG quality value (0 - 100). This is ignored if imgFormat = GIF. // int jpegQuality = gallerySetting.ThumbnailImageJpegQuality; // // Generate the new image and save to disk. // var size = ImageHelper.SaveImageFile(originalBitmap, newFilePath, ImageFormat.Jpeg, newSize.Width, newSize.Height, jpegQuality); // var rotatedSize = ExecuteAutoRotation(newFilePath, jpegQuality); // if (!rotatedSize.IsEmpty) // { // size = rotatedSize; // } // GalleryObject.Thumbnail.Width = (int)size.Width; // GalleryObject.Thumbnail.Height = (int)size.Height; //} try { // Now delete the thumbnail image created by FFmpeg, but no worries if an error happens. The file is in the temp directory // which is cleaned out each time the app starts anyway. File.Delete(tmpVideoThumbnailPath); } catch (IOException ex) { EventController.RecordError(ex, AppSetting.Instance, GalleryObject.GalleryId, Factory.LoadGallerySettings()); } catch (UnauthorizedAccessException ex) { EventController.RecordError(ex, AppSetting.Instance, GalleryObject.GalleryId, Factory.LoadGallerySettings()); } catch (NotSupportedException ex) { EventController.RecordError(ex, AppSetting.Instance, GalleryObject.GalleryId, Factory.LoadGallerySettings()); } } else { // FFmpeg didn't run or no thumbnail image was created by FFmpeg. Build a generic video thumbnail. var thumbImagePath = Path.Combine(AppSetting.Instance.WebRootPath, GlobalConstants.GenericThumbnailDirectory, GlobalConstants.GenericVideoThumbnailFileName); var size = ImageHelper.SaveImageFileAsJpeg(thumbImagePath, newFilePath, gallerySetting.MaxThumbnailLength, true, gallerySetting.ThumbnailImageJpegQuality); GalleryObject.Thumbnail.Width = size.Width; GalleryObject.Thumbnail.Height = size.Height; //using (var ms = new MemoryStream(Resources.GenericThumbnailImage_Video)) //{ // using (var originalBitmap = new Bitmap(ms)) // { // var newSize = CalculateWidthAndHeight(new Size(originalBitmap.Width, originalBitmap.Height), gallerySetting.MaxThumbnailLength, true); // // Get JPEG quality value (0 - 100). // int jpegQuality = gallerySetting.ThumbnailImageJpegQuality; // // Generate the new image and save to disk. // var size = ImageHelper.SaveImageFile(originalBitmap, newFilePath, ImageFormat.Jpeg, newSize.Width, newSize.Height, jpegQuality); // GalleryObject.Thumbnail.Width = (int)size.Width; // GalleryObject.Thumbnail.Height = (int)size.Height; // } //} } GalleryObject.Thumbnail.FileName = newFilename; GalleryObject.Thumbnail.FileNamePhysicalPath = newFilePath; int fileSize = (int)(GalleryObject.Thumbnail.FileInfo.Length / 1024); GalleryObject.Thumbnail.FileSizeKB = (fileSize < 1 ? 1 : fileSize); // Very small files should be 1, not 0. }