示例#1
0
 /// <summary>
 /// Add a texture to the cache, this will return a TextureCacheHandle that you MUST dispose
 /// when you aren't using it anymore.
 /// </summary>
 /// <param name="textureName"></param>
 /// <param name="image"></param>
 private TextureCacheHandle Add(string textureName, PagedImage image)
 {
     lock (syncObject)
     {
         TextureCacheHandle handle;
         UInt64             imageSize = image.Size;
         if (imageSize < maxCacheSize) //Image itself can fit
         {
             while (currentCacheSize + imageSize > maxCacheSize && lastAccessedOrder.Last != null)
             {
                 //Drop oldest images until there is enough space
                 String last = lastAccessedOrder.Last.Value;
                 lastAccessedOrder.RemoveLast();
                 var destroyImage = loadedImages[last];
                 loadedImages.Remove(last);
                 currentCacheSize -= destroyImage.Size;
                 destroyImage.destroyIfPossible();
             }
             currentCacheSize += image.Size;
             handle            = new PagedImageCacheHandle(image, false);
             loadedImages.Add(textureName, handle);
             lastAccessedOrder.AddFirst(textureName);
         }
         else
         {
             handle = new PagedImageCacheHandle(image, true);
         }
         handle.checkout();
         return(handle);
     }
 }
        //private unsafe byte getColor(int x, int y, FreeImageBitmap src, Channel channel)
        //{
        //    int bpp = 4;
        //    if (src.PixelFormat == FreeImageAPI.PixelFormat.Format24bppRgb)
        //    {
        //        bpp = 3;
        //    }

        //    byte* pixel = (byte*)src.Bits.ToPointer();
        //    pixel += (src.Pitch * (src.Height - y - 1) + x) * bpp;
        //    switch (channel)
        //    {
        //        case Channel.Alpha:
        //            return pixel[3];
        //        case Channel.Red:
        //            return pixel[2];
        //        case Channel.Green:
        //            return pixel[1];
        //        case Channel.Blue:
        //            return pixel[0];
        //    }
        //    throw new NotSupportedException(); //Won't get here
        //}

        private async Task saveUncompressed(String sourceFile, String destFile, bool lossless, FREE_IMAGE_FILTER filter, ImagePageSizeStrategy pageSizeStrategy, Action <FreeImageBitmap> afterResize = null)
        {
            await Task.Run(() =>
            {
                if ((outputFormats & OutputFormats.Uncompressed) != 0)
                {
                    Log.Info("Creating paged data for {0}", sourceFile);
                    using (FreeImageBitmap source = FreeImageBitmap.FromFile(sourceFile))
                    {
                        using (var stream = File.Open(String.Format(PagedTextureNameFormat, destFile), FileMode.Create, FileAccess.ReadWrite))
                        {
                            PagedImage.fromBitmap(source, 128, 1, stream, PagedImage.ImageType.WEBP, maxSize, lossless, filter, pageSizeStrategy, afterResize);
                        }
                    }
                }
            });
        }
示例#3
0
        internal TexturePageHandle getImage(VTexPage page, IndirectionTexture indirectionTexture, OriginalTextureInfo textureUnit, int textelsPerPage, int padding, int padding2)
        {
            String textureName;

            if (texturesArePaged)
            {
                textureName = textureUnit.TextureFileName;
            }
            else
            {
                textureName = String.Format("{0}_{1}", textureUnit.TextureFileName, indirectionTexture.RealTextureSize.Width >> page.mip);
            }
            TextureCacheHandle cacheHandle;

            if (!this.TryGetValue(textureName, out cacheHandle))
            {
                String file = textureUnit.TextureFileName;
                if (texturesArePaged) //Paged Images
                {
                    //using (var perfMon = new LogPerformanceBlock(String.Format("Loaded image {0} in {{0}} ms", file), Logging.LogLevel.Info, "TextureCache"))
                    //{
                    PagedImage pagedImage = new PagedImage();
                    pagedImage.load(() => VirtualFileSystem.Instance.openStream(file, Engine.Resources.FileMode.Open, Engine.Resources.FileAccess.Read));
                    cacheHandle = this.Add(textureName, pagedImage);
                    //}
                }
                else //Normal Images
                {
                    String extension  = Path.GetExtension(file);
                    String directFile = textureUnit.TextureFileName.Substring(0, file.Length - extension.Length);
                    directFile = String.Format("{0}_{1}{2}", directFile, indirectionTexture.RealTextureSize.Width >> page.mip, extension);
                    if (VirtualFileSystem.Instance.exists(directFile))
                    {
                        var image = doLoadImage(extension, directFile);
                        cacheHandle = this.Add(textureName, image);
                    }
                    else
                    {
                        //Not using cache for full size images, this is a rare case that we are not really supporting right now
                        Image image = doLoadImage(extension, textureUnit.TextureFileName);

                        //If we aren't mip 0 resize accordingly
                        if (page.mip > image.NumMipmaps && page.mip != 0)
                        {
                            using (Image original = image)
                            {
                                image = new Image(original.Width >> page.mip, original.Height >> page.mip, original.Depth, original.Format, original.NumFaces, original.NumMipmaps);
                                using (var src = original.getPixelBox())
                                {
                                    using (var dest = image.getPixelBox())
                                    {
                                        Image.Scale(src, dest, Image.Filter.FILTER_BILINEAR);
                                    }
                                }
                            }
                        }
                        cacheHandle = this.Add(textureName, image);
                    }
                }
            }
            return(cacheHandle.createTexturePageHandle(page, indirectionTexture, padding, padding2, textelsPerPage, textureUnit.MipOffset));
        }
 public PagedImageCacheHandle(PagedImage pagedImage, bool destroyOnNoRef) : base(destroyOnNoRef)
 {
     this.pagedImage = pagedImage;
 }
示例#5
0
        public void extractPage(FreeImageBitmap image, int padding, Stream stream, PagedImage pagedImage, int pageSize, IntSize2 fullPageSize, int size, FREE_IMAGE_FORMAT outputFormat, FREE_IMAGE_SAVE_FLAGS saveFlags)
        {
            IntRect serialImageRect = new IntRect();

            MemoryStream[]    memoryStreams = new MemoryStream[size];
            FreeImageBitmap[] pages         = new FreeImageBitmap[size];
            try
            {
                for (int i = 0; i < size; ++i)
                {
                    memoryStreams[i] = new MemoryStream();
                    pages[i]         = new FreeImageBitmap(fullPageSize.Width, fullPageSize.Height, FreeImageAPI.PixelFormat.Format32bppArgb);
                }

                //Calculate pages as tiles, always repeat outer limits
                for (int y = 0; y < size; ++y)
                {
                    serialImageRect.Height = pageSize;
                    serialImageRect.Top    = y * pageSize;

                    Parallel.For(0, size, x =>
                                 //for (int x = 0; x < size; ++x)
                    {
                        IntRect imageRect = serialImageRect;

                        imageRect.Width = pageSize;
                        imageRect.Left  = x * pageSize;

                        using (var pageBox = pages[x].createPixelBox(PixelFormat.PF_A8R8G8B8))
                        {
                            pageBox.Top    += (uint)padding;
                            pageBox.Bottom -= (uint)padding;
                            pageBox.Left   += (uint)padding;
                            pageBox.Right  -= (uint)padding;

                            using (var imageBox = image.createPixelBox())
                            {
                                imageBox.Left   = (uint)imageRect.Left;
                                imageBox.Right  = (uint)imageRect.Right;
                                imageBox.Top    = (uint)imageRect.Top;
                                imageBox.Bottom = (uint)imageRect.Bottom;

                                PixelBox.BulkPixelConversion(imageBox, pageBox);
                            }

                            padFillColor(image, padding, pageSize, fullPageSize, imageRect, pageBox);
                        }
                        //int startPos = (int)stream.Position;
                        pages[x].RotateFlip(RotateFlipType.RotateNoneFlipY); //Have to flip the page over for ogre to be happy
                        pages[x].Save(memoryStreams[x], outputFormat, saveFlags);
                        //pages[x].saveToFile($"page/page{image.Width}_x{x}y_{y}.bmp", FREE_IMAGE_FORMAT.FIF_BMP);
                        memoryStreams[x].Position = 0;
                        //++pagedImage.numImages;
                        //pagedImage.pages.Add(new ImageInfo(startPos, (int)(stream.Position)));
                    });
                    //}

                    for (int x = 0; x < size; ++x)
                    {
                        int startPos = (int)stream.Position;
                        //page.RotateFlip(RotateFlipType.RotateNoneFlipY); //Have to flip the page over for ogre to be happy
                        //page.Save(stream, outputFormat, saveFlags);
                        memoryStreams[x].CopyTo(stream);
                        ++pagedImage.NumImages;
                        pagedImage.Pages.Add(new PagedImage.ImageInfo(startPos, (int)(stream.Position)));
                        memoryStreams[x].Dispose();
                        memoryStreams[x] = new MemoryStream();
                    }
                }
            }
            finally
            {
                for (int i = 0; i < size; ++i)
                {
                    memoryStreams[i].Dispose();
                    pages[i].Dispose();
                }
            }
        }
示例#6
0
        public void extractPage(FreeImageBitmap image, int padding, Stream stream, PagedImage pagedImage, int pageSize, IntSize2 fullPageSize, int size, FREE_IMAGE_FORMAT outputFormat, FREE_IMAGE_SAVE_FLAGS saveFlags)
        {
            bool    topSide, bottomSide;
            IntRect serialImageRect = new IntRect();

            MemoryStream[]    memoryStreams = new MemoryStream[size];
            FreeImageBitmap[] pages         = new FreeImageBitmap[size];
            try
            {
                for (int i = 0; i < size; ++i)
                {
                    memoryStreams[i] = new MemoryStream();
                    pages[i]         = new FreeImageBitmap(fullPageSize.Width, fullPageSize.Height, FreeImageAPI.PixelFormat.Format32bppArgb);
                }

                //Calculate pages, note that there is overlap by padding between them this is intentional
                for (int y = 0; y < size; ++y)
                {
                    serialImageRect.Height = fullPageSize.Height;
                    serialImageRect.Top    = y * pageSize - padding;
                    topSide = serialImageRect.Top < 0;
                    if (topSide)
                    {
                        serialImageRect.Top     = 0;
                        serialImageRect.Height -= padding;
                    }

                    bottomSide = serialImageRect.Bottom > image.Height;
                    if (bottomSide)
                    {
                        if (topSide)
                        {
                            //Take entire image
                            serialImageRect.Top    = 0;
                            serialImageRect.Height = image.Height;
                        }
                        else
                        {
                            //Extra row on top, bottom flush with texture bottom will add extra pixel row on bottom will add extra pixel row on bottom below
                            serialImageRect.Top     = image.Height - pageSize - padding;
                            serialImageRect.Height -= padding;
                        }
                    }

                    Parallel.For(0, size, x =>
                                 //for (int x = 0; x < size; ++x)
                    {
                        bool leftSide, rightSide;
                        IntRect imageRect = serialImageRect;

                        imageRect.Width = fullPageSize.Width;
                        imageRect.Left  = x * pageSize - padding;
                        leftSide        = imageRect.Left < 0;
                        if (leftSide)
                        {
                            imageRect.Left   = 0;
                            imageRect.Width -= padding;
                        }

                        rightSide = imageRect.Right > image.Width;
                        if (rightSide)
                        {
                            if (leftSide)
                            {
                                //Take entire image
                                imageRect.Left  = 0;
                                imageRect.Width = image.Width;
                            }
                            else
                            {
                                //Extra row on left, right flush with texture right will add extra pixel row on right below
                                imageRect.Left   = image.Width - pageSize - padding;
                                imageRect.Width -= padding;
                            }
                        }

                        using (var pageBox = pages[x].createPixelBox(PixelFormat.PF_A8R8G8B8))
                        {
                            if (topSide)
                            {
                                pageBox.Top += (uint)padding;
                            }

                            if (bottomSide)
                            {
                                pageBox.Bottom -= (uint)padding;
                            }

                            if (leftSide)
                            {
                                pageBox.Left += (uint)padding;
                            }

                            if (rightSide)
                            {
                                pageBox.Right -= (uint)padding;
                            }

                            using (var imageBox = image.createPixelBox())
                            {
                                imageBox.Left   = (uint)imageRect.Left;
                                imageBox.Right  = (uint)imageRect.Right;
                                imageBox.Top    = (uint)imageRect.Top;
                                imageBox.Bottom = (uint)imageRect.Bottom;

                                PixelBox.BulkPixelConversion(imageBox, pageBox);
                            }

                            if (topSide)
                            {
                                using (PixelBox altSrcBox = image.createPixelBox())
                                {
                                    pageBox.Top    = 0;
                                    pageBox.Bottom = (uint)padding;
                                    pageBox.Left   = (uint)padding;
                                    pageBox.Right  = (uint)(fullPageSize.Width - padding);

                                    altSrcBox.Top    = (uint)imageRect.Top;
                                    altSrcBox.Bottom = (uint)(imageRect.Top + padding);
                                    altSrcBox.Left   = (uint)imageRect.Left;
                                    altSrcBox.Right  = (uint)(imageRect.Left + pageSize);

                                    PixelBox.BulkPixelConversion(altSrcBox, pageBox);
                                }
                            }

                            if (bottomSide)
                            {
                                using (PixelBox altSrcBox = image.createPixelBox())
                                {
                                    pageBox.Top    = (uint)(fullPageSize.Height - padding);
                                    pageBox.Bottom = (uint)fullPageSize.Height;
                                    pageBox.Left   = (uint)padding;
                                    pageBox.Right  = (uint)(fullPageSize.Width - padding);

                                    altSrcBox.Top    = (uint)(imageRect.Bottom - padding);
                                    altSrcBox.Bottom = (uint)imageRect.Bottom;
                                    altSrcBox.Left   = (uint)imageRect.Left;
                                    altSrcBox.Right  = (uint)(imageRect.Left + pageSize);

                                    PixelBox.BulkPixelConversion(altSrcBox, pageBox);
                                }
                            }

                            if (leftSide)
                            {
                                using (PixelBox altSrcBox = image.createPixelBox())
                                {
                                    pageBox.Top    = (uint)padding;
                                    pageBox.Bottom = (uint)(fullPageSize.Height - padding);
                                    pageBox.Left   = 0;
                                    pageBox.Right  = (uint)padding;

                                    altSrcBox.Top    = (uint)imageRect.Top;
                                    altSrcBox.Bottom = (uint)(imageRect.Top + pageSize);
                                    altSrcBox.Left   = (uint)imageRect.Left;
                                    altSrcBox.Right  = (uint)(imageRect.Left + padding);

                                    PixelBox.BulkPixelConversion(altSrcBox, pageBox);
                                }
                            }

                            if (rightSide)
                            {
                                using (PixelBox altSrcBox = image.createPixelBox())
                                {
                                    pageBox.Top    = (uint)padding;
                                    pageBox.Bottom = (uint)(fullPageSize.Height - padding);
                                    pageBox.Left   = (uint)(fullPageSize.Width - padding);
                                    pageBox.Right  = (uint)fullPageSize.Width;

                                    altSrcBox.Top    = (uint)imageRect.Top;
                                    altSrcBox.Bottom = (uint)(imageRect.Top + pageSize);
                                    altSrcBox.Left   = (uint)(imageRect.Right - padding);
                                    altSrcBox.Right  = (uint)imageRect.Right;

                                    PixelBox.BulkPixelConversion(altSrcBox, pageBox);
                                }
                            }
                        }
                        //int startPos = (int)stream.Position;
                        pages[x].RotateFlip(RotateFlipType.RotateNoneFlipY); //Have to flip the page over for ogre to be happy
                        pages[x].Save(memoryStreams[x], outputFormat, saveFlags);
                        memoryStreams[x].Position = 0;
                        //++pagedImage.numImages;
                        //pagedImage.pages.Add(new ImageInfo(startPos, (int)(stream.Position)));
                    });
                    //}

                    for (int x = 0; x < size; ++x)
                    {
                        int startPos = (int)stream.Position;
                        //page.RotateFlip(RotateFlipType.RotateNoneFlipY); //Have to flip the page over for ogre to be happy
                        //page.Save(stream, outputFormat, saveFlags);
                        memoryStreams[x].CopyTo(stream);
                        ++pagedImage.NumImages;
                        pagedImage.Pages.Add(new PagedImage.ImageInfo(startPos, (int)(stream.Position)));
                        memoryStreams[x].Dispose();
                        memoryStreams[x] = new MemoryStream();
                    }
                }
            }
            finally
            {
                for (int i = 0; i < size; ++i)
                {
                    memoryStreams[i].Dispose();
                    pages[i].Dispose();
                }
            }
        }