private static byte[] CreateMapSynchronized(IPRecord record, int zoomLevel, int desiredWidth, int desiredHeight, string mapFile)
        {
            byte[] sourceMapCompressed = File.ReadAllBytes("maps/" + mapFile);
            byte[] rgb = JpegCodec.Decode(sourceMapCompressed, out int w, out int h);

            RGBImage image = new RGBImage(rgb, w, h, rgb.Length / h);

            // Mark the image at the location of the IPRecord
            TileSystem.LatLongToPixelXY(record.latitude, record.longitude, zoomLevel, out int pixelX, out int pixelY);
            Color color = Color.Red;

            image.SetPixel(pixelX, pixelY, color);
            for (int i = 1; i < 8; i++)
            {
                image.SetPixel(pixelX + i, pixelY, color);
                image.SetPixel(pixelX - i, pixelY, color);
                image.SetPixel(pixelX, pixelY + i, color);
                image.SetPixel(pixelX, pixelY - i, color);
            }

            // Crop to desired size
            image = image.SubImage(pixelX - (desiredWidth / 2), pixelY - (desiredHeight / 2), desiredWidth, desiredHeight);

            byte[] jpegData = JpegCodec.Encode(image.rgb, image.width, image.height, 90);
            return(jpegData);
        }
        public RGBImage SubImage(int startX, int startY, int w, int h)
        {
            if (w > width || h > height || (w == width && h == height))
            {
                return(this);
            }

            int      newStride = (w * 3) + (w % 4);
            RGBImage sub       = new RGBImage(new byte[newStride * h], w, h, newStride);

            int endX = startX + w;
            int endY = startY + h;

            for (int srcY = startY, subY = 0; srcY < endY; srcY++, subY++)
            {
                for (int srcX = startX, subX = 0; srcX < endX; srcX++, subX++)
                {
                    sub.SetPixel(subX, subY, GetPixel(srcX, srcY));
                }
            }
            return(sub);
        }