---
title: Image
source: https://vjmap.com/en/guide/image.html
---

# Image

## Introduction

When loading large images on the frontend, the following measures can be taken to speed up loading:

1. **Image compression**: Compressing images can significantly reduce file size and shorten load time. When compressing, maintain image quality to avoid affecting display.
2. **Image tiling**: Splitting large images into smaller tiles avoids loading the entire image at once and speeds up loading. This requires frontend tile stitching and seamless assembly.
3. **CDN acceleration**: Using a CDN (Content Delivery Network) caches images on nodes closer to users, speeding up delivery. Static images can be stored on a CDN for faster access.
4. **Lazy loading**: Lazy loading defers image loading until the user scrolls to them, avoiding loading many images at once and slowing the page.
5. **WebP format**: WebP can reduce image size to less than half of JPEG and PNG, speeding up loading.
6. **HTTP/2**: HTTP/2 allows parallel loading of multiple images, improving page load speed.
7. **Preloading**: Preloading fetches resources needed for the next step after the page loads. For images, you can preload the next image to display for faster browsing.

For images of hundreds of MB or several GB, instant loading is impractical even with optimization. The second approach above—**image tiling**—is the best solution.

`VJMap` supports common image formats such as `tif;png;jpeg;tiff;hdr;avif;webp;jpe;jpc;jpg;heif;bmp;dib;heic;jfif;gif;zip;hif;pdf;`. After uploading an image, the backend processes and tiles it, enabling instant display on the frontend.

## Image Tiling Overview

Image tiling is the process of splitting a large image into smaller tiles for storage and processing. It is commonly used in web maps, tile maps, and image mosaics.

The tiling process typically includes:

1. **Define tile size**: Set the size of each tile, usually square or rectangular.
2. **Calculate tile count**: Based on tile size, compute how many tiles are needed. Formula: tile count = image width / tile width × image height / tile height.
3. **Slice the image**: Split the image into the calculated number of tiles using an image library or custom code.
4. **Store tiles**: Save tiles to disk in formats such as JPEG or PNG.
5. **Load tiles**: Load the required tiles where needed and assemble them into the full image.

Tiling reduces the complexity of handling large images and improves load speed, so users can view details faster. It is widely used where large images must be processed and displayed efficiently.

## Image Map Extent Settings

Some image maps have an associated geographic extent. Set this extent when uploading the image or afterward.

For example, TIFF images often have a corresponding TFW file with geographic extent.

**TIFF/TFW, JPG/JPGW world file format (6 parameters)**

```
0.030000

0.0000000000

0.0000000000

-0.030000

451510.875000

3358045.000000
```

Meaning of each line:

1. X resolution scale of one pixel in the X direction.
2. Translation.
3. Rotation.
4. Negative of the Y resolution scale of one pixel in the Y direction.
5. X coordinate of pixel (1,1) (top-left).
6. Y coordinate of pixel (1,1) (top-left).

When uploading, set the map extent using the first, fifth, and sixth values from the file:

![image-20230319205612982](https://vjmap.com/blogimages/image-20230319205612982.png)

Or after upload, click **Set Map Extent** in the operation menu:

![image-20230319205732187](https://vjmap.com/blogimages/image-20230319205732187.png)

## Image Processing

To rotate, stitch, or otherwise process images before tiling, create a `cmd.txt` file with the processing commands, then package it with the images into a ZIP file for upload.

To stitch `1.jpg` and `2.jpg` into `m1.png`, use the following in `cmd.txt`:

```
join
1.jpg
2.jpg
m1.png
horizontal
```

Then package `1.jpg`, `2.jpg`, and `cmd.txt` into a ZIP file and upload.

Example source images:

![image-20230319204505566](https://vjmap.com/blogimages/image-20230319204505566.png)

To stitch these three files into one, create `cmd.txt` in the same directory with:

```
join
0.jpg
1.jpg
m1.png
horizontal

join
m1.png
2.jpg
m3.png
horizontal
```

Then package `0.jpg`, `1.jpg`, `2.jpg`, and `cmd.txt` into `image.zip` (you can choose the archive name) and upload it.

![image-20230319204822323](https://vjmap.com/blogimages/image-20230319204822323.png)

**cmd.txt format:**

```
command_name_1
command_name_1_param_1
command_name_1_param_2

command_name_2
command_name_2_param_1
command_name_2_param_2
command_name_2_param_3

command_name_3
command_name_3_param_1
```

- Separate multiple commands with blank lines.
- Separate command names and parameters with line breaks.

## Image Processing Commands

### Rotate Image

```
rot
in - Input image filename
out - Output image filename
angle - Rotation angle. Default: d90. Allowed: d0, d90, d180, d270
```

Example: rotate `1.jpg` by 90 degrees before tiling.

In `cmd.txt`:

```
rot
1.jpg
result.jpg
d90
```

`result.jpg` can be any name (letters or numbers only). Package `1.jpg` and `cmd.txt` into a ZIP file and upload.

### Crop Image

Crop by specifying top-left coordinates and crop width and height.

```
crop
in - Input image filename
out - Output image filename
int left
int top
int width
int height
```

### Resize Image

```
resize
in - Input image filename
out - Output image filename
scale - Scale factor. e.g. 2 = 2×, 0.5 = half size
```

### Flip Image

```
flip
in - Input image filename
out - Output image filename
direction - horizontal or vertical
```

### Affine Transform

```
affine
in - Input image filename
out - Output image filename
"2 0 0 1" - 2×2 transform matrix as four space-separated numbers
```

### Join Images

```
join
in - First input image filename
in - Second input image filename
out - Output image filename
direction - horizontal or vertical
```

### Image Array

Merges multiple files or files matching a wildcard into one array. Often used to stitch multiple images into one or merge channels into a multi-channel image.

```
arrayjoin
image1.jpg
image2.jpg
image3.jpg
... (more input files)
output.jpg
```

## Image Format Support (Backend Config)

Add `supportImageFormat` under the `map` section in `config.json`:

```json
{
    "map" : {
      "supportImageFormat": "jpc;tif;tiff;png;jpg;jpeg;jpe;jfif;bmp;dib;gif;pdf;hdr;webp;heic;hif;heif;avif;zip",
      "supportImageFileMinSize": 0,
      "supportImageFileMaxSize": 0
    }
}
```

- `supportImageFormat`: Supported file types. Add, remove, or modify formats as needed.
- `supportImageFileMinSize` and `supportImageFileMaxSize`: Min and max upload size in bytes. `0` means no limit.

Restart the service after changing these parameters.

---

# Implementation

## Preview

![imageslice.gif](https://vjmap.com/blogimages/imageslice.gif)

## Upload and Open Image

Upload a large image for backend tiling. Example upload code:

```js
async onChangeFile(file) {
            try {
                message.info('Uploading file...')
                this.isSelectFile = false;
                this.uploadMapResult = await svc.uploadMap(file.raw);
                if (this.uploadMapResult.error) {
                    message.error('Upload failed: ' + this.uploadMapResult.error)
                    return
                }
                this.form.mapid = this.uploadMapResult.mapid;
                this.form.uploadname = this.uploadMapResult.uploadname;
                this.maptype = this.uploadMapResult.maptype || '';
                this.dialogVisible = true;
            } catch (error) {
                console.error(error);
                message.error('Upload failed.', error)
            }
        }
```

To process images after upload, create a `cmd.txt` with the commands and package it with the images in a ZIP file.

To stitch `1.jpg` and `2.jpg` into `m1.png`, use in `cmd.txt`:

```
join
1.jpg
2.jpg
m1.png
horizontal
```

Then package `1.jpg`, `2.jpg`, and `cmd.txt` into a ZIP file and upload.

**Open image code:**

```js
async onOpenMap() {
            try {
                let mapid = this.form.mapid;
                let param = {
                    ...this.uploadMapResult,
                    // Map ID
                    mapid: this.form.mapid,
                    // fileid from upload
                    fileid: this.uploadMapResult.fileid,
                    // upload filename
                    uploadname: this.form.uploadname,
                    // Map open mode (e.g. "Open directly" -> Memory, else GeomRender)
                    mapopenway: this.form.openway === "直接打开图形" ? vjmap.MapOpenWay.Memory : vjmap.MapOpenWay.GeomRender,
                    // Secret key for password-protected map
                    secretKey: this.form.isPasswordProtection ? svc.pwdToSecretKey(this.form.password) : undefined,
                    style: vjmap.openMapDarkStyle(), // use dark style when container has dark background
                    // Image type: top-left coords and resolution
                    imageLeft: this.form.imageLeft ? +this.form.imageLeft : undefined,
                    imageTop: this.form.imageTop ? +this.form.imageTop : undefined,
                    imageResolution: this.form.imageResolution ? +this.form.imageResolution : undefined,
                }
                let isVectorStyle = this.form.openway === "存储后渲染矢量";
                await openMap(param, isVectorStyle);
            } catch (error) {
                console.error(error);
                message.error('Failed to open map.', error)
            }
        }
```

# Use Cases

## Case 1: Stitch Images and View on Frontend

Source images:

![image-20230319204505566](https://vjmap.com/blogimages/image-20230319204505566.png)

![image-20230319204822323](https://vjmap.com/blogimages/image-20230319204822323.png)

Result:

![image-20230319204924823](https://vjmap.com/blogimages/image-20230319204924823.png)

Try it: [https://vjmap.com/app/cloud/#/map/t3c93d14ff09?version=v1&mapopenway=GeomRender&vector=false](https://vjmap.com/app/cloud/#/map/t3c93d14ff09?version=v1&mapopenway=GeomRender&vector=false)

## Case 2: Tile TIFF Imagery and Overlay with CAD for Calibration

When uploading TIFF imagery, you can set the geographic extent.

**TIFF/TFW, JPG/JPGW world file format (6 parameters)**

```
0.030000
0.0000000000
0.0000000000
-0.030000
451510.875000
3358045.000000
```

Meaning of each line:

1. X resolution scale of one pixel in the X direction.
2. Translation.
3. Rotation.
4. Negative of the Y resolution scale of one pixel in the Y direction.
5. X coordinate of pixel (1,1) (top-left).
6. Y coordinate of pixel (1,1) (top-left).

Set the map extent using the first, fifth, and sixth values when uploading:

![image-20230319205612982](https://vjmap.com/blogimages/image-20230319205612982.png)

Or after upload, click **Set Map Extent** in the operation menu:

![image-20230319205732187](https://vjmap.com/blogimages/image-20230319205732187.png)

After tiling, the imagery can be overlaid and calibrated with CAD. Result:

![image-20230319205945507](https://vjmap.com/blogimages/image-20230319205945507.png)

Try it: [https://vjmap.com/demo/#/demo/map/comprehensive/04imagecadmap](https://vjmap.com/demo/#/demo/map/comprehensive/04imagecadmap)

## imageproc Source Code

main.go

```go
package main

import (
    "fmt"
    "os"
    "os/exec"
)

func main() {
    // Path to the exe to run
    cmdPath := os.Args[1]
    // Arguments to pass
    args := os.Args[2:]

    // Run command
    cmd := exec.Command(cmdPath, args...)
    output, err := cmd.CombinedOutput()
    if err != nil {
        fmt.Println("ERROR_MSG:", err.Error(), string(output))
    } else {
        // Output result
        fmt.Println(string(output))
    }
}

```
