Ejemplo n.º 1
0
        static void WriteImages(BitmapTag bitmap, string outPath)
        {
            var ms = new MemoryStream();

            for (var i = 0; i < bitmap.TextureInfos[0].LevelsOfDetail.Length; i++)
            {
                var lod = bitmap.TextureInfos[0].LevelsOfDetail[i];

                if (lod.Data.IsEmpty)
                {
                    continue;
                }

                var ddsHeader = new DdsHeader(
                    bitmap.TextureInfos[0].Format,
                    bitmap.TextureType,
                    bitmap.TextureInfos[0].Width,
                    bitmap.TextureInfos[0].Height,
                    bitmap.TextureInfos[0].Depth,
                    bitmap.MipMapCount,
                    null,
                    null);

                ddsHeader.HeaderData.CopyTo(ms);

                ms.Write(lod.Data.ToArray(), 0, lod.Data.Length);
            }

            ms.Position     = 0;
            using var image = Pfim.Dds.Create(ms, new Pfim.PfimConfig());

            using Image imsImage = image.Format switch
                  {
                      Pfim.ImageFormat.Rgb24 => Image.LoadPixelData <Bgr24>(image.Data, image.Width, image.Height),
                      Pfim.ImageFormat.Rgba32 => Image.LoadPixelData <Bgra32>(image.Data, image.Width, image.Height),
                      _ => throw new NotSupportedException()
                  };

            // UI images aren't fully opaque, making it so
            imsImage.Mutate(x => x.ProcessPixelRowsAsVector4((Span <Vector4> span) =>
            {
                for (var i = 0; i < span.Length; i++)
                {
                    if (span[i].W > 0f)
                    {
                        span[i].W = 1f;
                    }
                }
            }));
            imsImage.SaveAsPng(Path.Combine(outPath, "full.png"));

            imsImage.Mutate(x => x.Resize(ThumbnailSize, ThumbnailSize));
            imsImage.SaveAsPng(Path.Combine(outPath, "thumbnail.png"));
        }
Ejemplo n.º 2
0
        public static void WriteTextureHeader(BitmapTag bitm, Stream destination)
        {
            var ddsHeader = DdsHeader.Create(
                bitm.TextureInfos[0].Format,
                CapsLookup[bitm.TextureType],
                Caps2Lookup[bitm.TextureType],
                bitm.TextureInfos[0].Width,
                bitm.TextureInfos[0].Height,
                bitm.TextureInfos[0].Depth,
                bitm.MipMapCount,
                null,
                null);

            destination.Write(ddsHeader);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Initializes a new <see cref="HaloBitmap"/> instance using the supplied object index entry.
        /// </summary>
        /// <param name="entry">The object index entry that contains the bitmap tag group data.</param>
        /// <exception cref="ArgumentNullException"><paramref name="entry"/> is null.</exception>
        /// <exception cref="ArgumentException"><paramref name="entry"/> is not a bitmap.</exception>
        public HaloBitmap(IndexEntry entry)
        {
            //Check
            if (entry == null)
            {
                throw new ArgumentNullException(nameof(entry));
            }
            else if (entry.Root != HaloTags.bitm)
            {
                throw new ArgumentException("Index entry is not bitmap.", nameof(entry));
            }

            //Setup
            this.entry = entry;
            tag        = new BitmapTag(entry);
            maps       = new Bitmap[tag.Bitmaps.Length][][];

            //Setup Property Accessors
            bitmaps = new BitmapProperties[tag.Bitmaps.Length];
            for (int i = 0; i < tag.Bitmaps.Length; i++)
            {
                bitmaps[i] = new BitmapProperties(this, i);
            }
            sequences = new SequenceProperties[tag.Sequences.Length];
            for (int i = 0; i < tag.Sequences.Length; i++)
            {
                sequences[i] = new SequenceProperties(this, i);
            }

            //Check
            if (tag == null)
            {
                return;
            }
            else if (tag.Bitmaps.Length == 0)
            {
                return;
            }

            //Loop through bitmaps
            for (int k = 0; k < tag.Bitmaps.Length; k++)
            {
                //Setup
                BitmapTagGroup.Bitmap bitmap = tag.Bitmaps[k];
                maps[k] = new Bitmap[6][];

                //Loop through LODs
                byte[] sourceData = null;
                for (int l = 0; l < 6; l++)
                {
                    //Get source data
                    if (bitmap.rawOffsets[l] != uint.MaxValue)
                    {
                        RawLocation rawLocation = (RawLocation)(bitmap.rawOffsets[l] & 0xC0000000);
                        if (rawLocation == RawLocation.Local)
                        {
                            sourceData = entry.Raws[RawSection.Bitmap][(int)bitmap.rawOffsets[l]].GetBuffer();
                        }
                        else
                        {
                            string filelocation = string.Empty;
                            int    rawOffset    = (int)(bitmap.rawOffsets[l] & (uint)RawLocation.LocalMask);
                            switch (rawLocation)
                            {
                            case RawLocation.Mainmenu:
                                filelocation = HaloSettings.MainmenuPath;
                                break;

                            case RawLocation.Shared:
                                filelocation = HaloSettings.SharedPath;
                                break;

                            case RawLocation.SinglePlayerShared:
                                filelocation = HaloSettings.SingleplayerSharedPath;
                                break;
                            }

                            //Check
                            if (File.Exists(filelocation))
                            {
                                using (FileStream fs = new FileStream(filelocation, FileMode.Open))
                                    using (BinaryReader mapReader = new BinaryReader(fs))
                                    {
                                        fs.Seek(rawOffset, SeekOrigin.Begin);
                                        sourceData = mapReader.ReadBytes(bitmap.rawLengths[l]);
                                    }
                            }
                        }
                    }

                    //Set
                    if (sourceData.Length == 0)
                    {
                        continue;
                    }

                    //Prepare
                    BitmapFlags  flags        = (BitmapFlags)bitmap.flags;
                    BitmapFormat format       = (BitmapFormat)bitmap.format;
                    PixelFormat  bitmapFormat = PixelFormat.Format32bppArgb;
                    int          sourceBits   = 32;
                    switch (format)
                    {
                    case BitmapFormat.A8:
                    case BitmapFormat.Y8:
                    case BitmapFormat.P8Bump:
                    case BitmapFormat.P8:
                    case BitmapFormat.Ay8: sourceBits = 8; break;

                    case BitmapFormat.A8y8:
                    case BitmapFormat.A1r5g5b5:
                    case BitmapFormat.A4r4g4b4:
                    case BitmapFormat.V8u8:
                    case BitmapFormat.G8b8:
                    case BitmapFormat.R5g6b5: sourceBits = 16; break;

                    case BitmapFormat.Dxt1: sourceBits = 4; break;

                    case BitmapFormat.Dxt5:
                    case BitmapFormat.Dxt3: sourceBits = 8; break;

                    case BitmapFormat.Argbfp32: sourceBits = 128; break;
                    }

                    //Handle
                    switch (format)
                    {
                    case BitmapFormat.R5g6b5: bitmapFormat = PixelFormat.Format16bppRgb565; break;

                    case BitmapFormat.A1r5g5b5: bitmapFormat = PixelFormat.Format16bppArgb1555; break;

                    case BitmapFormat.X8r8g8b8: bitmapFormat = PixelFormat.Format32bppRgb; break;

                    case BitmapFormat.P8Bump: bitmapFormat = PixelFormat.Format8bppIndexed; break;

                    case BitmapFormat.P8: bitmapFormat = PixelFormat.Format8bppIndexed; break;
                    }

                    //Prepare
                    int width = bitmap.width, height = bitmap.height;
                    if (flags.HasFlag(BitmapFlags.Linear))
                    {
                        width = (int)Math.Ceiling(width / 16f) * 16;
                    }

                    //Loop LOD
                    for (int i = 0; i < l; i++)
                    {
                        width  /= 2;
                        height /= 2;
                    }

                    //Prepare
                    int mapWidth = width, mapHeight = height, location = 0;
                    int mipmapCount = bitmap.mipmapCount;
                    maps[k][l] = new Bitmap[mipmapCount + 1];
                    Size   bitmapSize = Size.Empty;
                    byte[] mapData    = null;

                    //Loop
                    for (int i = 1; i <= mipmapCount + 1; i++)
                    {
                        //Prepare
                        int mapIndex = i - 1;
                        mapWidth = width; mapHeight = height;
                        for (int j = 1; j < i; j++)
                        {
                            mapWidth  /= 2;
                            mapHeight /= 2;
                        }

                        //Get Size
                        bitmapSize = new Size(mapWidth, mapHeight);

                        //Check
                        if (bitmapSize.Width == 0 || bitmapSize.Height == 0)
                        {
                            continue;
                        }

                        //Create Map
                        int mapStride = mapWidth * sourceBits / 8;
                        int mapSize   = mapStride * mapHeight;

                        //Ehh?
                        switch (format)
                        {
                        case BitmapFormat.Dxt1: mapSize = Math.Max(mapSize, 8); break;

                        case BitmapFormat.Dxt3:
                        case BitmapFormat.Dxt5: mapSize = Math.Max(mapSize, 16); break;

                        case BitmapFormat.P8:
                        case BitmapFormat.P8Bump: mapSize = Math.Max(mapSize, 16); break;

                        default: mapSize = Math.Max(mapSize, 1); break;
                        }

                        mapData = new byte[mapSize];
                        if (location + mapSize > sourceData.Length)
                        {
                            continue;
                        }
                        Array.Copy(sourceData, location, mapData, 0, mapSize);

                        //Deswizzle?
                        if ((flags & BitmapFlags.Swizzled) == BitmapFlags.Swizzled)
                        {
                            mapData = Swizzler.Swizzle(mapData, mapWidth, mapHeight, bitmap.depth, sourceBits, true);
                        }
                        if (mapData == null)
                        {
                            mapData = new byte[mapSize];
                        }

                        using (Bitmap map = new Bitmap(mapWidth, mapHeight, bitmapFormat))
                        {
                            unsafe
                            {
                                //Lock Bits
                                BitmapData data = map.LockBits(new Rectangle(0, 0, mapWidth, mapHeight), ImageLockMode.ReadWrite, bitmapFormat);

                                //Prepare Buffer
                                byte[] bitmapData = new byte[data.Stride * data.Height];
                                int    dataLength = Math.Min(bitmapData.Length, mapSize);

                                //Handle Format...
                                switch (format)
                                {
                                case BitmapFormat.A8:
                                    for (int x = 0; x < mapWidth * mapHeight; x++)
                                    {
                                        bitmapData[x * 4 + 0] = 255;
                                        bitmapData[x * 4 + 1] = 255;
                                        bitmapData[x * 4 + 2] = 255;
                                        bitmapData[x * 4 + 3] = mapData[x];
                                    }
                                    break;

                                case BitmapFormat.Y8:
                                    for (int x = 0; x < mapWidth * mapHeight; x++)
                                    {
                                        bitmapData[x * 4 + 0] = mapData[x];
                                        bitmapData[x * 4 + 1] = mapData[x];
                                        bitmapData[x * 4 + 2] = mapData[x];
                                        bitmapData[x * 4 + 3] = 255;
                                    }
                                    break;

                                case BitmapFormat.Ay8:
                                    for (int x = 0; x < mapWidth * mapHeight; x++)
                                    {
                                        bitmapData[x * 4 + 0] = mapData[x];
                                        bitmapData[x * 4 + 1] = mapData[x];
                                        bitmapData[x * 4 + 2] = mapData[x];
                                        bitmapData[x * 4 + 3] = mapData[x];
                                    }
                                    break;

                                case BitmapFormat.A8y8:
                                    for (int x = 0; x < mapWidth * mapHeight; x++)
                                    {
                                        bitmapData[x * 4 + 0] = mapData[x * 2];
                                        bitmapData[x * 4 + 1] = mapData[x * 2];
                                        bitmapData[x * 4 + 2] = mapData[x * 2];
                                        bitmapData[x * 4 + 3] = mapData[x * 2 + 1];
                                    }
                                    break;

                                case BitmapFormat.A4r4g4b4:
                                    for (int x = 0; x < mapWidth * mapHeight; x++)
                                    {
                                        bitmapData[x * 4 + 0] = (byte)(mapData[x * 2 + 0] & 0xF0);
                                        bitmapData[x * 4 + 1] = (byte)(mapData[x * 2 + 0] & 0x0F);
                                        bitmapData[x * 4 + 2] = (byte)(mapData[x * 2 + 1] & 0xF0);
                                        bitmapData[x * 4 + 3] = (byte)(mapData[x * 2 + 1] & 0x0F);
                                    }
                                    break;

                                case BitmapFormat.P8Bump:
                                case BitmapFormat.P8: Array.Copy(mapData, 0, bitmapData, 0, dataLength); break;

                                case BitmapFormat.R5g6b5: Array.Copy(mapData, 0, bitmapData, 0, dataLength); break;

                                case BitmapFormat.A1r5g5b5: Array.Copy(mapData, 0, bitmapData, 0, dataLength); break;

                                case BitmapFormat.X8r8g8b8: Array.Copy(mapData, 0, bitmapData, 0, dataLength); break;

                                case BitmapFormat.A8r8g8b8: Array.Copy(mapData, 0, bitmapData, 0, dataLength); break;

                                case BitmapFormat.Dxt1:
                                    if (mapWidth >= 4 && mapHeight >= 4)
                                    {
                                        S3TC.DecompressDxt1(ref bitmapData, mapData, bitmapSize);
                                    }
                                    break;

                                case BitmapFormat.Dxt3:
                                    if (mapWidth >= 4 && mapHeight >= 4)
                                    {
                                        S3TC.DecompressDxt3(ref bitmapData, mapData, bitmapSize);
                                    }
                                    break;

                                case BitmapFormat.Dxt5:
                                    if (mapWidth >= 4 && mapHeight >= 4)
                                    {
                                        S3TC.DecompressDxt5(ref bitmapData, mapData, bitmapSize);
                                    }
                                    break;

                                case BitmapFormat.Argbfp32:
                                    for (int x = 0; x < mapWidth * mapHeight; x++)
                                    {
                                        bitmapData[x * 4 + 0] = (byte)Math.Min((BitConverter.ToSingle(mapData, x * 16 + 8) * 255f), 255f);
                                        bitmapData[x * 4 + 1] = (byte)Math.Min((BitConverter.ToSingle(mapData, x * 16 + 4) * 255f), 255f);
                                        bitmapData[x * 4 + 2] = (byte)Math.Min((BitConverter.ToSingle(mapData, x * 16) * 255f), 255f);
                                        bitmapData[x * 4 + 3] = (byte)Math.Min((BitConverter.ToSingle(mapData, x * 16 + 12) * 255f), 255f);
                                    }
                                    break;

                                case BitmapFormat.Rgbfp32: break;

                                case BitmapFormat.Rgbfp16: break;

                                case BitmapFormat.V8u8:
                                    for (int x = 0; x < mapWidth * mapHeight; x++)
                                    {
                                        bitmapData[x * 4 + 0] = 255;
                                        bitmapData[x * 4 + 1] = (byte)(127 + (sbyte)mapData[x * 2 + 1]);
                                        bitmapData[x * 4 + 2] = (byte)(127 + (sbyte)mapData[x * 2]);
                                        bitmapData[x * 4 + 3] = 255;
                                    }
                                    break;

                                case BitmapFormat.G8b8: break;
                                }

                                //Copy
                                Marshal.Copy(bitmapData, 0, data.Scan0, bitmapData.Length);
                                map.UnlockBits(data);

                                //Setup Palettes
                                if (format == BitmapFormat.P8Bump)
                                {
                                    map.SetNormalMapPalette();
                                }
                                else if (format == BitmapFormat.P8)
                                {
                                    map.SetGrayscalePalette();
                                }

                                //Set
                                location += mapSize;
                            }

                            //Draw into cropped image
                            maps[k][l][mapIndex] = new Bitmap(bitmap.width, bitmap.height, bitmapFormat);
                            using (Graphics g = Graphics.FromImage(maps[k][l][mapIndex])) g.DrawImage(map, Point.Empty);
                        }
                    }
                }
            }
        }
Ejemplo n.º 4
0
        private static TagPreviewViewModel GetBitmPreview(BitmapTag bitm)
        {
            var preview = new TagPreviewViewModel();

            preview.AddItem("bitmap", bitm, GetBitmapPreview);

            return(preview);

            object GetBitmapPreview(BitmapTag bitm)
            {
                // HACK: hard coding texture 0, needs texture binder rewrite to support here
                if (bitm.TextureInfos[0].Width == 0 || bitm.TextureInfos[0].Height == 0)
                {
                    return(null);
                }

                var textureBinder = new OpenGLTextureBinder();

                var settings = new GameWindowSettings();

                var nsettings = new NativeWindowSettings()
                {
                    API = ContextAPI.OpenGL,
                    AutoLoadBindings = true,
                    Size             = new OpenTK.Mathematics.Vector2i(bitm.TextureInfos[0].Width, bitm.TextureInfos[0].Height),
                    Title            = "OpenH2",
                    Flags            = ContextFlags.Debug | ContextFlags.Offscreen,
                    APIVersion       = new Version(4, 0)
                };

                var window = new GameWindow(settings, nsettings);

                window.IsVisible = false;
                window.MakeCurrent();

                GL.Enable(EnableCap.DebugOutput);
                GL.DebugMessageCallback(callback, (IntPtr.Zero));

                GL.Enable(EnableCap.DepthTest);
                GL.Enable(EnableCap.CullFace);
                GL.Enable(EnableCap.Blend);
                GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);

                var meshId           = UploadQuadMesh();
                var matriciesUniform = new GlobalUniform()
                {
                    ProjectionMatrix = Matrix4x4.CreateOrthographic(2f, 2f, 0, 10),
                    ViewMatrix       = Matrix4x4.Identity,
                    ViewPosition     = Vector3.Zero
                };

                var shader = ShaderCompiler.CreateShader(Shader.TextureViewer);

                var handle = textureBinder.GetOrBind(bitm, out var _);

                GL.ActiveTexture(TextureUnit.Texture0);
                GL.BindTexture(TextureTarget.Texture2D, handle);

                GL.ClearColor(0f, 0f, 0f, 1f);
                GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

                GL.UseProgram(shader);

                GL.GenBuffers(1, out uint MatriciesUniformHandle);

                GL.BindBuffer(BufferTarget.UniformBuffer, MatriciesUniformHandle);

                GL.BufferData(BufferTarget.UniformBuffer, GlobalUniform.Size, ref matriciesUniform, BufferUsageHint.DynamicDraw);

                GL.BindBufferBase(BufferRangeTarget.UniformBuffer, 0, MatriciesUniformHandle);
                GL.BindBuffer(BufferTarget.UniformBuffer, 0);

                GL.BindVertexArray(meshId);

                GL.DrawElements(PrimitiveType.Triangles, 6, DrawElementsType.UnsignedInt, 0);

                GL.Flush();

                var bmp = new WriteableBitmap(new PixelSize(bitm.TextureInfos[0].Width, bitm.TextureInfos[0].Height), new Avalonia.Vector(72, 72), Avalonia.Platform.PixelFormat.Rgba8888);

                using (var buf = bmp.Lock())
                {
                    GL.ReadPixels(0, 0, bitm.TextureInfos[0].Width, bitm.TextureInfos[0].Height, PixelFormat.Rgba, PixelType.UnsignedByte, buf.Address);
                }

                window.Close();
                window.Dispose();

                return(bmp);
            }
        }
Ejemplo n.º 5
0
        public override Bitmap DecodeStream(Stream s, ResizeSettings settings, string optionalPath)
        {
            if (string.IsNullOrEmpty(optionalPath))
            {
                if (s.CanSeek)
                {
                    //Check the header instead if no filename is present.
                    byte[] header = new byte[4];
                    s.Read(header, 0, 4);
                    bool isPdf = (header[0] == '%' && header[1] == 'P' && header[2] == 'D' && header[3] == 'F');
                    s.Seek(-4, SeekOrigin.Current); //Restore position.

                    if (!isPdf)
                    {
                        return(null);
                    }
                }
                else
                {
                    return(null); //It's not seekable, we can't check the header.
                }
            }
            else if (!_supportedExtensions.Contains(Path.GetExtension(optionalPath), StringComparer.OrdinalIgnoreCase))
            {
                // Not a supported format
                return(null);
            }

            // Do not allow decoding if Ghostscript there are issues with performing this decode
            IIssue[] issues = GetIssues().ToArray();
            if (issues.Length > 0)
            {
                string message = string.Join(Environment.NewLine, issues.Select(x => x.Summary).ToArray());
                throw new InvalidOperationException(message);
            }

            // Must write input stream to a temporary file for Ghostscript to process.
            FileInfo tempInputPathInfo = new FileInfo(Path.GetTempFileName());

            try
            {
                using (FileStream tempInputStream = tempInputPathInfo.Create())
                {
                    StreamExtensions.CopyToStream(s, tempInputStream);
                }

                // Get information about the PDF such as page count and media boxes
                // Although this creates a second trip to Ghostscript engine, it's not possible to generate a rendered image in exact
                // dimensions requested. Skipping this step will cause a rendered image, of some size, to be resized further.
                PdfInfo pdfInfo = GetPdfInfo(tempInputPathInfo.FullName);

                // Extract the requested page number from resize settings, or default to first page
                int pageNumber = settings.GetValueOrDefault("page", 1);

                // Try to get the page number from PDF info. If not available, abort. This is caused by
                // requesting a page that does not exist.
                PageInfo pageInfo = pdfInfo.Pages.SingleOrDefault(x => x.Number == pageNumber);
                if (pageInfo == null)
                {
                    return(null);
                }

                // We only support media box (as opposed to clip, bleed, art, etc.) If this is not available, abort.
                if (pageInfo.MediaBox == null)
                {
                    return(null);
                }

                // Get the output size of the generated bitmap by applying the resize settings and media box.
                Size outputSize = (pageInfo.Rotate == -90 || pageInfo.Rotate == 90) ?
                                  GetOutputSize(settings, pageInfo.MediaBox.Height, pageInfo.MediaBox.Width)
                    : GetOutputSize(settings, pageInfo.MediaBox.Width, pageInfo.MediaBox.Height);



                // Create default Ghostscript settings and apply the resize settings.
                GhostscriptSettings ghostscriptSettings = new GhostscriptSettings
                {
                    GhostscriptArgument.NoPause,
                    GhostscriptArgument.Quiet,
                    GhostscriptArgument.Safer,
                    GhostscriptArgument.Batch,
                    { GhostscriptArgument.OutputDevice, "pngalpha" },
                    { GhostscriptArgument.MaxBitmap, 24000000 },
                    { GhostscriptArgument.RenderingThreads, 4 },
                    { GhostscriptArgument.GridFitTT, 0 },
                    { GhostscriptArgument.AlignToPixels, 0 },                                         //Subpixel rendering depends on output device... perhaps testing would help determine if 1 would be better?
                    { GhostscriptArgument.FirstPage, pageNumber },
                    { GhostscriptArgument.LastPage, pageNumber },
                    GhostscriptArgument.Printed,
                    GhostscriptArgument.PdfFitPage,
                    GhostscriptArgument.FixedMedia,
                    { GhostscriptArgument.Height, outputSize.Height },
                    { GhostscriptArgument.Width, outputSize.Width }
                };
                ApplyResizeSettings(settings, ghostscriptSettings);

                // Have Ghostscript process the input to a PNG file with transparency.
                // The PNG will be reloaded and further processed by the resizer pipeline.
                FileInfo tempOutputPathInfo = new FileInfo(Path.GetTempFileName());
                try
                {
                    // Add output file and input file. The input file must be the very last argument.
                    ghostscriptSettings.Add(GhostscriptArgument.OutputFile, tempOutputPathInfo.FullName);
                    ghostscriptSettings.Add(tempInputPathInfo.FullName);
                    _engine.Execute(ghostscriptSettings);

                    // NOTE: Do not dispose of memory stream because it is used as the backing source for the loaded bitmap.
                    MemoryStream memoryStream = new MemoryStream((int)tempOutputPathInfo.Length);
                    using (FileStream fileStream = tempOutputPathInfo.Open(FileMode.Open))
                    {
                        StreamExtensions.CopyToStream(fileStream, memoryStream);
                    }

                    // Per ImagerResizer plugin example source code:
                    // NOTE: If the Bitmap class is used for decoding, read gdi-bugs.txt and make sure you set b.Tag to new BitmapTag(optionalPath,stream);
                    BitmapTag bitmapTag = new BitmapTag("ghostscript.png", memoryStream);
                    return(new Bitmap(memoryStream)
                    {
                        Tag = bitmapTag
                    });
                }
                //catch(GhostscriptException)
                //{
                //    // Conversion failed
                //    return null; //or maybe we should show details? If it's a valid PDF?
                //}
                finally
                {
                    tempOutputPathInfo.Delete();
                }
            }
            finally
            {
                tempInputPathInfo.Delete();
            }
        }