Пример #1
0
        private void LoadTileDataSync(PositionKey key, ICachedTile tile)
        {
            var red   = RawDataPool.Capture();
            var green = RawDataPool.Capture();
            var blue  = RawDataPool.Capture();

            try
            {
                if (key == null || tile == null)
                {
                    return;
                }

                var name = key.ToString();
                var res  = _tileStore.Exists(name);
                if (res.IsFailure)
                {
                    tile.SetState(TileState.Empty);
                    return;
                }

                var version = res.ResultData?.CurrentVersion ?? 1;
                var img     = _tileStore.Read(name, "img", version);

                if (img.IsFailure || img.ResultData == null)
                {
                    tile.SetState(TileState.Empty);
                    return;
                }

                var fileData = InterleavedFile.ReadFromStream(img.ResultData);
                if (fileData != null)
                {
                    WaveletCompress.Decompress(fileData, red, green, blue, 1);
                }

                tile.EnsureDataReady();
                var packed = tile.GetTileData() ?? throw new Exception("Byte pool allocation failed");

                var end = TileImageSize * TileImageSize;
                for (int i = 0; i < end; i++)
                {
                    packed[4 * i + 0] = blue[i];
                    packed[4 * i + 1] = green[i];
                    packed[4 * i + 2] = red[i];

                    if (blue[i] >= 254 && green[i] >= 254 && red[i] >= 254)
                    {
                        packed[4 * i + 3] = 0;
                    }
                    else
                    {
                        packed[4 * i + 3] = 255;
                    }
                }

                tile.SetState(TileState.Ready);
            }
            catch (Exception ex)
            {
                Logging.WriteLogMessage("Failed to load tile data\r\n" + ex);
                tile?.MarkCorrupted();
            }
            finally {
                RawDataPool.Release(red);
                RawDataPool.Release(green);
                RawDataPool.Release(blue);
            }
        }
Пример #2
0
        /// <summary>
        /// Write an image onto a tile, with transparency.
        /// Returns true if any pixels were changed.
        /// `tileArea` is in tile space. `imageArea` is in image space.
        /// </summary>
        /// <remarks>The scaling here is only intended for small variations (between 0.6x and 1.4x). The
        /// Source image should be scaled if you are outside of this range</remarks>
        private bool AlphaMapImageToTileScaled(RawImageInterleaved_UInt8 img, ICachedTile tile, Quad imageArea, Quad tileArea)
        {
            // This needs to be improved
            var dst = tile?.GetTileData();
            var src = img?.Data;

            if (src == null || dst == null || imageArea == null || tileArea == null)
            {
                return(false);
            }
            if (img.Width < 1 || img.Height < 1)
            {
                return(false);
            }

            bool changed = false;

            // start and end limits on tile
            int x0 = (int)Math.Max(tileArea.X, 0);
            int x1 = (int)Math.Min(tileArea.X + tileArea.Width, TileImageSize);
            int y0 = (int)Math.Max(tileArea.Y, 0);
            int y1 = (int)Math.Min(tileArea.Y + tileArea.Height, TileImageSize);

            int dst_width  = x1 - x0;
            int dst_height = y1 - y0;

            if (dst_width < 1 || dst_height < 1)
            {
                return(false);
            }

            double scale_x = imageArea.Width / dst_width;
            double scale_y = imageArea.Height / dst_height;

            var imgyo = imageArea.Y;
            var imgxo = imageArea.X;

            // AA caches
            int[] src_aa = new int[(img.Width + 1) * 4];

            for (int y = y0; y < y1; y++)
            {
                var img_yi = y - y0;

                // prepare a scaled row here
                AntiAliasRow(img, img_yi, scale_y, imgyo, src, src_aa);

                // copy image row
                for (int x = x0; x < x1; x++)
                {
                    var img_xi = x - x0;

                    // Measure AA
                    var    xoff_f = Range(0.0, (img_xi * scale_x) + imgxo, img.Width);
                    var    xoff   = (int)xoff_f;
                    double x_frac = xoff_f - xoff;
                    var    imul   = (int)(255 * x_frac);
                    var    mul    = 255 - imul;

                    var src_xi = xoff * 4;

                    var src_i  = Range(0, src_xi, src_aa.Length - 4);     // offset into source raw image
                    var src_i2 = Range(0, src_xi + 4, src_aa.Length - 4); // offset into source raw image
                    var dst_i  = y * (TileImageSize * 4) + (x * 4);       // offset into tile data
                    if (dst_i < 0)
                    {
                        continue;
                    }
                    if (dst_i >= dst.Length)
                    {
                        continue;
                    }

                    // Threshold alpha
                    if (src_aa[src_i + 3] < 2 && src_aa[src_i2 + 3] < 2)
                    {
                        continue;
                    }

                    // Take source samples and do AA
                    var srcB = ((src_aa[src_i + 0] * mul) + (src_aa[src_i2 + 0] * imul)) >> 8;
                    var srcG = ((src_aa[src_i + 1] * mul) + (src_aa[src_i2 + 1] * imul)) >> 8;
                    var srcR = ((src_aa[src_i + 2] * mul) + (src_aa[src_i2 + 2] * imul)) >> 8;
                    var srcA = ((src_aa[src_i + 3] * mul) + (src_aa[src_i2 + 3] * imul)) >> 8;

                    var newAlpha = srcA / 255.0f;
                    var oldAlpha = 1.0f - newAlpha;

                    // Alpha blend over existing color
                    // This for plain alpha:
                    //dst[dst_i + 0] = Clip((dst[dst_i + 0] * oldAlpha) + (src[src_i + 0] * newAlpha));
                    //dst[dst_i + 1] = Clip((dst[dst_i + 1] * oldAlpha) + (src[src_i + 1] * newAlpha));
                    //dst[dst_i + 2] = Clip((dst[dst_i + 2] * oldAlpha) + (src[src_i + 2] * newAlpha));

                    // This for pre-multiplied alpha
                    dst[dst_i + 0] = Clip((dst[dst_i + 0] * oldAlpha) + srcB);
                    dst[dst_i + 1] = Clip((dst[dst_i + 1] * oldAlpha) + srcG);
                    dst[dst_i + 2] = Clip((dst[dst_i + 2] * oldAlpha) + srcR);
                    dst[dst_i + 3] = 255; // tile alpha is always 100%

                    changed = true;
                }
            }
            return(changed);
        }