contributed by < JoshuaLee0321
, Paintakotako
>
JPEG is a compression algorithm, not a file format.
jpeg
format?Almost every binary file contains a couple of markers (or headers).
They are very crucial for making sense of a file and are used by programs like file (on Mac/Linux) to tell us details about a file. These markers define where some specific information in a file is stored.
For example:
7F
followed by "ELF" (7F 45 4C 46).0x505249202a20485454502f322e300d0a0d0a534d0d0a0d0a
, or PRI *
HTTP/2.0\r\n\r\nSM\r\n\r\n
. The preface is designed to avoid the processing of frames by servers and intermediaries which support earlier versions of HTTP but not 2.0.GIF89a
(47 49 46 38 39 61) or GIF87a
(47 49 46 38 37 61)FF D8
and end with FF D9
.References: Magic_number_(programming)
So, if we want to encode a pictrue into JPEG, we must follow the abovementioned format.
The JPEG standard basically has four different operational modes:
The commonly referred JPEG compression mode is essentially the Baseline Sequential DCT-based Coding mode. In this mode, compression is based on the Sequential Discrete Cosine Transform (DCT), which is widely used for encoding JPEG images.
Major steps of JPEG encoding:
An RGB triplet (r,g,b) represents the
three-dimensional coordinate
of the point of the given color within the cube or its faces or along its edges.
On this step the colors of the
RGB
coordinates are converted to . During this conversion we take three standard channels (RGB
) and convert them into a different representation whichis based on a luminance channel and two opposing color channels. These three channels are typically less interdependent then the RGB channels. That allows us to store them with different resolution. If the image isCMYK
orgrayscale
, it is processed without any color conversion.
The conversion formula is as follows:
It is widely known that we are much more sensitive to changes in luminance than in chromainance. It means thatneglect larger changes in the chrominance without affecting our perception of the image.
The discrete cosine transform (DCT) helps separate the image into parts (or spectral sub-bands) of differing importance (with respect to the image's visual quality). The DCT is similar to the discrete Fourier transform: it transforms a signal or image from the spatial domain to the frequency domain
Before we apply JPEG compression to an image, it converts the image into chunks of 8x8 blocks of pixels.
Before running, we need to generate excutable file (ELF).
The following process can generate ELF step by step
Follow the RISCV-asm-manual-pseudo-ops, the code which was written by the auther has some syntax error.
We can use the following assembly code to observe difference between none folding data and folding data.
.org
, .set
, .-str
: These instuction was not found in RISCV-asm manual, but in GNU assembler manual.
The .data
section is inserted into the .text
section.
Using Makefile can help us generate ELF efficeintly, using the following code:
After generating ELF file, we can disassemble the elf file in order to find out whether all .asm
file is linked correctly
By observing the disassemly code, we find that all external symbols are correctly inserted into the ELF file, which meets out expectations.
Running on rv32emu, reading the docs section, RISC-V calling conventions
is slightly different to the origin version of RISC-V, when we try to run raw riscv version assembly on emulator, warning such like unknown syscall 0
arise.
So, we need to modify origin code in order to run correctly on rv32emu
.
Using the syscall provided for RISC-V does not work on rv32emu, so we need to modify the original code in order to get our output correctly.
When expanding a macro, we discovered that labels defined within the macro are redundantly expanded. This leads to confusion during the assembling stage, as it is uncertain which macro to jump to. The assembler then signals a duplicate label definition. To address this issue, we need to move the labels defined within the macro to the external scope to resolve the problem of redundant expansion.
Details can refer to this commit.
Using system call clock_gettime in order to evaluate each functions eclapes cycles.
Details can refer to this commit
After implementing rdcycle function call, we can get the following result:
Function | Clock cycyles |
---|---|
rgb2y | 1430 |
dct_c | 700 |
dct_r | 684 |
nq_y | 919 |
nzigzag | 144 |
rle | 10138 |
nhuffman_y | 5109 |
norganize | 2486 |
Total cycles elapsed: 27330
Show me more about optimizations.