<commit_before>--[[
rendering image with mupdf library
--]]

local ffi = require("ffi")
local Blitbuffer = require("ffi/blitbuffer")
local mupdf = ffi.load("libs/libmupdf.so")

require("ffi/mupdf_h")

local Image = {}

function Image:initContext(cache_size)
	-- Remember to change library version when upgrading MuPDF!
	self.context = mupdf.fz_new_context_imp(nil, nil, cache_size or bit.lshift(8, 20), "1.5")
end

function Image:loadImage(filename, width, height)
	local file = io.open(filename)
    if file then
	    local data = file:read("*a")
	    file:close()
	    self.image = mupdf.fz_new_image_from_data(self.context,
                        ffi.cast("unsigned char*", data), #data)
        if self.image ~= nil then
            self.pixmap = mupdf.fz_new_pixmap_from_image(self.context,
                        self.image, width or -1, height or -1)
        end
    end
end

function Image:toBlitBuffer()
	local pixmap = ffi.new("fz_pixmap[1]")
	pixmap = self.pixmap
	if self.pixmap.n ~= 2 then
		self.pixmap = mupdf.fz_new_pixmap(self.context, mupdf.fz_device_gray(self.context),
										  pixmap.w, pixmap.h);
		mupdf.fz_convert_pixmap(self.context, self.pixmap, pixmap);
		mupdf.fz_drop_pixmap(self.context, pixmap);
	end
	self.bb = Blitbuffer.new(self.pixmap.w, self.pixmap.h, Blitbuffer.TYPE_BB8A, self.pixmap.samples)
	self.bb:invert() -- our blitbuffers have reversed b->w scale
	self.bb = self.bb:copy() -- we make a copy so mupdf can drop the memory
end

function Image:freeContext()
	if self.pixmap ~= nil then
		mupdf.fz_drop_pixmap(self.context, self.pixmap)
		self.pixmap = nil
	end
    if self.image ~= nil then
        mupdf.fz_drop_image(self.context, self.image)
        self.image = nil
    end

    --[[ FIXME: segmentation fault when calling fz_free_context if we called
    -- fz_drop_image first. Although valgrind shows that commenting out
    -- fz_free_context does not leading to memory leak, it's still a dirty hack
    -- and need to be fixed by those who knows mupdf better.
	if self.context ~= nil then
		mupdf.fz_free_context(self.context)
		self.context = nil
	end
    --]]
end

function Image:fromFile(filename, width, height)
	self:initContext()
	self:loadImage(filename, width, height)
	self:toBlitBuffer()
	self:freeContext()
	return self.bb
end

return Image
<commit_msg>fix memory leak in freeContext<commit_after>--[[
rendering image with mupdf library
--]]

local ffi = require("ffi")
local Blitbuffer = require("ffi/blitbuffer")
local mupdf = ffi.load("libs/libmupdf.so")

require("ffi/mupdf_h")

local Image = {}

function Image:initContext(cache_size)
    -- Remember to change library version when upgrading MuPDF!
    self.context = mupdf.fz_new_context_imp(nil, nil, cache_size or bit.lshift(8, 20), "1.5")
end

function Image:loadImage(filename, width, height)
    local file = io.open(filename)
    if file then
        local data = file:read("*a")
        file:close()
        local image = mupdf.fz_new_image_from_data(self.context,
                        ffi.cast("unsigned char*", data), #data)
        if image ~= nil then
            self.pixmap = mupdf.fz_new_pixmap_from_image(self.context,
                        image, width or -1, height or -1)
            self.image = mupdf.fz_keep_image(self.context, image)
        end
    end
end

function Image:toBlitBuffer()
    local pixmap = ffi.new("fz_pixmap[1]")
    pixmap = self.pixmap
    if self.pixmap.n ~= 2 then
        self.pixmap = mupdf.fz_new_pixmap(self.context, mupdf.fz_device_gray(self.context),
                        pixmap.w, pixmap.h);
        mupdf.fz_convert_pixmap(self.context, self.pixmap, pixmap);
        mupdf.fz_drop_pixmap(self.context, pixmap);
    end
    self.bb = Blitbuffer.new(self.pixmap.w, self.pixmap.h, Blitbuffer.TYPE_BB8A, self.pixmap.samples)
    self.bb:invert() -- our blitbuffers have reversed b->w scale
    self.bb = self.bb:copy() -- we make a copy so mupdf can drop the memory
end

function Image:freeContext()
    if self.image ~= nil then
        mupdf.fz_drop_image(self.context, self.image)
        self.image = nil
    end
    if self.pixmap ~= nil then
        mupdf.fz_drop_pixmap(self.context, self.pixmap)
        self.pixmap = nil
    end
    if self.context ~= nil then
        mupdf.fz_free_context(self.context)
        self.context = nil
    end
end

function Image:fromFile(filename, width, height)
    self:initContext(0)
    self:loadImage(filename, width, height)
    self:toBlitBuffer()
    self:freeContext()
    return self.bb
end

return Image

{'fraction_non_alphanumeric': 0.1113561190738699, 'fraction_numerical': 0.004630650496141125, 'mean_word_length': 3.1012658227848102, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5347992', 'n_tokens_mistral': 1639, 'n_tokens_neox': 1596, 'n_words': 376}