public static Response FromPartialStream(this IResponseFormatter response, Request request, Stream stream, string contentType) { // Store the len var len = stream.Length; // Create the response now var res = response.FromStream(stream, contentType) .WithHeader("Connection", "Keep-alive") .WithHeader("Accept-ranges", "Bytes"); // Use the partial status code res.StatusCode = HttpStatusCode.PartialContent; long startPos = 0; foreach (var s in request.Headers["Range"]) { var start = s.Split('=')[1]; var m = Regex.Match(start, @"(\d+)-(\d+)?"); start = m.Groups[1].Value; var end = len - 1; if (!string.IsNullOrWhiteSpace(m.Groups[2]?.Value)) { end = Convert.ToInt64(m.Groups[2].Value); } startPos = Convert.ToInt64(start); var length = len - startPos; res.WithHeader("Content-range", "Bytes " + start + "-" + end + "/" + len); res.WithHeader("Content-length", length.ToString(CultureInfo.InvariantCulture)); } stream.Seek(startPos, SeekOrigin.Begin); return(res); }
public static Response GetIcon(string key, IResponseFormatter response) { var image = ComicBook.PublisherIcons.GetImage(key); if (image == null) { return(response.AsRedirect("/original/Views/spacer.png")); } return(response.FromStream(GetBytesFromImage(image), MimeTypes.GetMimeType(".jpg"))); }
public static Response WriteTo(this IMetadataFormatter formatter, IResponseFormatter response) { var format = response.Context.GetResponseFormat(); if (format == ResponseFormat.Html) { return HttpStatusCode.NoContent; } var representation = format == ResponseFormat.Json ? "json" : "xml"; var encodedString = formatter.GetRepresentation(representation); var stream = new MemoryStream(Encoding.UTF8.GetBytes(encodedString)); return response.FromStream(stream, Euclid.Common.Extensions.MimeTypes.GetByExtension(representation)); }
public static Response AsAttachment( this IResponseFormatter formatter, Stream stream, string attachmentName, string contentType = "application/text") { Require.ArgumentNotNull(formatter, nameof(formatter)); Require.ArgumentNotNullEmpty(attachmentName, nameof(attachmentName)); Require.ArgumentNotNullEmpty(contentType, nameof(contentType)); var response = formatter.FromStream(stream, contentType); response.Headers.Add("Content-Disposition", $"attachment; filename={attachmentName}"); response.Headers.Add("Cache-Control", "no-cache"); response.StatusCode = HttpStatusCode.OK; return(response); }
public static Response GetPageImage(Guid id, int page, int width, int height, IResponseFormatter response) { // Restrict access to the FreeImage library to one thread at a time. lock (lockThis) { int max_width = 0; int max_height = 0; bool thumbnail = !(width == -1 && height == -1); bool processed = false; string filename = string.Format("{0}-p{1}-w{2}-h{3}.jpg", id, page, width, height); if (thumbnail) { MemoryStream cachestream = ImageCache.Instance.LoadFromCache(filename, true, false); // Cached thumbnails are assumed to be in the correct format and adhere to the size/format restrictions of the ipad. if (cachestream != null) { return(response.FromStream(cachestream, MimeTypes.GetMimeType(".jpg"))); } } else { // Check if a processed (rescaled and/or progressive) image is cached. string processed_filename = string.Format("{0}-p{1}-processed.jpg", id, page); MemoryStream cachestream = ImageCache.Instance.LoadFromCache(processed_filename, false, false); if (cachestream != null) { return(response.FromStream(cachestream, MimeTypes.GetMimeType(".jpg"))); } } MemoryStream stream = null; // Check if original image is in the cache. string org_filename = string.Format("{0}-p{1}.jpg", id, page); stream = ImageCache.Instance.LoadFromCache(org_filename, false, false); if (stream == null) { // Image is not in the cache, get it via ComicRack. var bytes = GetPageImageBytes(id, page); if (bytes == null) { return(HttpStatusCode.NotFound); } stream = new MemoryStream(bytes); // Always save the original page to the cache ImageCache.Instance.SaveToCache(org_filename, stream, false, false); } stream.Seek(0, SeekOrigin.Begin); Bitmap bitmap = new Bitmap(stream, false); int bitmap_width = (int)bitmap.Width; int bitmap_height = (int)bitmap.Height; if (ImageCache.Instance.use_max_dimension) { int mw, mh; if (bitmap_width >= bitmap_height) { mw = ImageCache.Instance.max_dimension_long; mh = ImageCache.Instance.max_dimension_short; } else { mw = ImageCache.Instance.max_dimension_short; mh = ImageCache.Instance.max_dimension_long; } if (bitmap_width > mw || bitmap_height > mh) { double scaleW = (double)mw / (double)bitmap_width; double scaleH = (double)mh / (double)bitmap_height; double scale = Math.Min(scaleW, scaleH); max_width = (int)Math.Floor(scale * bitmap_width); max_height = (int)Math.Floor(scale * bitmap_height); } else { max_width = bitmap_width; max_height = bitmap_height; } } else // Check if the image dimensions exceeds the maximum image dimensions if ((bitmap_width * bitmap_height) > ImageCache.Instance.maximum_imagesize) { max_width = (int)Math.Floor(Math.Sqrt((double)bitmap_width / (double)bitmap_height * (double)ImageCache.Instance.maximum_imagesize)); max_height = (int)Math.Floor((double)max_width * (double)bitmap_height / (double)bitmap_width); } else { max_width = bitmap_width; max_height = bitmap_height; } // Calculate the dimensions of the returned image. int result_width = width; int result_height = height; if (result_width == -1 && result_height == -1) { result_width = max_width; result_height = max_height; } else { if (result_width == -1) { result_height = Math.Min(max_height, result_height); double ratio = (double)result_height / (double)max_height; result_width = (int)Math.Floor(((double)max_width * ratio)); } else if (result_height == -1) { result_width = Math.Min(max_width, result_width); double ratio = (double)result_width / (double)max_width; result_height = (int)Math.Floor(((double)max_height * ratio)); } } // TODO: do this per requesting target device instead of using one global setting. // Resize ? if (result_width != bitmap_width || result_height != bitmap_height) { processed = true; Bitmap resizedBitmap = Resize(bitmap, result_width, result_height); bitmap.Dispose(); bitmap = resizedBitmap; resizedBitmap = null; } // Check if the image must be converted to progressive jpeg(Not using this) if (ImageCache.Instance.use_progressive_jpeg && (result_width * result_height) >= ImageCache.Instance.progressive_jpeg_size_threshold) { processed = true; // Convert image to progressive jpeg // FreeImage source code reveals that lower 7 bits of the FREE_IMAGE_SAVE_FLAGS enum are used for low-level quality control. // FREE_IMAGE_SAVE_FLAGS quality = (FREE_IMAGE_SAVE_FLAGS)ImageCache.Instance.progressive_jpeg_quality; //FREE_IMAGE_SAVE_FLAGS flags = FREE_IMAGE_SAVE_FLAGS.JPEG_SUBSAMPLING_444 | FREE_IMAGE_SAVE_FLAGS.JPEG_PROGRESSIVE | quality; //FIBITMAP dib = FreeImage.CreateFromBitmap(bitmap); //bitmap.Dispose(); //bitmap = null; //stream.Dispose(); stream = new MemoryStream(); bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg); bitmap = null; //FreeImage.SaveToStream(dib, stream, FREE_IMAGE_FORMAT.FIF_JPEG, flags); //FreeImage.Unload(dib); // dib.SetNull(); } else if (processed) { // image was rescaled, make new stream with rescaled bitmap stream = GetBytesFromImage(bitmap); // For now, images that were resized because they exceeded the maximum dimensions are not saved to the cache. } if (bitmap != null) { bitmap.Dispose(); bitmap = null; } // Always save thumbnails to the cache if (thumbnail) { ImageCache.Instance.SaveToCache(filename, stream, true, false); } else if (processed) { // Store rescaled and/or progressive jpegs in the cache for now. string processed_filename = string.Format("{0}-p{1}-processed.jpg", id, page); ImageCache.Instance.SaveToCache(processed_filename, stream, false, false); } stream.Seek(0, SeekOrigin.Begin); return(response.FromStream(stream, MimeTypes.GetMimeType(".jpg"))); } }
public static Response GetIcon(string key, IResponseFormatter response) { var image = ComicBook.PublisherIcons.GetImage(key); if (image == null) { return response.AsRedirect("/original/Views/spacer.png"); } return response.FromStream(GetBytesFromImage(image), MimeTypes.GetMimeType(".jpg")); }
public static Response GetPageImage(Guid id, int page, int width, int height, IResponseFormatter response) { // Restrict access to the FreeImage library to one thread at a time. lock(lockThis) { int max_width = 0; int max_height = 0; bool thumbnail = !(width == -1 && height == -1); bool processed = false; string filename = string.Format("{0}-p{1}-w{2}-h{3}.jpg", id, page, width, height); if (thumbnail) { MemoryStream cachestream = ImageCache.Instance.LoadFromCache(filename, true); // Cached thumbnails are assumed to be in the correct format and adhere to the size/format restrictions of the ipad. if (cachestream != null) return response.FromStream(cachestream, MimeTypes.GetMimeType(".jpg")); } else { // Check if a processed (rescaled and/or progressive) image is cached. string processed_filename = string.Format("{0}-p{1}-processed.jpg", id, page); MemoryStream cachestream = ImageCache.Instance.LoadFromCache(processed_filename, false); if (cachestream != null) return response.FromStream(cachestream, MimeTypes.GetMimeType(".jpg")); } MemoryStream stream = null; // Check if original image is in the cache. string org_filename = string.Format("{0}-p{1}.jpg", id, page); stream = ImageCache.Instance.LoadFromCache(org_filename, false); if (stream == null) { // Image is not in the cache, get it via ComicRack. var bytes = GetPageImageBytes(id, page); if (bytes == null) { return HttpStatusCode.NotFound; } stream = new MemoryStream(bytes); // Always save the original page to the cache ImageCache.Instance.SaveToCache(org_filename, stream, false); } stream.Seek(0, SeekOrigin.Begin); #if USE_GDI Bitmap bitmap = new Bitmap(stream, false); int bitmap_width = (int)bitmap.Width; int bitmap_height = (int)bitmap.Height; #elif USE_DIB FIBITMAP dib = FreeImage.LoadFromStream(stream); if (dib == null) { Console.WriteLine("Loading bitmap failed. Aborting."); // Check whether there was an error message. return HttpStatusCode.InternalServerError; } int bitmap_width = (int)FreeImage.GetWidth(dib); int bitmap_height = (int)FreeImage.GetHeight(dib); #elif USE_FIB FreeImageBitmap fib = FreeImageBitmap.FromStream(stream, false); if (fib == null) { Console.WriteLine("Loading bitmap failed. Aborting."); // Check whether there was an error message. return HttpStatusCode.InternalServerError; } int bitmap_width = (int)fib.Width; int bitmap_height = (int)fib.Height; #endif if (ImageCache.Instance.use_max_dimension) { int mw, mh; if (bitmap_width >= bitmap_height) { mw = ImageCache.Instance.max_dimension_long; mh = ImageCache.Instance.max_dimension_short; } else { mw = ImageCache.Instance.max_dimension_short; mh = ImageCache.Instance.max_dimension_long; } if (bitmap_width > mw || bitmap_height > mh) { double scaleW = (double)mw / (double)bitmap_width; double scaleH = (double)mh / (double)bitmap_height; double scale = Math.Min(scaleW, scaleH); max_width = (int)Math.Floor(scale * bitmap_width); max_height = (int)Math.Floor(scale * bitmap_height); } else { max_width = bitmap_width; max_height = bitmap_height; } } else // Check if the image dimensions exceeds the maximum image dimensions if ((bitmap_width * bitmap_height) > ImageCache.Instance.maximum_imagesize) { max_width = (int)Math.Floor(Math.Sqrt((double)bitmap_width / (double)bitmap_height * (double)ImageCache.Instance.maximum_imagesize)); max_height = (int)Math.Floor((double)max_width * (double)bitmap_height / (double)bitmap_width); } else { max_width = bitmap_width; max_height = bitmap_height; } // Calculate the dimensions of the returned image. int result_width = width; int result_height = height; if (result_width == -1 && result_height == -1) { result_width = max_width; result_height = max_height; } else { if (result_width == -1) { result_height = Math.Min(max_height, result_height); double ratio = (double)result_height / (double)max_height; result_width = (int)Math.Floor(((double)max_width * ratio)); } else if (result_height == -1) { result_width = Math.Min(max_width, result_width); double ratio = (double)result_width / (double)max_width; result_height = (int)Math.Floor(((double)max_height * ratio)); } } // TODO: do this per requesting target device instead of using one global setting. // Resize ? if (result_width != bitmap_width || result_height != bitmap_height) { processed = true; #if USE_DIB || USE_FIB //FREE_IMAGE_FILTER resizer = FREE_IMAGE_FILTER.FILTER_BICUBIC; FREE_IMAGE_FILTER resizer = FREE_IMAGE_FILTER.FILTER_LANCZOS3; #if USE_FIB fib.Rescale(result_width, result_height, resizer); #else FIBITMAP newdib = FreeImage.Rescale(dib, result_width, result_height, resizer); if (!newdib.IsNull) { FreeImage.Unload(dib); dib.SetNull(); dib = newdib; } #endif #elif USE_GDI Bitmap resizedBitmap = Resize(bitmap, result_width, result_height); bitmap.Dispose(); bitmap = resizedBitmap; resizedBitmap = null; #endif } // Check if the image must be converted to progressive jpeg if (ImageCache.Instance.use_progressive_jpeg && (result_width * result_height) >= ImageCache.Instance.progressive_jpeg_size_threshold) { processed = true; // Convert image to progressive jpeg // FreeImage source code reveals that lower 7 bits of the FREE_IMAGE_SAVE_FLAGS enum are used for low-level quality control. FREE_IMAGE_SAVE_FLAGS quality = (FREE_IMAGE_SAVE_FLAGS)ImageCache.Instance.progressive_jpeg_quality; FREE_IMAGE_SAVE_FLAGS flags = FREE_IMAGE_SAVE_FLAGS.JPEG_SUBSAMPLING_444 | FREE_IMAGE_SAVE_FLAGS.JPEG_PROGRESSIVE | quality; #if USE_DIB || USE_FIB stream.Dispose(); stream = new MemoryStream(); #if USE_FIB fib.Save(stream, FREE_IMAGE_FORMAT.FIF_JPEG, flags); fib.Dispose(); #else FreeImage.SaveToStream(dib, stream, FREE_IMAGE_FORMAT.FIF_JPEG, flags); FreeImage.Unload(dib); dib.SetNull(); #endif #else FIBITMAP dib = FreeImage.CreateFromBitmap(bitmap); bitmap.Dispose(); bitmap = null; stream.Dispose(); stream = new MemoryStream(); FreeImage.SaveToStream(dib, stream, FREE_IMAGE_FORMAT.FIF_JPEG, flags); FreeImage.Unload(dib); dib.SetNull(); #endif } else if (processed) { // image was rescaled, make new stream with rescaled bitmap #if USE_DIB || USE_FIB FREE_IMAGE_SAVE_FLAGS flags = FREE_IMAGE_SAVE_FLAGS.JPEG_SUBSAMPLING_444 | FREE_IMAGE_SAVE_FLAGS.JPEG_OPTIMIZE | FREE_IMAGE_SAVE_FLAGS.JPEG_QUALITYNORMAL; stream.Dispose(); stream = new MemoryStream(); #if USE_FIB fib.Save(stream, FREE_IMAGE_FORMAT.FIF_JPEG, flags); fib.Dispose(); #else FreeImage.SaveToStream(dib, stream, FREE_IMAGE_FORMAT.FIF_JPEG, flags); FreeImage.Unload(dib); dib.SetNull(); #endif #else stream = GetBytesFromImage(bitmap); #endif // For now, images that were resized because they exceeded the maximum dimensions are not saved to the cache. } #if USE_DIB FreeImage.Unload(dib); dib.SetNull(); #elif USE_FIB fib.Dispose(); #elif USE_GDI if (bitmap != null) { bitmap.Dispose(); bitmap = null; } #endif // Always save thumbnails to the cache if (thumbnail) { ImageCache.Instance.SaveToCache(filename, stream, true); } else if (processed) { // Store rescaled and/or progressive jpegs in the cache for now. string processed_filename = string.Format("{0}-p{1}-processed.jpg", id, page); ImageCache.Instance.SaveToCache(processed_filename, stream, false); } stream.Seek(0, SeekOrigin.Begin); return response.FromStream(stream, MimeTypes.GetMimeType(".jpg")); } }
public static Response GetThumbnailImage(Guid id, int page, IResponseFormatter response) { var bitmap = Image.FromStream(new MemoryStream(GetPageImageBytes(id, page)), false, false); double ratio = 200D / (double)bitmap.Height; int width = (int)(bitmap.Width * ratio); var callback = new Image.GetThumbnailImageAbort(() => true); var thumbnail = bitmap.GetThumbnailImage(width, 200, callback, IntPtr.Zero); MemoryStream stream = GetBytesFromImage(thumbnail); return response.FromStream(stream, MimeTypes.GetMimeType(".jpg")); }
public static Response GetPageImage(Guid id, int page, IResponseFormatter response) { var bytes = GetPageImageBytes(id, page); if (bytes == null) { return response.AsRedirect("/Comics/Images/spacer.png"); } return response.FromStream(new MemoryStream(bytes), MimeTypes.GetMimeType(".jpg")); }