Example #1
0
        public static StreamInfo RetrievePreview(ResourceBE attachment, uint height, uint width, RatioType ratio, SizeType size, FormatType format, out string filename)
        {
            if (!AttachmentBL.Instance.IsAllowedForImageMagickPreview(attachment))
            {
                throw new AttachmentPreviewFailedWithMimeTypeNotImplementedException(attachment.MimeType);
            }
            if (format != FormatType.UNDEFINED && size != SizeType.UNDEFINED && size != SizeType.ORIGINAL && size != SizeType.CUSTOM)
            {
                throw new AttachmentPreviewFormatConversionWithSizeNotImplementedException();
            }

            // check that attachment has a width and height defined
            AttachmentBL.Instance.IdentifyUnknownImages(new ResourceBE[] { attachment });

            #region check validity of size, width, and height parameters

            // NOTE (steveb): following table describes the possible state-transitions; note that the resulting graph must acyclic to avoid infinite loops.
            //      BESTFIT
            //          -> THUMB
            //          -> WEBVIEW
            //          -> ORIGINAL
            //      UNDEFINED
            //          -> CUSTOM
            //          -> ORIGINAL
            //      THUMB
            //          -> ORIGINAL
            //      WEBVIEW
            //          -> ORIGINAL
            //      CUSTOM
            //          -> ORIGINAL
            //      ORIGINAL
again:
            switch (size)
            {
            case SizeType.BESTFIT:
                if (width == 0 && height == 0)
                {
                    // no dimensions specified, use original
                    size = SizeType.ORIGINAL;
                    goto again;
                }
                if (width <= DekiContext.Current.Instance.ImageThumbPixels && height <= DekiContext.Current.Instance.ImageThumbPixels)
                {
                    // thumbnail is big enough
                    size = SizeType.THUMB;
                    goto again;
                }
                else if (width <= DekiContext.Current.Instance.ImageWebviewPixels && height <= DekiContext.Current.Instance.ImageWebviewPixels)
                {
                    // webview is big enough
                    size = SizeType.WEBVIEW;
                    goto again;
                }
                else
                {
                    // use original
                    size = SizeType.ORIGINAL;
                    goto again;
                }

            case SizeType.CUSTOM:
                if (height == 0 && width == 0)
                {
                    // no dimensions specified, use original
                    size = SizeType.ORIGINAL;
                    goto again;
                }
                if ((attachment.MetaXml.ImageWidth <= width && attachment.MetaXml.ImageHeight <= height) && (attachment.MetaXml.ImageWidth >= 0 && attachment.MetaXml.ImageHeight >= 0))
                {
                    // requested dimensions are larger than original, use original (we don't scale up!)
                    size = SizeType.ORIGINAL;
                    goto again;
                }
                break;

            case SizeType.ORIGINAL:
                width  = 0;
                height = 0;
                break;

            case SizeType.UNDEFINED:
                if (height != 0 || width != 0)
                {
                    size = SizeType.CUSTOM;
                    goto again;
                }
                else
                {
                    size = SizeType.ORIGINAL;
                    goto again;
                }

            case SizeType.THUMB:
                width  = DekiContext.Current.Instance.ImageThumbPixels;
                height = DekiContext.Current.Instance.ImageThumbPixels;
                if ((attachment.MetaXml.ImageWidth <= width && attachment.MetaXml.ImageHeight <= height) && (attachment.MetaXml.ImageWidth >= 0 && attachment.MetaXml.ImageHeight >= 0))
                {
                    size = SizeType.ORIGINAL;
                    goto again;
                }
                break;

            case SizeType.WEBVIEW:
                width  = DekiContext.Current.Instance.ImageWebviewPixels;
                height = DekiContext.Current.Instance.ImageWebviewPixels;
                if ((attachment.MetaXml.ImageWidth <= width && attachment.MetaXml.ImageHeight <= height) && (attachment.MetaXml.ImageWidth >= 0 && attachment.MetaXml.ImageHeight >= 0))
                {
                    size = SizeType.ORIGINAL;
                    goto again;
                }
                break;
            }
            #endregion


            // Asking to convert to the same format as original
            if (format != FormatType.UNDEFINED && format == ResolvePreviewFormat(attachment.MimeType))
            {
                format = FormatType.UNDEFINED;
            }

            //Determine if the result is capable of being cached
            bool cachable = (
                format == FormatType.UNDEFINED &&                    //No format conversion
                ratio != RatioType.VARIABLE &&                       //must be a fixed aspect ratio or not provided
                (size == SizeType.THUMB || size == SizeType.WEBVIEW) //must be one of the known cached thumb sizes.
                );

            // load image
            StreamInfo result = null;
            try {
                if (size == SizeType.ORIGINAL && format == FormatType.UNDEFINED)
                {
                    result = DekiContext.Current.Instance.Storage.GetFile(attachment, SizeType.ORIGINAL, false);
                }
                else
                {
                    bool cached = false;

                    //The type of image is based on uploaded file's mimetype
                    if (format == FormatType.UNDEFINED)
                    {
                        format = ResolvePreviewFormat(attachment.MimeType);
                    }

                    // check if image can be taken from the cache
                    if (cachable)
                    {
                        result = GetCachedThumb(attachment, size);
                        cached = (result != null);
                    }

                    // load image if we haven't yet
                    if (result == null)
                    {
                        result = DekiContext.Current.Instance.Storage.GetFile(attachment, SizeType.ORIGINAL, false);
                        if (result != null)
                        {
                            result = BuildThumb(attachment, result, format, ratio, width, height);
                        }
                    }

                    // store result if possible and needed
                    if (cachable && !cached && (result != null))
                    {
                        SaveCachedThumb(attachment, size, result);
                        result = GetCachedThumb(attachment, size);
                    }
                }
                if (result == null)
                {
                    ThrowOnBadPreviewImage();
                }

                // full filename for response content-disposition header
                switch (size)
                {
                case SizeType.CUSTOM:
                    filename = string.Format("{0}_({1}x{2}){3}", attachment.Name, width == 0 ? "" : width.ToString(), height == 0 ? "" : height.ToString(), attachment.FilenameExtension == string.Empty ? string.Empty : "." + attachment.FilenameExtension);
                    break;

                case SizeType.ORIGINAL:
                    filename = attachment.Name;
                    break;

                case SizeType.BESTFIT:
                case SizeType.THUMB:
                case SizeType.UNDEFINED:
                case SizeType.WEBVIEW:
                default:
                    filename = string.Format("{0}_({1}){2}", attachment.Name, size.ToString().ToLowerInvariant(), attachment.FilenameExtension == string.Empty ? string.Empty : "." + attachment.FilenameExtension);
                    break;
                }
                if (format != FormatType.UNDEFINED)
                {
                    filename = Path.ChangeExtension(filename, format.ToString().ToLowerInvariant());
                }
                return(result);
            } catch {
                if (result != null)
                {
                    result.Close();
                }
                throw;
            }
        }