Get DCT coefficients of jpeg image

I took a crack at translating this code into Julia using the JpegTurbo.jl package I linked above:

import JpegTurbo: LibJpeg
import JpegTurbo.LibJpeg: DCTSIZE

function jpeg_read_coefficients(io::IO)
    cinfo = LibJpeg.jpeg_decompress_struct()
    jerr = Ref{LibJpeg.jpeg_error_mgr}()
    cinfo.err = LibJpeg.jpeg_std_error(jerr)
    LibJpeg.jpeg_create_decompress(cinfo)
    io_file = Libc.FILE(io)
    LibJpeg.jpeg_stdio_src(cinfo, io_file)
    LibJpeg.jpeg_read_header(cinfo, true)
    
    coef_arrays = LibJpeg.jpeg_read_coefficients(cinfo)
    access_virt_barray = unsafe_load(cinfo.mem).access_virt_barray
    components = Matrix{LibJpeg.JCOEF}[]
    
    for ci = 1:cinfo.num_components
        comp_info = unsafe_load(cinfo.comp_info, ci)
        c_height = comp_info.height_in_blocks * DCTSIZE
        c_width = comp_info.width_in_blocks * DCTSIZE
        m = Matrix{LibJpeg.JCOEF}(undef, c_height, c_width)
        
        for blk_y = 1:comp_info.height_in_blocks
            buffer = unsafe_load(ccall(access_virt_barray, LibJpeg.JBLOCKARRAY, 
                (Ref{LibJpeg.jpeg_decompress_struct},Ptr{Cvoid},LibJpeg.JDIMENSION,LibJpeg.JDIMENSION,LibJpeg.boolean),
                cinfo, unsafe_load(coef_arrays,ci), blk_y-1, 1, false))
            for blk_x = 1:comp_info.width_in_blocks
                bufptr = unsafe_load(buffer, blk_x)
                for i=1:DCTSIZE, j=1:DCTSIZE
                    m[i + DCTSIZE*(blk_y-1), j + DCTSIZE*(blk_x-1)] =
                        bufptr[(i-1)*DCTSIZE + j]
                end
            end
        end
        
        push!(components, m)
    end
    
    LibJpeg.jpeg_destroy_decompress(cinfo)
    close(io_file)
    return components
end

jpeg_read_coefficients(filename::AbstractString) =
    open(jpeg_read_coefficients, filename, "r")

It runs, in the sense that jpeg_read_coefficients(filename) returns an array of matrices of DCT coefficients (one per component). I’m not sure if it’s correct, since I don’t know what the right output is — it’s possible there is a typo, but at least the above code should be a good start.

Update: fixed to explicitly close the file as suggested by @pakk-minidose below

4 Likes