theonlineoasis

These files are a partial wrapper of some functionality in libjpeg to make a python module.

Code samples on this website come without any guarantees – use them at your own risk! I am grateful for comments or patches sent to my email address: first name.last name@cl.cam.ac.uk.

from ctypes import cdll, Structure, c_char_p, pointer, POINTER, Array, cast, addressof, sizeof
from pylibjpegtypes import jpeg_info

class libjpeg:
  def __init__(self):
    pylibjpeg = cdll.LoadLibrary('pylibjpeg/pylibjpeg.so')
    self.load_jpeg_file = pylibjpeg.load_jpeg_file
    self.load_jpeg_file.restype = POINTER(jpeg_info)
    self.load_jpeg_file.argtypes = [c_char_p,]
  
  def get_jpeg_info(self, file_name):
    info = self.load_jpeg_file(file_name)
    component_count = info.contents.component_count
    blocks = []
    qmatrices = []
    for ci in range(0, component_count):
      bw = info.contents.width_blocks[ci]
      bh = info.contents.height_blocks[ci]
      this_component = []
      for by in range(0, bh):
        for bx in range(0, bw):
          this_component.append(info.contents.dct_coefficients[ci][64 * (bx + by * bw) : 64 * (bx + by * bw) + 64])
      blocks.append(this_component)
      qmatrices.append(info.contents.quantization_tables[ci][0 : 64])
      
    return (qmatrices, blocks)
#include <stdio.h>
#include <stdlib.h>
#include <jpeglib.h>
#include <jerror.h>
#include <inttypes.h>

#include "ijgdct.h"

#define BLOCK_SIZE 64

typedef struct jpeg_info
{
  uint8_t component_count;
  uint16_t* width_blocks;
  uint16_t* height_blocks;
  uint16_t** quantization_tables;
  int32_t** dct_coefficients;
} jpeg_info;

jpeg_info* load_jpeg_file(const char* file_name);
#include "pylibjpeg.h"

jpeg_info* load_jpeg_file(const char* file_name)
{
  struct jpeg_decompress_struct cinfo;
  struct jpeg_error_mgr jerr;
  jpeg_info* result;
  jvirt_barray_ptr* coeff_arrays;
  int ci, by, bx, bi;
  FILE* infile;

  // Create decompression object.
  cinfo.err = jpeg_std_error(&jerr);
  jpeg_create_decompress(&cinfo);

  if ((infile = fopen(file_name, "rb")) == NULL)
  {
    fprintf(stderr, "Can't open %s\n", file_name);
    exit(1);
  }
  jpeg_stdio_src(&cinfo, infile);

  // Get all compression parameters.
  jpeg_read_header(&cinfo, TRUE);

  // Read coefficients.
  coeff_arrays = jpeg_read_coefficients(&cinfo);
  
  // Setup the result structure.
  // TODO: Deal with component count != 3 case.
  result = (jpeg_info*)malloc(sizeof(jpeg_info));
  result->component_count = 3;
  result->quantization_tables = (uint16_t**)malloc(sizeof(uint16_t*) * result->component_count);
  result->dct_coefficients = (int32_t**)malloc(sizeof(int32_t*) * result->component_count);
  result->width_blocks = (uint16_t*)malloc(sizeof(uint16_t) * result->component_count);
  result->height_blocks = (uint16_t*)malloc(sizeof(uint16_t) * result->component_count);

  for (ci = 0; ci < 3; ci++)
  {
    JBLOCKARRAY buffer;
    JCOEFPTR blockptr;
    jpeg_component_info* compptr;
    compptr = cinfo.comp_info + ci;

    result->quantization_tables[ci] = (uint16_t*)malloc(sizeof(uint16_t) * BLOCK_SIZE);
    for (bi = 0; bi < BLOCK_SIZE; bi++)
      result->quantization_tables[ci][bi] = compptr->quant_table->quantval[bi];

    result->width_blocks[ci] = compptr->width_in_blocks;
    result->height_blocks[ci] = compptr->height_in_blocks;
    result->dct_coefficients[ci] = (int32_t*)malloc(sizeof(int32_t) * compptr->width_in_blocks * compptr->height_in_blocks * BLOCK_SIZE);

    for (by = 0; by < compptr->height_in_blocks; by++)
    {
      buffer = (cinfo.mem->access_virt_barray)((j_common_ptr)&cinfo, coeff_arrays[ci], by, (JDIMENSION)1, FALSE);
      for (bx = 0; bx < compptr->width_in_blocks; bx++)
      {
        blockptr = buffer[0][bx];
        for (bi = 0; bi < BLOCK_SIZE; bi++)
          result->dct_coefficients[ci][BLOCK_SIZE * (bx + by * compptr->width_in_blocks) + bi] = blockptr[bi];
        //int clips = block_idct(block);
        //if (clips & 1)
        //  printf("Clips at 255\n");
        //if (clips & 2)
        //  printf("Clips at 0\n");
      }
    }
  }

  // Clean up.
  jpeg_finish_decompress(&cinfo);
  jpeg_destroy_decompress(&cinfo);

  return result;
}
from ctypes import cdll, Structure, c_uint8, c_uint16, c_int32, c_char_p, pointer, POINTER

class jpeg_info(Structure):
  _fields_ = [
    ('component_count', c_uint8),
    ('width_blocks', POINTER(c_uint16)),
    ('height_blocks', POINTER(c_uint16)),
    ('quantization_tables', POINTER(POINTER(c_uint16))),
    ('dct_coefficients', POINTER(POINTER(c_int32)))]
OBJ=pylibjpeg.o

CC=gcc
CFLAGS=-Wall -g3 -fPIC
UNAME=$(shell uname)

ifeq ($(UNAME), Darwin)
  SO_NAME=pylibjpeg.0.dylib
  SO_NAME_MINOR=pylibjpeg.0.0.dylib
  LINKER_FLAGS=-dynamiclib -Wl,-headerpad_max_install_names,-undefined,dynamic_lookup,-compatibility_version,0.0,-current_version,0.0,-install_name,$(SO_NAME)
else
  SO_NAME=pylibjpeg.so.0
  SO_NAME_MINOR=pylibjpeg.so.0.0
  LINKER_FLAGS=-shared -Wl,-soname,$(SO_NAME)
endif

all: $(SO_NAME_MINOR)

pylibjpeg.o:

$(SO_NAME_MINOR): $(OBJ)
	gcc -Wall $(LINKER_FLAGS) -o $(SO_NAME_MINOR) $(OBJ) -ljpeg -lc
	-ln -f -s $(SO_NAME_MINOR) $(SO_NAME)

clean: 
	-rm $(SO_NAME_MINOR)
	-rm $(SO_NAME)
	-rm $(OBJ)