MAPF

An experimental image format written in Python.


Keywords
MAPF
License
MIT
Install
pip install MAPF==0.9.9

Documentation

Macro Advanced Picture Format


DOWNLOAD

COMPARISONS WITH JPG/WEBP/PNG

PYPI


What is MAPF?

  • MAPF is an experimental Image Format written in python to encode mostly screenshots or artificially generated graphics, it can be better than jpg and webp.

Why MAPF is better than webp/jpg compressing screenshots?

  • MAPF hasn't block compression algorithm.
    So it compress it pixel by pixel.

Which version I should download?

You can download it in different versions from here...

  • MAPF0.9.9_win64_pyinstaller.zip - Compiled by pyinstaller MAPF binary for windows VISTA, 7, 8, 8.1 and 10 - 64 bit. In exe included all possible compressions (external binaries too). Big exe size (~19MB) and not too fast executing.

  • MAPF0.9.9_win64_nuitka_upx.zip - Compiled by nuitka MAPF binary for windows VISTA, 7, 8, 8.1 and 10 - 64 bit. In zip included all possible compressions (external binaries too), but you have to extract all of items in archive into one folder. Small exe size (~5MB) and fast executing.

  • MAPF0.9.9_win32_pyinstaller.zip - Compiled by pyinstaller MAPF binary for windows VISTA, 7, 8, 8.1 and 10 - 32 bit. In exe included all possible compressions (external binaries too). Big exe size (~19MB) and not too fast executing. Works on 64bit windows too!

  • MAPF0.9.9_win32_nuitka_upx.zip - Compiled by nuitka MAPF binary for windows VISTA, 7, 8, 8.1 and 10 - 32 bit. In zip included all possible compressions (external binaries too), but you have to extract all of items in archive into one folder. Small exe size (~3MB) and fast executing. Works ONLY on 32bit windows platform!

  • MAPF-0.9.9.tar.gz - Source of MAPF, can be installed on windows with python 3. Install via pip install MAPF-0.9.9.tar.gz.

  • MAPF0.9.9_win64_compressors.zip - Only external compressors binaries (bcm.exe, nz.exe) packed into zip file for windows 64bit, unpack it into folder with MAPF executable/script. (size ~400KB)

  • MAPF0.9.9_win32_compressors.zip - Only external compressors binaries (bcm.exe, nz.exe) packed into zip file for windows 32bit, unpack it into folder with MAPF executable/script. (size ~340KB)

  • Or install it directly to python using: pip install MAPF...

How MAPF compression works?

  • MAPF in mode 0 a special color space it supports only 2 097 152 colors (not 16 777 216 like in RGB color space).

  • Then it runs internal compression...
    Internal compression convert 24-bit colors into 8 or 16 bit.

  • Some examples:

    • If RGB data is ([50,60,30] [50,60,30]), internal compression converts it into ([50,60,30] [130]), 6 bytes --> 4 bytes.
    • If RGB data is ([1,2,3] [2,3,4]), internal compression converts it into ([1,2,3] [161]), 6 bytes --> 4 bytes.
    • If RGB data is ([2,0,3] [1,1,4]), internal compression converts it into ([2,0,3] [170]), 6 bytes --> 4 bytes.
    • If RGB data is ([0,0,0] [255,0,0]), internal compression converts it into ([128] [131]), 6 bytes --> 2 bytes.
    • etc...
  • And then runs external compression like lzma...

License

The MIT License (MIT)

Copyright (C) 2018 Aleksander Błażelonis [olokelo]

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

List of image modes in MAPF

Image mode Color depth (bits) Internal compression speed
(pixels per sec)
Quality range Maximum color count Recommended for Not recommended for
Lossy RGB (0) 24 ~ 920 000 pps (0,92MP/s) 0-31 2 097 152 (128**3) Color palettes
Landscapes
Big size images
Screenshots
Lossy RGBA (1) 32 ~ 920 000 pps (0,92MP/s) 0-31 268 435 456 (128**4) Icons Big size images
Screenshots
Lossless YUV (2) 24 ~ 83 253 060 pps (83,2MP/s) 1 16 777 216 (256**3) Screenshots
Compressing raw
Icons
Lossy YUV (3) From ~9 to 24 With compression helper:
~ 14 464 785 pps (14,5MP/s)
Without compression helper:
~ 44 532 678 pps (44.5MP/s)
0-127 11 239 424 (224**3) Landscapes
Screenshots
Selfies
Color palettes
Luma/monochrome (4) 8 With compression helper:
~ 4 942 298 (4,9MP/s)
Without compression helper:
~ 24 984 686 (25MP/s)
0-31 256 Monochrome fotos Icons
Color palettes
Draft/preview (5) 24 ~ 16 874 132 (16,9MP/s) 0-31 262144 (64**3) Thumbnails from
any image
Screenshots
Icons
Lossless YUV+A (6) 32 ~ 83 253 060 pps (83,2MP/s) 1 4 294 967 296 (256**4) Icons Landscapes
Blocking YUV (7) 24 ~ 9 222 817 (9,2MP/s) [quality 127]
~ 11 599 003 (11,6MP/s) [quality 0]
0-127 11 239 424 (224**3) Screenshots Icons
Landscapes

List of compression algorithms used in MAPF

Compression Type Compressed size Compression speed Decompression speed Level range Author MAPF identifier
LZMA (0) Built-in Good Good Good 1-9 Igor Pavlov lzma, xz, lz
BZIP2 (1) Built-in Good Weak+ Good 1-9 Julian Seward bz2, bzip2
NANOZIP (2) External executable The best Weak Weak - Sami Runsas nano-zip, nanozip,
nz, nano_zip
BROTLI (3) External module Very good The worst Good 1-11 Google brotli, br
ZSTD (4) External module Good Good Very good 1-22 Yann Collet (facebook) zstd, zst
SNAPPY (5) External module Weak The best The best - Google snappy, sz
None (6) Built-in - - - - - without
BCM (7) External exeutable Very good Good+ Very good - Ilya Muravyov bcm

All benchmarks above has made using 3.2GHZ i5 processor 8GB of ram and 64 bit windows 10.

Command line usage:

  • Encode to MAPF (function save):
    • Options:
      • -i, --input: Input image path.
        In python: input_path <-- str
      • -d, --destination: Destination of output MAPF image.
        In python: output_path <-- str/None
      • -m, --image-mode: Can be int in range 0-7 or image mode identifier. (see image modes section). Default: 3 (Lossy YUV)
        In python: image_mode <-- int/str
      • -cm, --compress-mode: Can be int in range 0-7 or compress mode identifier. (see compress modes section). Default: 0 (LZMA)
        In python: compress_mode <-- int/str
      • -cp, --compress-power: Compression power for external compression algorithm. (see compress ranges in compress modes section). Default: 9
        In python: compress_power <-- int
      • -q, --quality: Auto adjusted quality for images.
        Warning, sometimes quality isn't correct. Quality is only hint to image encoder, but for example sometimes image in quality 40 can be smaller than quality 20. Default: -1
        In python: quality <-- int
      • -s, --scalar-quality: You can adjust image downsampling (and enlarging it in decoding) level. Can be in range 0-3. Default: 3
        In python: quality_scalar <-- int
      • -c, --color-quality: Color palette used in image (less = less colors used in image) can be int in range 0-7. Default: 6
        In python: quality_colors <-- int
      • -y, --yuv-quality: Subsampling quality of image in mode 3. (range 0-15)
        Warning, -y below 4 resizes also Y channel, so image is downscaling 2x.
        Default: 4
        In python: subsampling_quality <-- int
      • -e, --enlarger: Enlarger used in down/upsampling image. Can be in range 0-3
        (0: BICUBIC, 1: BILINEAR, 2: LANCZOS, 3: NEAREST). Default: 2
        In python: enlarger <-- int
      • -nh, --no-helper: Disable compression helper (disable removing one-pixel obstacles). Maybe useful option in very small images or in text compressing.
        In python: helper <-- bool
      • -hm, --helper-max: Compression helper is written in python, so when it's run it can take a lot of time. Helper max sets maximum data length (in MB), when helper can be used. Default is 8, so helper will run only when length of data < 8MB.
        In python: compress_helper_max <-- int
      • -o, --optimizer: Enable optimizer, in mode 0 or 1 enables optimizer algorithm, which helps to compress image.
        In python: optimizer_enabled <-- bool
      • -oc, --optimizer-chunk: Chunk of optimizing pixels. (less is slower) Default is 8.
        In python: optimizer_chunk <-- int
      • -om, --optimizer-maxdiff: Maximum chroma difference between pixels loaded in chunk. Default: 25
        In python: optimizer_maxdiff <-- int
      • -nd, --no-debug: Disable debug info printed to stdout.
        In python: debug <-- bool
      • -bq, --quiet: Disable ANY prints to stdout (warnings and comparsions).
        In python: quiet <-- bool

    • First way: MAPF input.{jpg,png,gif,webp,ico,jpeg,tiff,bmp} [options]
      • Encode input image into input filename merged with .mapf extension.
    • Second way: MAPF input.{jpg,png,gif,webp,ico,jpeg,tiff,bmp} output.mapf [options]
      • Encode input image into output file.
    • Third way: MAPF -i input.xxx -d output.mapf [options]
      • Encode image from -i into output file from -d.
  • Read from MAPF (function read):
    • Options:
      • -i, --input: Input MAPF path.
        In python: input_image <-- str/_io.BytesIO
      • -d, --destination: Destination of output image.
        In python: output_image <-- str/None
      • -r, --read: Switch mode to decompress.
      • -v, --view-only: Use it if you want to only view image.
        In python: showonly <-- bool
      • -nd, --no-debug: Disable debug info printed to stdout.
        In python: debug <-- bool
      • -bq, --quiet: Disable ANY prints to stdout (warnings and comparsions).
        In python: quiet <-- bool
    • First way: MAPF input.mapf [options]
      • Decode image and show it.
        You can also drag'n drop MAPF file to show it.
    • Second way: MAPF input.mapf output.{jpg,png,gif,webp,ico,jpeg,tiff,bmp} [options]
      • Decode image and save it to file provided in args.
    • Third way: MAPF -i input.mapf -d output -r [options]
      • Decode image and save it to file provided in -d.
  • Identify MAPF file (function identify):
    • MAPF input.mapf --identify
      • Displays MAPF image file details (ex. width, height, mode) without reading data.
        In python: MAPFfile <-- str
        In python: debug <-- bool
  • Display version:
    • `MAPF --version
      • Displays MAPF executable version.*
        In python: MAPF.version --> str
  • Display compressions:
    • MAPF --compressions
      • Displays MAPF available compressions.
        In python: avaiable_compressions --> dict

Some examples using MAPF from python:

Encode image to file:

from MAPF import MAPF
MAPF.save('input.jpg', 'output.mapf', compress_mode='nz', quality=4, image_mode="YUV", debug=False, quiet=True)

Decode MAPF file into PIL image:

from MAPF import MAPF
from PIL import Image
im = MAPF.read('output.mapf', showonly=False, debug=False, quiet=True)
im.show()
print(im.size, im.mode)

Output: (1920, 1200) RGB

Advanced in-memory usage (without saving to file):

from MAPF import MAPF
from PIL import Image
from io import BytesIO

data = save(input_path='input.jpg', compress_mode='nz', image_mode='YUV', quality=4, return_data=True, debug=False, quiet=True)
bio = BytesIO()
bio.write(data)
im = read(bio, showonly=False, debug=False)
im.show()

Identify MAPF Image from python:

from MAPF import MAPF
im = MAPF.identify('input.mapf', debug=False)
print(im['width'], im['height'], im['image_mode'], im['compress_mode'])

Output: 1920 1200 YCBCR nano-zip

MAPF file limitations...

MAPF image resolution is limited by maximum size of integers packed in header...

  • In RGB mode: maximum 1 431 655 765 pixels (65535x21845 pixels) [1.43 GigaPixel]
  • In RGBA mode: maximum 1 073 741 824 pixels (65535x16384 pixels) [1.07 GigaPixel]
  • In Lossless YUV mode: maximum 1 431 655 765 pixels (65535x21845 pixels) [1.43 GigaPixel]
  • In YUV mode: maximum 4 294 836 225 pixels (65535x65535 pixels) [4.30 GigaPixel]
  • In MONOCHROME mode: maximum 4 294 836 225 pixels (65535x65535 pixels) [4.30 GigaPixel]
  • In PREVIEW mode: maximum 1 431 655 765 pixels (65535x21845 pixels) [1.43 GigaPixel]
  • In Lossless YUVA mode: maximum 1 073 741 824 pixels (65535x16384 pixels) [1.07 GigaPixel]
  • In Block YUV mode: maximum 1 431 655 765 pixels (65535x21845 pixels) [1.43 GigaPixel]

JPEG VS MAPF (Downscaled 2x)

Open image in new tab to view full size

  • Lossy JPEG example (51.2KB). Converted by PILLOW 5.1.0: Image.open('ben1.png').convert('RGB').save('ben1.jpg', quality=5)

pict


  • Lossy MAPF example (50.3KB). MAPF ben1.png ben1.mapf -cm nz -y 13 -c 4
    And the decoded to png using: MAPF ben1.mapf ben1_mapf.png

pict



WEBP VS MAPF (Zoomed 2x)

  • Lossy WEBP example 29.8KB). Converted by PILLOW 5.1.0: Image.open('ben1.png').convert('RGB').save('ben1.webp', quality=5)

pict


  • Lossy MAPF example (29.7KB). MAPF ben1.png ben2.mapf -cm nz -y 10 -c 1 -nh
    And the decoded to png using: MAPF ben2.mapf ben2_mapf.png

pict


JPEG VS WEBP VS MAPF (Downscalled 8x)

All RGB colors in 4096x4096 image

  • Lossy JPEG example (266KB). Converted by PILLOW 5.1.0: Image.open('all.png').convert('RGB').save('ben3.jpg', quality=1)

pict


  • Lossy WEBP example (82.8KB). Converted by PILLOW 5.1.0: Image.open('all.png').convert('RGB').save('ben3.webp', quality=0) (then transcoded to high quality jpg, cause PNG generated from WEBP has about 10MB size).

pict


  • Lossy MAPF example (18.0KB). MAPF all.png ben3.mapf -cm nz -m RGB -s 3 -c 7
    And the decoded to png using: MAPF ben3.mapf ben3_mapf.png

pict


JPEG VS WEBP VS MAPF

Plain text in image

  • Lossy JPEG example (54.5KB). Converted by PILLOW 5.1.0: Image.open('randomtext.png').convert('RGB').save('ben4.jpg', quality=1)

pict


  • Lossy WEBP example (64.5KB). Converted by PILLOW 5.1.0: Image.open('randomtext.png').convert('RGB').save('ben4.webp', quality=0)

pict


  • Lossy MAPF example (52.6KB). MAPF randomtext.png ben4.mapf -cm nz -y 4 -c 5 -nh
    And the decoded to png using: MAPF ben4.mapf ben4_mapf.png

pict


JPEG VS WEBP VS MAPF (Downscalled 2x)

Monochrome image

  • Lossy JPEG example (16.0KB). Converted by PILLOW 5.1.0: Image.open('monochrome.jpg').convert('RGB').save('ben5.jpg', quality=1)

pict


  • Lossy WEBP example (15.7KB). Converted by PILLOW 5.1.0: Image.open('monochrome.jpg').convert('RGB').save('ben5.webp', quality=5)

pict


  • Lossy MAPF example (15.2KB). MAPF monochrome.jpg ben5.mapf -cm nz -m luma -s 2 -c 0
    And the decoded to png using: MAPF ben5.mapf ben5_mapf.png

pict


PNG VS WEBP VS MAPF

Lossless icon compression with alpha

  • Lossless PNG example (18.8KB).

pict


  • Lossless WEBP example (13.4KB). Converted by PILLOW 5.1.0: Image.open('logov.png').save('ben6.webp', lossless=1)

pict


  • Lossless MAPF example (12.9KB). MAPF logov.png ben6.mapf -cm nz -m lossless_yuva
    And the decoded to png using: MAPF ben6.mapf ben6_mapf.png

pict


WEBP VS MAPF

Lossless image compression

  • Lossless WEBP example (1.15MB). Converted by PILLOW 5.1.0: Image.open('jpgtest.jpg').convert('RGB').save('ben7.webp', lossless=1)

pict


  • Lossless MAPF example (1.0MB). MAPF jpgtest.jpg ben7.mapf -cm nz -m lossless_yuv
    And the decoded to png using: MAPF ben6.mapf ben7_mapf.png

pict


MAPF PREVIEW MODE

  • MAPF can also create thumbnails from images. MAPF thumb.jpeg thumb.mapf -m preview -s 1 -c 3 -cm nz
  • MAPF thumbnail example (only 445 bytes of data)

pict


  • Made from 34.5 kilobytes JPEG image, shown below...

pict


MAPF DOESN'T SUPPORT ANIMATIONS (YET) BUT I'LL TRY TO ADD IT IN NEXT VERSIONS ;)