Skip to content

Commit

Permalink
convert pic_jpeg interface to pure Lua/FFI solution
Browse files Browse the repository at this point in the history
pic_jpeg had a wrapper lib before that was needed because of the
libjpeg API which uses setjmp/longjmp error handling.
By using the TurboJPEG API that comes with libjpeg-turbo, we can
use a pure Lua/FFI based approach.
  • Loading branch information
hwhw committed Nov 11, 2014
1 parent 2990edc commit 6e399d6
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 149 deletions.
8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ all: $(OUTPUT_DIR)/libs $(if $(ANDROID),,$(LUAJIT)) \
$(if $(ANDROID),luacompat52 lualongnumber,) \
$(if $(WIN32),,$(EVERNOTE_LIB)) \
$(LUASERIAL_LIB) \
$(TURBOJPEG_LIB) \
$(if $(or $(ANDROID),$(WIN32)),,$(OUTPUT_DIR)/tar) \
$(if $(or $(ANDROID),$(WIN32)),,$(OUTPUT_DIR)/sdcv) \
$(if $(or $(ANDROID),$(WIN32)),,$(OUTPUT_DIR)/zsync) \
Expand Down Expand Up @@ -90,6 +91,9 @@ $(JPEG_LIB):
$(MAKE) -j$(PROCESSORS) -C $(JPEG_DIR) --silent install
cp -fL $(JPEG_DIR)/.libs/$(notdir $(JPEG_LIB)) $@

$(TURBOJPEG_LIB): $(JPEG_LIB)
cp -fL $(JPEG_DIR)/.libs/$(notdir $(TURBOJPEG_LIB)) $@

# libpng, fetched via GIT as a submodule
$(PNG_LIB): $(ZLIB)
-cd $(PNG_DIR) && sh autogen.sh
Expand Down Expand Up @@ -223,7 +227,6 @@ $(K2PDFOPT_LIB) $(LEPTONICA_LIB) $(TESSERACT_LIB): $(PNG_LIB) $(ZLIB) $(MUPDF_LI
libs: \
$(if $(or $(EMULATE_READER),$(ANDROID),$(WIN32)),,$(OUTPUT_DIR)/libs/libkoreader-input.so) \
$(OUTPUT_DIR)/libs/libkoreader-lfs.so \
$(OUTPUT_DIR)/libs/libpic_jpeg.so \
$(if $(ANDROID),,$(OUTPUT_DIR)/libs/libkoreader-djvu.so) \
$(OUTPUT_DIR)/libs/libkoreader-cre.so \
$(OUTPUT_DIR)/libs/libwrap-mupdf.so
Expand All @@ -238,9 +241,6 @@ $(OUTPUT_DIR)/libs/libkoreader-lfs.so: \
luafilesystem/src/lfs.c
$(CC) $(DYNLIB_CFLAGS) -o $@ $^

$(OUTPUT_DIR)/libs/libpic_jpeg.so: pic_jpeg.c $(JPEG_LIB)
$(CC) -I$(JPEG_DIR) $(DYNLIB_CFLAGS) -o $@ $^

# put all the libs to the end of compile command to make ubuntu's tool chain
# happy
$(OUTPUT_DIR)/libs/libkoreader-djvu.so: djvu.c \
Expand Down
1 change: 1 addition & 0 deletions Makefile.defs
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ FREETYPE_LIB=$(OUTPUT_DIR)/libs/libfreetype$(if $(WIN32),-6.dll,.so.6)
FREETYPE_DIR=freetype2

JPEG_LIB=$(OUTPUT_DIR)/libs/libjpeg$(if $(WIN32),-8.dll,.so.8)
TURBOJPEG_LIB=$(OUTPUT_DIR)/libs/libturbojpeg$(if $(WIN32),.dll,.so)
JPEG_DIR=libjpeg-turbo-1.3.1

PNG_LIB=$(OUTPUT_DIR)/libs/libpng16$(if $(WIN32),-16.dll,.so.16)
Expand Down
14 changes: 14 additions & 0 deletions ffi-cdecl/turbojpeg_decl.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include <turbojpeg.h>

#include "ffi-cdecl.h"
#include "ffi-cdecl-luajit.h"

cdecl_type(tjhandle)

cdecl_enum(TJPF)

cdecl_func(tjDestroy)
cdecl_func(tjInitDecompress)
cdecl_func(tjDecompressHeader2)
cdecl_func(tjDecompress2)
cdecl_func(tjDecompressToYUV)
67 changes: 36 additions & 31 deletions ffi/pic.lua
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
local ffi = require("ffi")
local BB = require("ffi/blitbuffer")
local pic_jpeg = ffi.load("libs/libpic_jpeg.so")

ffi.cdef[[
uint8_t *jpegLoadFile(const char *fname, int *width, int *height, int *components);

void *malloc(int size);
void free(void *ptr);
void *memset(void *s, int c, int n);
]]
local dummy = require("ffi/turbojpeg_h")
local turbojpeg
if ffi.os == "Windows" then
turbojpeg = ffi.load("libs/libturbojpeg.dll")
else
turbojpeg = ffi.load("libs/libturbojpeg.so")
end

local Pic = {}

Expand Down Expand Up @@ -90,38 +89,44 @@ function PicDocument:close()
self.image_bb:free()
self.image_bb = nil
end
if self.raw_img then
ffi.C.free(raw_img)
end
end

PicDocument.__gc = PicDocument.close

function Pic.openJPGDocument(filename)
local doc = PicDocument:new{}
local w_p = ffi.new("int[1]")
local h_p = ffi.new("int[1]")
local comp_p = ffi.new("int[1]")

local raw_img = pic_jpeg.jpegLoadFile(filename, w_p, h_p, comp_p)
if raw_img == nil then
error("Cannot open jpeg file")
local fh = io.open(filename, "r")
assert(fh, "couldn't open file")
local data = fh:read("*a")
fh:close()

local handle = turbojpeg.tjInitDecompress()
assert(handle, "no TurboJPEG API decompressor handle")

local width = ffi.new("int[1]")
local height = ffi.new("int[1]")
local jpegsubsamp = ffi.new("int[1]")
turbojpeg.tjDecompressHeader2(handle, ffi.cast("unsigned char*", data), #data, width, height, jpegsubsamp)
assert(width[0] > 0 and height[0] > 0, "image dimensions")

local doc = PicDocument:new{width=width[0], height=height[0]}
local format
if Pic.color then
doc.image_bb = BB.new(width[0], height[0], BB.TYPE_BBRGB24)
doc.components = 3
format = turbojpeg.TJPF_RGB
else
doc.image_bb = BB.new(width[0], height[0], BB.TYPE_BB8)
doc.components = 1
format = turbojpeg.TJPF_GRAY
end

doc.width = w_p[0]
doc.height = h_p[0]

if comp_p[0] == 1 then
doc.image_bb = BB.new(doc.width, doc.height, BB.TYPE_BB8, raw_img)
elseif comp_p[0] == 3 then
doc.image_bb = BB.new(doc.width, doc.height, BB.TYPE_BBRGB24, raw_img)
else
ffi.C.free(raw_img)
error("Unsupported image format")
if turbojpeg.tjDecompress2(handle, ffi.cast("unsigned char*", data), #data,
ffi.cast("unsigned char*", doc.image_bb.data),
width[0], doc.image_bb.pitch, height[0], format, 0) == -1 then
error("decoding JPEG file")
end

doc.raw_img = raw_img
doc.components = comp_p[0]
turbojpeg.tjDestroy(handle)

return doc
end
Expand Down
23 changes: 23 additions & 0 deletions ffi/turbojpeg_h.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
local ffi = require("ffi")

ffi.cdef[[
enum TJPF {
TJPF_RGB = 0,
TJPF_BGR = 1,
TJPF_RGBX = 2,
TJPF_BGRX = 3,
TJPF_XBGR = 4,
TJPF_XRGB = 5,
TJPF_GRAY = 6,
TJPF_RGBA = 7,
TJPF_BGRA = 8,
TJPF_ABGR = 9,
TJPF_ARGB = 10,
};
typedef void *tjhandle;
int tjDestroy(tjhandle);
tjhandle tjInitDecompress(void);
int tjDecompressHeader2(tjhandle, unsigned char *, long unsigned int, int *, int *, int *);
int tjDecompress2(tjhandle, unsigned char *, long unsigned int, unsigned char *, int, int, int, int, int);
int tjDecompressToYUV(tjhandle, unsigned char *, long unsigned int, unsigned char *, int);
]]
84 changes: 0 additions & 84 deletions pic_jpeg.c

This file was deleted.

30 changes: 0 additions & 30 deletions pic_jpeg.h

This file was deleted.

0 comments on commit 6e399d6

Please sign in to comment.