I am currently struggling to understand why recompressing an uncompressed JPEG image differs its original.
It's clear, that JPEG is a lossy compression, but what if the image to compress is already uncompressed, which means all sampling losses are already included? In other words: Downsampling and DCT should be inversable at this point without loosing data.
To make sure losses are not effected by the color space conversion, this step is skipped and YUV images are used.
Compress YUV image to JPEG (image.yuv --> image.yuv.jpg)
Uncompress JPEG image to YUV image (image.yuv.jpg --> image.yuv.jpg.yuv)
Compress YUV image to JPEG (image.yuv.jpg.yuv --> image.yuv.jpg.yuv.jpg)
Uncompress JPEG image to YUV image (image.yuv.jpg.yuv.jpg --> image.yuv.jpg.yuv.jpg.yuv)
Step 1 includes a lossy compression, so we will not deal with this step anymore. For me, intresting is what happens afterwards:
Uncompressing the JPEG image back to YUV (step 2) leads to an image which perfectly fits all sampling steps if compressed again (step 3). So the JPEG image after step 3 should (from my understanding) be exactly the same as after step 1. Also the YUV images after step 4 and step 2 should equal each other.
Looking at the steps for one 8x8 block the following simplified sequence should illustrate what I am trying to descibe. Lets start with the original YUV image, which can only be decompressed loosing all decimal places:
[ 1.123, 2.345, 3.456, ... ] (YUV)
DTC + Quantization
[ -26, -3, -6, ... ] (Quantized frequency space)
Inverse DTC + Quantization
[ 1, 2, 3, ... ] (YUV)
Doing this with input, which already matches all steps, which may lead to loss of data afterwards (using round numbers in my example), the decompressed image should match its original:
[ 1, 2, 3, ... ] (YUV)
DTC + Quantization
[ -26, -3, -6, ... ] (Quantized frequency space)
Inverse DTC + Quantization
[ 1, 2, 3, ... ] (YUV)
There are also some sources and discussions, which are confirming my idea:
need help creating Jpeg Generational Degradation code
What factors cause or prevent “generational loss” when JPEGs are recompressed multiple times?
Lossless Chroma Subampling
So much for theory. In praxis, I've runned these steps using ffmpeg and Nvidias jpeg samples (using NvJPEGEncoder).
ffmpeg:
#Create YUV image
ffmpeg -y -i image.jpg -s 1920x1080 -pix_fmt yuv420p image.yuv
#YUV to JPEG
ffmpeg -y -s 1920x1080 -pix_fmt yuv420p -i image.yuv image.yuv.jpg
#JPEG TO YUV
ffmpeg -y -i image.yuv.jpg -s 1920x1080 -pix_fmt yuv420p image.yuv.jpg.yuv
#YUV to JPEG
ffmpeg -y -s 1920x1080 -pix_fmt yuv420p -i image.yuv.jpg.yuv image.yuv.jpg.yuv.jpg
#JPEG TO YUV
ffmpeg -y -i image.yuv.jpg.yuv.jpg -s 1920x1080 -pix_fmt yuv420p image.yuv.jpg.yuv.jpg.yuv
#YUV to JPEG
ffmpeg -y -s 1920x1080 -pix_fmt yuv420p -i image.yuv.jpg.yuv.jpg.yuv image.yuv.jpg.yuv.jpg.yuv.jpg
Nvidia:
#Create YUV image
./jpeg_decode num_files 1 image.jpg image.yuv
#YUV to JPEG
./jpeg_encode image.yuv 1920 1080 image.yuv.jpg
#JPEG TO YUV
./jpeg_decode num_files 1 image.yuv.jpg image.yuv.jpg.yuv
#YUV to JPEG
./jpeg_encode image.yuv.jpg.yuv 1920 1080 image.yuv.jpg.yuv.jpg
#JPEG TO YUV
./jpeg_decode num_files 1 image.yuv.jpg.yuv.jpg image.yuv.jpg.yuv.jpg.yuv
#YUV to JPEG
./jpeg_encode image.yuv.jpg.yuv.jpg.yuv 1920 1080 image.yuv.jpg.yuv.jpg.yuv.jpg
But a comparison of the images
image.yuv.jpg.yuv and image.yuv.jpg.yuv.jpg.yuv
image.yuv.jpg.yuv.jpg and image.yuv.jpg.yuv.jpg.yuv.jpg
showing differences in the files. That brings me to my question why and where the difference gets happen, since from my understanding the files should be equal.
Related
I am trying to convert png images into webP with sampling factor. I am imagemagick tool for conversion, as they mentioned in docs -quality is used for sampling but it did not work.
This command works fine to covert kodak png to JPEG.
convert test/images/kodim$i.png -quality $(($j*5)) -sampling-factor 4:2:0 test/jpeg/kodim$i/`printf "%02d" $j`.jpg
Converting PnG to WebP
convert test/images/kodim$i.png -quality $(($j*5)) test/webP/kodim$i/`printf "%02d" $j`.webp
I want to follow same sampling as mentioned in JPEG.
This work fine on kodak images.
Just install webP encoder
sudo apt-get install webp
Code
for i in {01..24..1}; do
echo WebP Encoding test/images/kodim$i.png
mkdir -p test/webP/kodim$i
for j in {0..20..1}; do
cwebp test/images/kodim$i.png -q $(($j*5)) -o test/webP/kodim$i/`printf "%02d" $j`.webp
done
done
Important
This command creates a WebP lossy image at different qualities.
WebP lossy is always with YUV420 sampling, equivalent to imagemagick's -sampling-factor 2x2 (also -sampling-factor 4:2:0) for jpeg.
I have lot of images and not i want to split them w.r.t aspect ratio.
What is presently working is
convert -crop 2:1 input.png cropped_%d.png
The above command split the image. Assuming i have 900px x 2000px then it creates 5 images.
But now the problem is i want to keep some overlap
I tried
convert -crop 2:1+0+40 input.png cropped_%d.png
Its only giving one image.
I tried
convert -crop 1x4+0+40# Settings_commit1.png cropped_%d.png
This works well. But here i have to mention 1x4 (grid). But I want to do it by aspect ratio
I did the following way
$ convert --version
Version: ImageMagick 7.0.8-35 Q16 x86_64 2019-03-25 https://imagemagick.org
Copyright: © 1999-2019 ImageMagick Studio LLC
License: https://imagemagick.org/script/license.php
Features: Cipher DPC HDRI Modules OpenCL OpenMP
Delegates (built-in): bzlib cairo fontconfig freetype gslib heic jbig jng jp2 jpeg lcms lqr ltdl lzma openexr pangocairo png ps raw rsvg tiff webp wmf x xml zlib
The two commands split the image:
Based on aspect ratio split the image file (but overlap does not work 2:1+0+40)
convert -crop 2:1 input.png cropped_%d.png
Based on grid split the image file and overlap works (+0+40)
convert -crop 1x4+0+40# Settings_commit1.png cropped_%d.png (with 40px vertical overlap)
Logic is we get the number of split images from aspect ratio and then use it in grid
This is the scrip which worked
filename="someimage.png";
# just creating a dir and empty it
mkdir ~/croped
rm -rf ~/croped/*
# split the image base on aspect ratio and save them in croped folder
convert -crop 903:600 ${filename} ~/croped/crop_aspect_%d.png;
# count the number of files in the croped folder
number_files=`ls -l ~/croped | grep -E "crop_aspect_*" | wc -l`
# based on this number apply the grid
convert -crop 1x${number_files}+0+8# ${filename} ~/croped/crop_grid_%d.png
I tried to resize a very big image (457 MB and 21600x21600) with the following command
-i test.png -vf scale=320:-1 out.png
but it throws exception saying "Picture size 21600x21600 is invalid". How can I find out the biggest supported resolution by ffmpeg? Is there a way to resize this high resolution image with ffmpeg?
If you want to use ImageMagick it is included in most Linux distros and is available for macOS and Windows.
Your command becomes:
convert test.png -resize 320x result.png
If you are running v7 or newer, use:
magick test.png -resize 320x result.png
If you have lots to do, and you want all the resized images written in a directory called thumbs you can use:
mkdir thumbs
magick mogrify -path thumbs -resize 320x *.png
Alternatively, you may find vips is a lighter-weight installation and does a faster conversion using less memory:
mkdir thumbs
vipsthumbnail -s 320 -o "thumbs/%s.png" image.png
I'm trying to convert color image from .raw format into .jpg or .png format, I used ImageMagick with the following command prompt code:
convert -size 768X576 -depth 8 rgb:my_image.raw my_image.jpeg
It is work successfully to convert the image into jpeg format, but with some problems which are:
1- The resulted image is gray and not colored.
2- The resulted image is subdivided into 9 images as a grid of small images repeated.
When I change rgb into gray, return me 3 separated gray image with different in lighting conditions from darker to lighter.
I'm necessary need to convert the image format, can anyone please help me how can I edit the code or also any other software that able to open the image, I tried very software but they are usefulness, I use windows 10.
I tested it with my own raw input image, and it's working fine.
You may be using a wrong version of ImageMagick.
I downloaded the version: ImageMagick-7.0.8-49-Q8-x64-static.exe from https://imagemagick.org/script/download.php.
In the version I downloaded, the convert command is magick.exe and not convert.
The following command is working:
magick.exe -size 768x576 -depth 8 rgb:my_image.raw my_image.jpeg.
I prefer using FFmpeg for format conversion.
You can download it from https://ffmpeg.zeranoe.com/builds/
Select:
Version: stable (current version is 4.1.3).
Architecture: Windows 64-bit
Linking: static.
Extract the zip file, you only need ffmpeg.exe.
For converting the raw file to jpeg using FFmpeg you can use the following command:
ffmpeg -y -video_size 768x576 -pix_fmt rgb24 -i my_image.raw -pix_fmt yuvj444p my_image.jpeg
Assuming your raw file format is "chunky" RGB (ordered: r,g,b,r,g,b,r,g,b...), make sure the file size is 768*576*3 = 1,327,104 Bytes.
Just to make sure, the problem is not in your input file...
You can create an synthetic input raw image using FFmpeg and convert the result to jpeg:
Create synthetic input:
ffmpeg -y -f lavfi -i testsrc=duration=1:size=768x576:rate=1 -pix_fmt rgb24 -f image2 test_image.raw
Convert synthetic input:
ffmpeg -y -video_size 768x576 -pix_fmt rgb24 -i test_image.raw -pix_fmt yuvj444p test_image.jpeg
Result (test_image.jpeg):
I found the solution:
Apparently the raw image format is "planar" RGB:
RRRRR
RRRRR
RRRRR
GGGGG
GGGGG
GGGGG
BBBBB
BBBBB
BBBBB
Converting it to jpeg (using FFmpeg) is a complicated problem:
ffmpeg -y -video_size 768x576 -pix_fmt gbrp -i m-001-1.raw -filter_complex "extractplanes=g+b+r[g][b][r],[r][g][b]mergeplanes=0x001020:gbrp[v]" -map "[v]" m-001-1.jpeg
FFmpeg has no support for raw "planar" RGB format.
The only "planar" that is close to RGB is GBR (green plane is first).
I used extractplanes and mergeplanes for reordering the color channels.
ImageMagick has a much more simple solution:
magick.exe -depth 8 -interlace plane -size 768x576 rgb:image.raw image.jpeg
Example:
Since stackoverflow not allowing upload of raw files, I uploaded a png image in grayscale format that simulates the "planar" RGB:
For testing the solution use the following steps:
Download the image (imgur named it: D5IUp.png).
Convert from png to raw as "planar" RGB" (.y extension):
ffmpeg -y -i D5IUp.png -c:v rawvideo -pix_fmt gray D5IUp.y
Convert from raw to jpeg:
ffmpeg -y -video_size 128x96 -pix_fmt gbrp -i D5IUp.y -filter_complex "extractplanes=g+b+r[g][b][r],[r][g][b]mergeplanes=0x001020:gbrp[v]" -map "[v]" D5IUp.jpeg
Result:
Example for batch conversion using ImageMagick:
for %%f in (*.raw) do (magick.exe -depth 8 -interlace plane -size 768x576 rgb:"%%f" "%%~nf.jpeg")
I have a folder of images of varying sizes and quality. Is there a way with ImageMagic that I could automatically resize them to be no bigger 1100px x 1100px and less than 160kb. And not to re-size if they are smaller than those parameters. Also not to distort the image so it fits within but to only re-size so for example an image which is 2200px by 1000px would become 1100px by 500px.
I'm working on Ubuntu with ImageMagick 6.7.7-10.
Try this on a copy of your files:
mogrify -define jpeg:extent=160k -resize 1100x1100\> *.jpg
I am assuming your files are JPEG images. The command will largely work for other image types too, but it can only enforce the 160kB limit for JPEG files - not PNG, or TIFF etc.
Example
With version: ImageMagick 6.9.1-10 Q16 x86_64 2015-08-06
convert -size 2000x2000 xc:gray +noise random a.jpg
ls -lrt a.jpg
-rw-r--r-- 1 mark staff 6969601 21 Aug 18:28 a.jpg # <--- 7MB
mogrify -define jpeg:extent=160k -resize 1100x1100\> a.jpg
ls -lrt a.jpg
-rw-r--r-- 1 mark staff 147938 21 Aug 18:28 a.jpg # <--- 160kB
identify a.jpg
a.jpg JPEG 1100x1100 1100x1100+0+0 8-bit sRGB 148KB 0.000u 0:00.000