Git Product home page Git Product logo

sjpeg's Introduction

                     ____ __   __ __  ____ ____  ____
                    /  __\__) /  \  \/  _ \   / /  _ \
                   _\_   \  (/      /   __/  /_/   __/
                   \_____/___/__//_/\__/_/_____/_____/
                          (__)_/  _ \/  _ \/ .__\
                          _)  \   __/   __/  /  \
                         /____/__/  \_____/_____/v1.0
  • sjpeg: 's' stands for 'simple'.

  • sjpeg is a simple encoding library for encoding baseline JPEG files. It's also a command-line tool that takes PNG or JPEG images as input to produce JPEG files.

  • Why 'simple'? Well, the encoder used to be one single source file. And not a large one, moreover. Over time it grew and was split, for readability, but the spirit remains the same.

The sjpeg library:

The main header is src/sjpeg.h. This is mainly just one function to call, defined in src/sjpeg.h

size_t SjpegCompress(const uint8_t* rgb, int width, int height,
                     int quality, uint8_t** out_data);

This function will make a lot of automatic decisions based on input samples.

There is a more fine-tuned variant available too:

size_t SjpegEncode(const uint8_t* const data,
                   int W, int H, int stride,
                   uint8_t** const out_data,
                   int quality, int compression_method,
                   int yuv_mode);

as well as functions with a C++ string-based API.

The library comes primarily with a plain-C API, but a C++ version is available too, that uses std::string as interface.

SjpegFreeBuffer() can be called release the buffers returned by SjpegEncode() and SjpegCompress().

Also included in the library: some helper functions to inspect JPEG bitstream. They are meant to help re-processing a JPEG source: SjpegDimensions(): quickly get the JPEG picture dimensions. SjpegFindQuantizer(): return the quantization matrices SjpegEstimateQuality(): return an estimate of the encoding quality

SjpegEncodeParam interface:

This should be the most fine-tuned use of the library: SjpegEncodeParam gives access to a lot of fine controls (C++ only). See src/sjpeg.h for details.

In particular, using SjpegEncodeParam is the recommended way of re-compressing a JPEG input. Here is the recipe:

  • use SjpegFindQuantizer to extract the quantization matrices from the source
  • use SjpegEncodeParam::SetQuantMatrix() to transfer them to the encoding parameters (with a reduction factor if necessary)
  • call sjpeg::SjpegEncode() with this parameter

Alternately, one can use SjpegEstimateQuality() and SjpegEncodeParam::SetQuality() to pass a quality factor instead of the matrices.

SjpegEncodeParam is also useful for transferring some metadata to the final JPEG bitstream.

'Riskiness' score:

The riskiness score is a decision score to help decide between using YUV 4:2:0 and YUV 4:4:4 downsampling. The function to call is:

 int SjpegRiskiness(const uint8_t* rgb, int width, int height, int step, float* risk);

which returns a recommendation for 'yuv_mode' to use in the above API.

The 'sjpeg' command line tool:

examples/sjpeg is a very simple tool to compress a PNG/JPEG file to JPEG.

sjpeg in.png -o out.jpg -q 70 # compress the PNG source with quality 70

sjpeg in.jpg -o out.jpg -r 90 # recompress JPEG input to ~90%

sjpeg has various options to change the encoding method. Just try sjpeg -h.

The 'vjpeg' command line tool:

vjpeg UI

examples/vjpeg is a (non-essential) visualization tool, built with OpenGL/GLUT. It allows changing the compression parameters with the keyboard, and visually inspect the result. This is mostly educational, since most of the parameters from SjpegEncodeParam can be triggered from the keyboard.

Building the library and tools:

Please read the instructions in the INSTALL file.

Basically, you can use the supplied Makefile or generate your build with cmake:

  • make -j, or
  • mkdir build && cd build && cmake ../ && make -j

Compiling with Android NDK

The latest NDK for Android can be retrieved from the Android download page.

Assuming the variable NDK_ROOT is positioned correctly to point to the NDK's directory, the Android binaries can be built with:

$ mkdir build && cd build
$ cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/android.cmake \
           -DSJPEG_ANDROID_NDK_PATH=${NDK_ROOT}
$ make -j

Extra configuration option:

  • ANDROID_ABI: one of armeabi-v7a,armeabi-v7a with NEON,arm64-v8a,x86,x86_64... (default is arm64-v8a)

Discussion list

The following forum can be used to report bugs or just discuss sjpeg:

https://groups.google.com/forum/#!forum/sjpeg

sjpeg's People

Contributors

eclipseo avatar ewouth avatar jzern avatar madebr avatar ricardobtez avatar skal65535 avatar szabadka 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

Watchers

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

sjpeg's Issues

Add an API to target a given file-size or PSNR

(opening this 'issue' as a vague reminder for an interesting TODO)

Similar to WebP API[1], it would useful to have an inner loop that dichotomizes toward
a given, user-specified, target for PSNR or file-size.

Compared to an external script that would dichotomize on -quality, there's some savings to be had by not re-doing histogram collection or sample import for instance. Also the gradient descent could alternate trellis & adaptive-quantization (right now, the trellis pass is somewhat sub-optimal because there's no update pass on the Huffman codes).

Agreed, PSNR is not the ultimate metric to aim for, but targeting PSNR>40dB is usually a good threshold for lot of practical purpose.

[1] https://developers.google.com/speed/webp/docs/api#advanced_encoding_api

CMakefiles and makefile do not specify -std which results in compilation failure

I am using Linux Mint 18.1 with GCC 5.4.0-6 and CMake 3.10.0-rc1. I perform the following:
mkdir build
cd build
cmake ..
make -j

I get the following error message:
make[2]: Entering directory '/home/nlbutts/projects/sjpeg/build'
[ 6%] Building CXX object CMakeFiles/sjpeg.dir/src/bit_writer.cc.o
/usr/bin/c++ -I/home/nlbutts/projects/sjpeg/src -O3 -DNDEBUG -fPIC -o CMakeFiles/sjpeg.dir/src/bit_writer.cc.o -c /home/nlbutts/projects/sjpeg/src/bit_writer.cc
In file included from /home/nlbutts/projects/sjpeg/src/bit_writer.h:29:0,
from /home/nlbutts/projects/sjpeg/src/bit_writer.cc:19:
/home/nlbutts/projects/sjpeg/src/sjpeg.h:336:6: error: ‘shared_ptr’ in namespace ‘std’ does not name a template type
std::shared_ptr MakeByteSink(std::string* output);
^
/home/nlbutts/projects/sjpeg/src/sjpeg.h:339:6: error: ‘shared_ptr’ in namespace ‘std’ does not name a template type
std::shared_ptr MakeByteSink(std::vector* output);
^
/home/nlbutts/projects/sjpeg/src/sjpeg.h:340:17: error: ‘shared_ptr’ in namespace ‘std’ does not name a template type
template<> std::shared_ptr MakeByteSink(std::vector<uint8_t>* output);
^
In file included from /home/nlbutts/projects/sjpeg/src/bit_writer.cc:19:0:
/home/nlbutts/projects/sjpeg/src/bit_writer.h: In member function ‘virtual bool sjpeg::Sink::Commit(size_t, size_t, uint8_t**)’:
/home/nlbutts/projects/sjpeg/src/bit_writer.h:63:71: error: ‘nullptr’ was not declared in this scope
data = extra_size ? reinterpret_cast<uint8_t>(&(ptr_)[pos_]) : nullptr;
^
/home/nlbutts/projects/sjpeg/src/bit_writer.cc: In constructor ‘sjpeg::MemorySink::MemorySink(size_t)’:
/home/nlbutts/projects/sjpeg/src/bit_writer.cc:31:12: error: ‘nullptr’ was not declared in this scope
: buf_(nullptr), pos_(0), max_pos_(0) {
^
/home/nlbutts/projects/sjpeg/src/bit_writer.cc: In member function ‘virtual void sjpeg::MemorySink::Reset()’:
/home/nlbutts/projects/sjpeg/src/bit_writer.cc:41:10: error: ‘nullptr’ was not declared in this scope
buf_ = nullptr;
^
/home/nlbutts/projects/sjpeg/src/bit_writer.cc: In member function ‘void sjpeg::MemorySink::Release(uint8_t
*, size_t*)’:
/home/nlbutts/projects/sjpeg/src/bit_writer.cc:49:10: error: ‘nullptr’ was not declared in this scope
buf_ = nullptr;
^
/home/nlbutts/projects/sjpeg/src/bit_writer.cc: In member function ‘virtual bool sjpeg::MemorySink::Commit(size_t, size_t, uint8_t**)’:
/home/nlbutts/projects/sjpeg/src/bit_writer.cc:65:20: error: ‘nullptr’ was not declared in this scope
if (new_buf == nullptr) return false;
^
/home/nlbutts/projects/sjpeg/src/bit_writer.cc: At global scope:
/home/nlbutts/projects/sjpeg/src/bit_writer.cc:79:6: error: ‘shared_ptr’ in namespace ‘std’ does not name a template type
std::shared_ptr MakeByteSink(std::string* const output) {
^
/home/nlbutts/projects/sjpeg/src/bit_writer.cc:85:6: error: ‘shared_ptr’ in namespace ‘std’ does not name a template type
std::shared_ptr MakeByteSink(std::vector<uint8_t>* const output) {
^
/home/nlbutts/projects/sjpeg/src/bit_writer.cc: In constructor ‘sjpeg::BitWriter::BitWriter(sjpeg::ByteSink*)’:
/home/nlbutts/projects/sjpeg/src/bit_writer.cc:92:64: error: ‘nullptr’ was not declared in this scope
BitWriter::BitWriter(ByteSink* const sink) : sink_(sink), buf_(nullptr) {
^
CMakeFiles/sjpeg.dir/build.make:62: recipe for target 'CMakeFiles/sjpeg.dir/src/bit_writer.cc.o' failed
make[2]: *** [CMakeFiles/sjpeg.dir/src/bit_writer.cc.o] Error 1
make[2]: Leaving directory '/home/nlbutts/projects/sjpeg/build'
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/sjpeg.dir/all' failed
make[1]: *** [CMakeFiles/sjpeg.dir/all] Error 2
make[1]: Leaving directory '/home/nlbutts/projects/sjpeg/build'
Makefile:129: recipe for target 'all' failed
make: *** [all] Error 2

If I update the CMakelists.txt file and add -std=c++11, everything works fine.

vjpeg: Build failure for Windows Arm64 with MSVC

Currently building vjpeg.exe fails when using MSVC (Visual Studio) targeting the Arm64 platform. vjpeg.cc experiences a linking error:

vjpeg.cc
LINK : fatal error LNK1181: cannot open input file 'opengl32.lib' [C:\projects\sjpeg\vjpeg.vcxproj]

The error probably occurs because opengl32.lib is x86 specific.

Example builds can be found on AppVeyor: Arm64 (fails) | x64 (passes).

progressive coding

jpegrescan can sometimes shrink the size further. There should be an option to have progressive-coded output.

Starting a branch 'prog' for that.

build for Android failed

reported esser messages:

ld: error: undefined symbol: sjpeg::EncoderParam::ResetMetadata()
>>> referenced by utils.cc:514 (/home/leleliu008/.ndk-pkg/run/2308279/sjpeg/src/examples/utils.cc:514)
>>>               CMakeFiles/sjpeg-utils.dir/examples/utils.cc.o:(ReadJPEG(std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&, int*, int*, sjpeg::EncoderParam*))
>>> referenced by utils.cc:320 (/home/leleliu008/.ndk-pkg/run/2308279/sjpeg/src/examples/utils.cc:320)
>>>               CMakeFiles/sjpeg-utils.dir/examples/utils.cc.o:(ReadJPEG(std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&, int*, int*, sjpeg::EncoderParam*))
>>> referenced by utils.cc:745 (/home/leleliu008/.ndk-pkg/run/2308279/sjpeg/src/examples/utils.cc:745)
>>>               CMakeFiles/sjpeg-utils.dir/examples/utils.cc.o:(ReadPNG(std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&, int*, int*, sjpeg::EncoderParam*))
>>> referenced 3 more times
clang++: error: linker command failed with exit code 1 (use -v to see invocation)

workaroud:

sed -i '133c target_link_libraries(sjpeg-utils sjpeg)' CMakeLists.txt

Quantization tables should have wider type (probably uint16_t)

8 bits are not enough to store many useful default quant tables (example: https://github.com/mozilla/mozjpeg/blob/master/rdswitch.c#L322-L333 by the way, this is apparently the table which is used by default in mozjpeg, they probably have good reasons for using it instead of the JPEG Annex K).

Even when using a table which is all ≤ 255, after the scaling with quality parameter the values can become bigger and I think it's not good to have to limit them. (both the standard cjpeg tool and the mozjpeg fork allow values larger than 255 in final quantization tables, it can be seen by inspecting jpeg files produced by them with djpeg -v -v example.jpg > /dev/null; as an extreme example, a file produced by cjpeg -q 1 has quantizer values as big as 6050)

If you agree with the idea of changing the quant tables type from uint8_t to uint16_t, I might try to develop a patch.

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.