GithubHelp home page GithubHelp logo

ilyakurdyukov / jpeg-quantsmooth Goto Github PK

View Code? Open in Web Editor NEW
239.0 9.0 19.0 573 KB

JPEG artifacts removal based on quantization coefficients.

License: GNU Lesser General Public License v2.1

C 91.37% Shell 1.07% HTML 3.33% Makefile 3.12% Batchfile 0.11% Roff 1.00%
jpeg artifact-removal libjpeg web-assembly simd

jpeg-quantsmooth's Introduction

JPEG Quant Smooth

This program tries to recover the lost precision of DCT coefficients based on a quantization table from a JPEG image. The result is saved as a JPEG image with quantization set to 1 (like a JPEG saved at 100% quality).

You may not notice jpeg artifacts on the screen without zooming in, but you may notice them after printing. Also, when editing compressed images, artifacts can accumulate, but if you use this program before editing - the result will be better.

  • The original project page is here.

  • You can save a smoothed image with the original quantization tables, which will result in the same DCT coefficients as in the original image. (Note: chroma will be slightly different if upsampling is used at quality level 6)

  • Since this program uses quantization tables to recreate DCT coefficients, applying it to JPEG images that have been re-saved multiple times may not produce good results, as it can recover only from the last JPEG recoding, and not from the previous ones.

WebAssembly

Web version available here. Images are processed locally on your computer. Without multithreading and SIMD optimizations it runs slower than native code.

  • Click the "Load" button or drag-n-drop JPEG image into the browser window. After processing is complete, you can save the result by clicking the "Save" button. You can edit the filename field before saving. The options field is passed to the wasm code when you initiate a processing by loading a file.

Usage

jpegqs [options] input.jpg output.jpg

Options

-q, --quality n Quality setting (0-6, default is 3)
-n, --niter n Number of iterations (default is 3)
-t, --threads n Set the number of CPU threads to use
-o, --optimize Option for libjpeg to produce smaller output file
-v, --verbose n Print libjpeg debug output
-i, --info n Print quantsmooth debug output (default is 15)
Use the sum of flags: 0 - silent, 1/2/4 - various information, 8 - processing time, 16 - SIMD type.
-p, --cpu n Use to lower the SIMD type if CPU detection fails:
0 - auto, 1 - scalar, 2 - SSE2, 3 - AVX2, 4 - AVX512. (x86 build selects between modes 1-3, x86_64 from 2-4)

  • The processing time includes only the smoothing algorithm, jpeg reading and writing time is not included.
  • More iterations can make the result look like CG art, can make the photos look unnatural.

The quality setting sets a combination of flags for processing:

  1. default
  2. adds DIAGONALS flag
    smoother diagonal edges, ~1.5 times slower
  3. adds JOINT_YUV flag
    chroma channels will depend from luminance, better color consistency
  4. adds UPSAMPLE_UV flag
    non-blurring chroma upsampling, unlike fancy upsampling from libjpeg
  • levels 0-2 is the same as 4-6, but with LOW_QUALITY flag
    ~10 times faster, but the quality is lower
    LOW_QUALITY implies DIAGONALS (always set)

Examples

  • Images 3x zoomed.

Original images:

JPEG with quality increasing from 8% to 98%:

After processing:

Building on Linux

If your system have libjpeg development package installed, just type make. Tested with libjpeg-turbo8-dev package from Ubuntu-18.04.

Building for Linux distribution

Use the SIMD=select switch, so that jpegqs is compiled for different CPU vector extensions.

amd64 application: make SIMD=select MFLAGS="-m64" clean app
i386 application: make SIMD=select MFLAGS="-m32 -march=i386" clean app

Package dependencies: libc, libjpeg, openmp

Building with libjpeg sources

  1. Download and extract libjpeg sources:
    1. libjpeg, for example version 6b
      wget https://www.ijg.org/files/jpegsrc.v6b.tar.gz
      tar -xzf jpegsrc.v6b.tar.gz
    2. libjpeg-turbo, for example version 2.0.4
      wget -O libjpeg-turbo-2.0.4.tar.gz https://sourceforge.net/projects/libjpeg-turbo/files/2.0.4/libjpeg-turbo-2.0.4.tar.gz
      tar -xzf libjpeg-turbo-2.0.4.tar.gz
  • For a libjpeg (not turbo) you can build jpegqs in a simpler way:
    make JPEGSRC=jpeg-6b
    This uses static configuration from jconfig.h, which should work for common systems.
    The following items are not needed if you do so.
  1. Configure and build libjpeg:

    1. For libjpeg and libjpeg-turbo-1.x.x:
      (cd jpeg-6b && ./configure && make all)
    2. For libjpeg-turbo-2.x.x ./configure script is replaced with cmake:
      (cd libjpeg-turbo-2.0.4 && mkdir -p .libs && (cd .libs && cmake -G"Unix Makefiles" .. && make all))
  2. Tell make where to find libjpeg includes and libjpeg.a
    make JPEGLIB="-Ijpeg-6b jpeg-6b/libjpeg.a
    For a newer versions libjpeg.a is located in a .libs/ dir.

libjpeg build helper

The jpegqs makefile can download sources, extract and compile libjpeg for you. Replace %VER% with a version.

  • libjpeg: make jpeg-%VER%/libjpeg.a Tested versions: 6b, 7, 8d, 9c
  • libjpeg-turbo:make libjpeg-turbo-%VER%/libjpeg.a Tested versions: 1.0.0, 1.4.2, 1.5.3, 2.0.4

It will print you link to archive which you need to download, or you can allow the downloads by adding WGET_CMD=wget to the make command line.

Building on Windows

Get MSYS2, install needed packages with pacman and build with release.sh. If you are not familiar with building unix applications on windows, then you can download program from releases.

Use as a library

Can be easily added to other software that uses libjpeg to read JPEG images.

  1. Find the source that uses jpeg_start_decompress and jpeg_finish_decompress.
  2. Add include, either quantsmooth.h (compile jpegqs as inline) or libjpegqs.h (link to the jpegqs library).
  3. Change jpeg_ to jpegqs_ for these two functions.
  4. Calling jpegqs_start_decompress takes an additional argument with options, see example.c for how to use it.
  • Build libjpegqs.a static library with make SIMD=select lib

Alternatives and comparison

Similar projects, and how I see them after some testing.

jpeg2png:
 ✔️ good documentation and math model
 ✔️ has tuning options
 ✔️ better at deblocking low quality JPEG images
 ❓ has an overblurring (-w 0.0 switch makes the result a little sharper, but doesn't fix it)
 ➖ 10 to 20 times slower
 ➖ less permissive license (GPL-3.0)

jpeg2png can provide roughly same quality (better in not common cases), but significantly slower.

knusperli:
 ✔️ more permissive license (Apache-2.0)
 ➖ you can hardly see any improvements on the image
 ➖ no performance optimizations (but roughly same speed as for quantsmooth with optimizations)
 ➖ no any command line options
 ➖ uncommon build system

knusperli is good for nothing, in my opinion.

jpeg-quantsmooth's People

Contributors

ikem-krueger avatar ilyakurdyukov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jpeg-quantsmooth's Issues

macOS Support?

Hi there,

is there any chance you can make this build under macOS?
I was able to build it on my linux server just fine, but I would love to have this working on macOS too.

Anyway - thanks for this cool project!

JPEGQS_UPSAMPLE_UV has become broken

Reproducable on Arch Linux, observed roughly since libjpeg-turbo 2.1.90 (pre-3.0):

make SIMD=select clean example LDFLAGS="-lm $(pkg-config --libs libjpeg)"
./example test.jpg test.bmp

Sample input (YCbCr 4:2:0) and output (converted to PNG):
test
test

It is the JPEGQS_UPSAMPLE_UV flag that decides whether output becomes garbage. YCbCr 4:4:4 is fine.

Prog name?

all: quantsmooth
clean:
rm -rf quantsmooth
quantsmooth: quantsmooth.h idct.h
quantsmooth: quantsmooth.c
$(CC) $(CFLAGS) -s -o $@ $< $(LIBS)

Maybe?:

PNAME = jpegqs
...
all: $(PNAME)

clean:
	rm -rf $(PNAME)

$(PNAME): quantsmooth.h idct.h

$(PNAME): quantsmooth.c
	$(CC) $(CFLAGS) -s -o $@ $< $(LIBS)

And:

const char *progname = "quantsmooth", *fn;

To:

	const char *progname = argv[0], *fn;

Arithmetic coded JPG

@ilyakurdyukov I've used QuantSmooth via IrfanView & noticed that it isn't currently compatible with arithmetic coded jpgs. Are there plans to implement that?

Strange color issue happen on -q 5~6(--quality)

Hello Ilya Kurdyukov, Sorry to bother you.

I get some strange color issue on non-photo drawing content,
those issue will happen on -q 5~6(--quality).

In this non-photo picture case, green book middle area have some tiny red pixel,
-q 3~4 haven't happen this issue.

original-cut-png (jpeg q90 420)
original

qs-q6-png
q6

JPEG Quant Smooth : Copyright (C) 2020 Ilya Kurdyukov : 2020-05-17
Build date: Jan 11 2021
https://github.com/ilyakurdyukov/jpeg-quantsmooth/releases/tag/1.20210110

jpegqs64 -q 6 -o -t 12 test.jpg test-qs.jpg
sample.zip

libminiomp?

Hi @ilyakurdyukov .

"Мысли вслух, не более того".

Use default :

$ make
cc -Wall -O2  -march=native -Wextra -pedantic -fopenmp -DAPPNAME=jpegqs -o jpegqs quantsmooth.c -ljpeg  -Wl,--gc-sections -s -lm
$ ldd jpegqs 
        linux-vdso.so.1 (0x00007ffe5e16d000)
        libjpeg.so.62 => /usr/lib/x86_64-linux-gnu/libjpeg.so.62 (0x00007f7a394b7000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f7a39373000)
        libgomp.so.1 => /usr/lib/x86_64-linux-gnu/libgomp.so.1 (0x00007f7a39333000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7a3916e000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f7a3958c000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f7a39168000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f7a39146000)

Use https://github.com/ilyakurdyukov/libminiomp :

$ make LIBMINIOMP=libminiomp.a
cc -DOVERFLOW_CHECKS=0 -O2 -Wall -Wextra -c -o miniomp.o miniomp.c -ffunction-sections -fdata-sections
ar -rsc libminiomp.a miniomp.o
cc -Wall -O2  -march=native -Wextra -pedantic -fopenmp -DAPPNAME=jpegqs -o jpegqs quantsmooth.c -ljpeg -L./  -Wl,--gc-sections -s -lm
$ ldd jpegqs 
        linux-vdso.so.1 (0x00007fffe84cb000)
        libjpeg.so.62 => /usr/lib/x86_64-linux-gnu/libjpeg.so.62 (0x00007ff9a5392000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007ff9a524e000)
        libgomp.so.1 => /usr/lib/x86_64-linux-gnu/libgomp.so.1 (0x00007ff9a520e000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff9a5049000)
        /lib64/ld-linux-x86-64.so.2 (0x00007ff9a5467000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007ff9a5043000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007ff9a5021000)

This is wrong!

$ cc -Wall -O2  -march=native -Wextra -pedantic -fopenmp -DAPPNAME=jpegqs -o jpegqs quantsmooth.c libminiomp.a -ljpeg -L./  -Wl,--gc-sections -s -lm
$ ldd jpegqs
        linux-vdso.so.1 (0x00007ffd3b156000)
        libjpeg.so.62 => /usr/lib/x86_64-linux-gnu/libjpeg.so.62 (0x00007fdd879dc000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fdd87898000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fdd87876000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fdd876b1000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fdd87ab0000)

This is true! (added libminiomp.a)

Patch:

ifneq ($(LIBMINIOMP),)
LDFLAGS += $(LIBMINIOMP)
endif

MP3 DCT quant smooth?

Interested in MP3 DCT Quantum Smooth based on madplay (https://www.underbit.com/products/mad/) or mpg123 (https://www.mpg123.de/).

I immediately warn the obvious answer: I know about filter banks. I don’t propose to mess with “filter banks” for dequantization, but I suggest using other information.

“Volume War” in combination with “filter banks” in any MP3 without additional regulation (REPLAY_GAIN) leads to clipping. It is this fact that I propose to use for dequantizing MP3.

I’m not sure that the result of dequantization can be saved in MP3 (even 320kbps), but the utilities I have specified allow to save the result in WAV.

PS: This time expected library + tool.

Irfanview PlugIn Optimizations

@ilyakurdyukov Based on #11 & #18 (comment), I'd like to suggest for the prebuilt released IV plugin

  • exposing the available settings via the UI in a compact way
  • building against libjpeg-turbo by default for the sake of performance. Loading via the current plugin takes ~2⅛× the time (in my tests), which is why imho Irfan has it disabled by default. IV is known as a high-speed viewer for the last 24½ years, so improving that loading time any amount would make more likely to be enabled (hopefully, eventually by default) & expose your amazing work more widely.

Frames from video exported to lossless PNG

I was wondering if the program can improve frames from low resolution video. I exported the frames to PNG (lossless) but since they are not accepted by the program I converted to JPEG Q=100 (still not a lossless step). I ran the program with max quality, -q 6, but there's no difference between frames.

So I'm guessing the program needs an "original" JPEG file and won't work with frames exported from video even though they have JPEG like compression artifacts.

libjpeg8-dev?

make SIMD=none all
cc -Wall -O2  -DNO_SIMD -c -o libjpegqs.o libjpegqs.c
In file included from libjpegqs.c:28:0:
/usr/include/jpeglib.h:1150:55: fatal error: jpegint.h: Нет такого файла или каталога
compilation terminated.
make: *** [libjpegqs.o] Ошибка 1

jpegint.h : libjpeg62-dev - YES, libjpeg8-dev - NO.

libjpeg8-dev : /usr/include/jpeglib.h (end file):

#ifdef JPEG_INTERNALS
#include "jpegint.h"		/* fetch private declarations */
#include "jerror.h"		/* fetch error codes too */
#endif

New issue about FPB

sample file

id0_FPE_jpegqs+0x41c889.zip

command to reproduce

./jpegqs -o [sample file] /dev/null

crash detail

AddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizer:DEADLYSIGNAL
:DEADLYSIGNAL
:DEADLYSIGNAL
:DEADLYSIGNAL
=================================================================
AddressSanitizer:DEADLYSIGNAL
==28436==ERROR: AddressSanitizer: FPE on unknown address 0x0000004f5d6c (pc 0x0000004f5d6c bp 0x7ffc2659eef0 sp 0x7ffc2659e2c0 T0)
AddressSanitizer:DEADLYSIGNAL
    #0 0x4f5d6c  (/home/bupt/Desktop/jpeg-quantsmooth/jpegqs+0x4f5d6c)
    #1 0x7fbb4a1b3452 in __kmp_invoke_microtask (/usr/lib/x86_64-linux-gnu/libomp.so.5+0x7c452)
    #2 0x7fbb4a16d1b6  (/usr/lib/x86_64-linux-gnu/libomp.so.5+0x361b6)
    #3 0x7fbb4a16e2b5 in __kmp_fork_call (/usr/lib/x86_64-linux-gnu/libomp.so.5+0x372b5)
    #4 0x7fbb4a1617be in __kmpc_fork_call (/usr/lib/x86_64-linux-gnu/libomp.so.5+0x2a7be)
    #5 0x4ea485  (/home/bupt/Desktop/jpeg-quantsmooth/jpegqs+0x4ea485)
    #6 0x7fbb49b4fc86 in __libc_start_main /build/glibc-CVJwZb/glibc-2.27/csu/../csu/libc-start.c:310
    #7 0x41c889 in _init (/home/bupt/Desktop/jpeg-quantsmooth/jpegqs+0x41c889)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: FPE (/home/bupt/Desktop/jpeg-quantsmooth/jpegqs+0x4f5d6c) 
==28436==ABORTING

SSE flags?

#if defined(__SSE4_1__)
#define USE_SSE2
#define USE_SSE4
#include <smmintrin.h>
#elif defined(__SSE2__)
#define USE_SSE2
#include <emmintrin.h>
#define _mm_cvtepu8_epi16(a) _mm_unpacklo_epi8(a, _mm_setzero_si128())
// _mm_cmplt_epi16(a, _mm_setzero_si128()) or _mm_srai_epi16(a, 15)
#define _mm_cvtepi16_epi32(a) _mm_unpacklo_epi16(a, _mm_srai_epi16(a, 15))
#define _mm_abs_epi16(a) ({ \
__m128i __tmp = _mm_srai_epi16(a, 15); \
_mm_xor_si128(_mm_add_epi16(a, __tmp), __tmp); })
#endif

Maybe?:

#if defined(__SSE_USE__)
#if defined(__SSE4_1__)
#define USE_SSE2
#define USE_SSE4
#include <smmintrin.h>
#elif defined(__SSE2__)
#define USE_SSE2
#include <emmintrin.h>

#define _mm_cvtepu8_epi16(a) _mm_unpacklo_epi8(a, _mm_setzero_si128())
// _mm_cmplt_epi16(a, _mm_setzero_si128()) or _mm_srai_epi16(a, 15)
#define _mm_cvtepi16_epi32(a) _mm_unpacklo_epi16(a, _mm_srai_epi16(a, 15))
#define _mm_abs_epi16(a) ({ \
	__m128i __tmp = _mm_srai_epi16(a, 15); \
	_mm_xor_si128(_mm_add_epi16(a, __tmp), __tmp); })
#endif
#endif

Pass __SSE_USE__ from the Makefile:

CFLAGS ?= -Wall -D__SSE_USE__ -O2 -march=native -fopenmp

And add to docs alternative:

make CFLAGS="-Wall -O2"

PS: Debian Wheezy. I feel better without SSE.

Current Windows builds don't seem to output any images (wrong CPU features detection)

Just stumbled across this today, and it looks like a really neat program. However, I can't get the current Windows builds to produce any output file. The latest working version seems to be 2020-03-06 afaict. I'm on Windows 10 64bit, version 10.0.19041.264, if that matters. Here's the full console out put if that helps

jpegqs64.exe --verbose 1 -q 4 0008.jpg 0008_o.jpg


Compiled with libjpeg version 62
Version string: 6b  27-Mar-1998
Copyright (C) 1998, Thomas G. Lane

component[0] : table 0, samp 1x1
component[1] : table 1, samp 1x1
component[2] : table 1, samp 1x1
quant[0]:
0003 0003 0003 0004 0005 0007 000b 0011
0003 0003 0004 0005 0007 0008 000b 000f
0003 0004 0005 0006 0009 000c 0012 001b
0004 0005 0006 0008 000b 000f 0015 001f
0005 0007 0009 000b 000e 0013 001a 0026
0007 0008 000c 000f 0013 0019 0022 0030
000b 000b 0012 0015 001a 0022 002d 003e
0011 000f 001b 001f 0026 0030 003e 0054
quant[1]:
0003 0003 0003 0004 0005 0007 000b 0011
0003 0003 0004 0005 0007 0008 000b 000f
0003 0004 0005 0006 0009 000c 0012 001b
0004 0005 0006 0008 000b 000f 0015 001f
0005 0007 0009 000b 000e 0013 001a 0026
0007 0008 000c 000f 0013 0019 0022 0030
000b 000b 0012 0015 001a 0022 002d 003e
0011 000f 001b 001f 0026 0030 003e 0054

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.