added support for compress/decompress from buffer/memory mapped file
This commit is contained in:
parent
51efe91971
commit
f32c5e7164
|
@ -1177,6 +1177,8 @@ static opj_image_t* upsample_image_components(opj_image_t* original)
|
|||
* OPJ_DECOMPRESS MAIN
|
||||
*/
|
||||
/* -------------------------------------------------------------------------- */
|
||||
OPJ_BOOL debug_buffers = OPJ_FALSE;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
opj_decompress_parameters parameters; /* decompression parameters */
|
||||
|
@ -1236,13 +1238,13 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
/*Decoding image one by one*/
|
||||
for(imageno = 0; imageno < num_images ; imageno++) {
|
||||
for (imageno = 0; imageno < num_images; imageno++) {
|
||||
|
||||
fprintf(stderr,"\n");
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
if(img_fol.set_imgdir==1){
|
||||
if (get_next_file(imageno, dirptr,&img_fol, ¶meters)) {
|
||||
fprintf(stderr,"skipping file...\n");
|
||||
if (img_fol.set_imgdir == 1) {
|
||||
if (get_next_file(imageno, dirptr, &img_fol, ¶meters)) {
|
||||
fprintf(stderr, "skipping file...\n");
|
||||
destroy_parameters(¶meters);
|
||||
continue;
|
||||
}
|
||||
|
@ -1250,8 +1252,33 @@ int main(int argc, char **argv)
|
|||
|
||||
/* read the input file and put it in memory */
|
||||
/* ---------------------------------------- */
|
||||
if (debug_buffers) {
|
||||
FILE* p_file = NULL;
|
||||
OPJ_SIZE_T sz = 0;
|
||||
OPJ_BYTE* buffer = NULL;
|
||||
|
||||
p_file = fopen(parameters.infile, "rb");
|
||||
if (p_file) {
|
||||
fseek(p_file, 0L, SEEK_END);
|
||||
sz = ftell(p_file);
|
||||
fseek(p_file, 0L, SEEK_SET);
|
||||
buffer = (OPJ_BYTE*)malloc(sz);
|
||||
if (buffer) {
|
||||
int res = 0;
|
||||
res = fread(buffer, 1, sz, p_file);
|
||||
if (res) {
|
||||
fclose(p_file);
|
||||
l_stream = opj_stream_create_buffer_stream(buffer, sz, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!l_stream) {
|
||||
l_stream = opj_stream_create_mapped_file_stream(parameters.infile, OPJ_J2K_STREAM_CHUNK_SIZE, OPJ_TRUE);
|
||||
//l_stream = opj_stream_create_default_file_stream(parameters.infile, 1);
|
||||
}
|
||||
|
||||
l_stream = opj_stream_create_default_file_stream(parameters.infile,1);
|
||||
if (!l_stream){
|
||||
fprintf(stderr, "ERROR -> failed to create the stream from the file %s\n", parameters.infile);
|
||||
destroy_parameters(¶meters);
|
||||
|
|
|
@ -33,7 +33,19 @@
|
|||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif /* _WIN32 */
|
||||
#else /* _WIN32 */
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
# include <unistd.h>
|
||||
# include <sys/mman.h>
|
||||
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "opj_includes.h"
|
||||
|
||||
|
@ -129,6 +141,87 @@ static OPJ_BOOL opj_seek_from_file (OPJ_OFF_T p_nb_bytes, FILE * p_user_data)
|
|||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef void* opj_handle_t;
|
||||
#else
|
||||
typedef OPJ_INT32 opj_handle_t;
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct opj_buffer_info
|
||||
{
|
||||
OPJ_BYTE *buf;
|
||||
OPJ_OFF_T off;
|
||||
OPJ_SIZE_T len;
|
||||
opj_handle_t fd; // for file mapping
|
||||
} opj_buffer_info_t;
|
||||
|
||||
static void opj_free_buffer_info(void* user_data) {
|
||||
if (user_data)
|
||||
opj_free(user_data);
|
||||
}
|
||||
|
||||
static OPJ_SIZE_T opj_read_from_buffer(void * p_buffer,
|
||||
OPJ_SIZE_T p_nb_bytes,
|
||||
opj_buffer_info_t* p_source_buffer)
|
||||
{
|
||||
OPJ_SIZE_T l_nb_read;
|
||||
|
||||
if (p_source_buffer->off + p_nb_bytes < p_source_buffer->len)
|
||||
{
|
||||
l_nb_read = p_nb_bytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
l_nb_read = (OPJ_SIZE_T)(p_source_buffer->len - p_source_buffer->off);
|
||||
}
|
||||
memcpy(p_buffer, p_source_buffer->buf + p_source_buffer->off, l_nb_read);
|
||||
p_source_buffer->off += l_nb_read;
|
||||
|
||||
return l_nb_read ? l_nb_read : ((OPJ_SIZE_T)-1);
|
||||
}
|
||||
|
||||
static OPJ_SIZE_T opj_write_from_buffer(void * p_buffer,
|
||||
OPJ_SIZE_T p_nb_bytes,
|
||||
opj_buffer_info_t* p_source_buffer)
|
||||
{
|
||||
memcpy(p_source_buffer->buf + p_source_buffer->off, p_buffer, p_nb_bytes);
|
||||
p_source_buffer->off += p_nb_bytes;
|
||||
p_source_buffer->len += p_nb_bytes;
|
||||
|
||||
return p_nb_bytes;
|
||||
}
|
||||
|
||||
static OPJ_OFF_T opj_skip_from_buffer(OPJ_OFF_T p_nb_bytes,
|
||||
opj_buffer_info_t * p_source_buffer)
|
||||
{
|
||||
if (p_source_buffer->off + p_nb_bytes < p_source_buffer->len) {
|
||||
p_source_buffer->off += p_nb_bytes;
|
||||
}
|
||||
else {
|
||||
p_source_buffer->off = p_source_buffer->len;
|
||||
}
|
||||
return p_nb_bytes;
|
||||
}
|
||||
|
||||
static OPJ_BOOL opj_seek_from_buffer(OPJ_OFF_T p_nb_bytes,
|
||||
opj_buffer_info_t * p_source_buffer)
|
||||
{
|
||||
if (p_nb_bytes < p_source_buffer->len)
|
||||
{
|
||||
p_source_buffer->off = p_nb_bytes;
|
||||
}
|
||||
else {
|
||||
p_source_buffer->off = p_source_buffer->len;
|
||||
}
|
||||
return OPJ_TRUE;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef OPJ_STATIC
|
||||
BOOL APIENTRY
|
||||
|
@ -917,6 +1010,8 @@ void OPJ_CALLCONV opj_destroy_cstr_index(opj_codestream_index_t **p_cstr_index)
|
|||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
opj_stream_t* OPJ_CALLCONV opj_stream_create_default_file_stream (const char *fname, OPJ_BOOL p_is_read_stream)
|
||||
{
|
||||
return opj_stream_create_file_stream(fname, OPJ_J2K_STREAM_CHUNK_SIZE, p_is_read_stream);
|
||||
|
@ -958,3 +1053,265 @@ opj_stream_t* OPJ_CALLCONV opj_stream_create_file_stream (
|
|||
|
||||
return l_stream;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
OPJ_INT32 opj_get_file_open_mode(const char* mode)
|
||||
{
|
||||
OPJ_INT32 m = -1;
|
||||
switch (mode[0]) {
|
||||
case 'r':
|
||||
m = O_RDONLY;
|
||||
if (mode[1] == '+')
|
||||
m = O_RDWR;
|
||||
break;
|
||||
case 'w':
|
||||
case 'a':
|
||||
m = O_RDWR | O_CREAT;
|
||||
if (mode[0] == 'w')
|
||||
m |= O_TRUNC;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static OPJ_UINT64 opj_size_proc(opj_handle_t fd)
|
||||
{
|
||||
ULARGE_INTEGER m;
|
||||
m.LowPart = GetFileSize(fd, &m.HighPart);
|
||||
return(m.QuadPart);
|
||||
}
|
||||
|
||||
|
||||
static void* opj_map(opj_handle_t fd, OPJ_SIZE_T len) {
|
||||
void* ptr = NULL;
|
||||
HANDLE hMapFile = NULL;
|
||||
|
||||
if (!fd || !len)
|
||||
return NULL;
|
||||
|
||||
/* Passing in 0 for the maximum file size indicates that we
|
||||
would like to create a file mapping object for the full file size */
|
||||
hMapFile = CreateFileMapping(fd, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
if (hMapFile == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ptr = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
|
||||
CloseHandle(hMapFile);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static OPJ_INT32 opj_unmap(void* ptr, OPJ_SIZE_T len){
|
||||
OPJ_INT32 rc = -1;
|
||||
if (ptr)
|
||||
rc = UnmapViewOfFile(ptr) ? 0 : -1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static opj_handle_t opj_open_fd(const char* fname, const char* mode) {
|
||||
void* fd = NULL;
|
||||
OPJ_INT32 m = -1;
|
||||
DWORD dwMode = 0;
|
||||
|
||||
if (!fname)
|
||||
return (void*)-1;
|
||||
|
||||
|
||||
m = opj_get_file_open_mode(mode);
|
||||
switch (m) {
|
||||
case O_RDONLY:
|
||||
dwMode = OPEN_EXISTING;
|
||||
break;
|
||||
case O_RDWR:
|
||||
dwMode = OPEN_ALWAYS;
|
||||
break;
|
||||
case O_RDWR | O_CREAT:
|
||||
dwMode = OPEN_ALWAYS;
|
||||
break;
|
||||
case O_RDWR | O_TRUNC:
|
||||
dwMode = CREATE_ALWAYS;
|
||||
break;
|
||||
case O_RDWR | O_CREAT | O_TRUNC:
|
||||
dwMode = CREATE_ALWAYS;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fd = (opj_handle_t)CreateFileA(fname,
|
||||
(m == O_RDONLY) ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE),
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwMode,
|
||||
(m == O_RDONLY) ? FILE_ATTRIBUTE_READONLY : FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if (fd == INVALID_HANDLE_VALUE) {
|
||||
return (opj_handle_t)-1;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
static OPJ_INT32 opj_close_fd(opj_handle_t fd) {
|
||||
OPJ_INT32 rc = -1;
|
||||
if (fd) {
|
||||
rc = CloseHandle(fd) ? 0 : -1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static OPJ_UINT64 opj_size_proc(opj_handle_t fd)
|
||||
{
|
||||
struct stat sb;
|
||||
if (!fd)
|
||||
return 0;
|
||||
|
||||
if (fstat(fd, &sb)<0)
|
||||
return(0);
|
||||
else
|
||||
return((OPJ_UINT64)sb.st_size);
|
||||
}
|
||||
|
||||
static void* opj_map(opj_handle_t fd, OPJ_SIZE_T len) {
|
||||
void* ptr = NULL;
|
||||
OPJ_UINT64 size64 = 0;
|
||||
|
||||
if (!fd)
|
||||
return NULL;
|
||||
|
||||
size64 = opj_size_proc(fd);
|
||||
ptr = (void*)mmap(0, (size_t)size64, PROT_READ, MAP_SHARED, fd, 0);
|
||||
return ptr == (void*)-1 ? NULL : ptr;
|
||||
}
|
||||
|
||||
static OPJ_INT32 opj_unmap(void* ptr, OPJ_SIZE_T len) {
|
||||
// unmap
|
||||
if (ptr)
|
||||
munmap(ptr, (off_t)len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static opj_handle_t opj_open_fd(const char* fname, const char* mode) {
|
||||
opj_handle_t fd = 0;
|
||||
OPJ_INT32 m = -1;
|
||||
if (!fname) {
|
||||
return -1;
|
||||
}
|
||||
m = opj_get_file_open_mode(mode);
|
||||
fd = open(fname, m, 0666);
|
||||
if (fd < 0) {
|
||||
if (errno > 0 && strerror(errno) != NULL) {
|
||||
printf("%s: %s", fname, strerror(errno));
|
||||
}
|
||||
else {
|
||||
printf("%s: Cannot open", fname);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
static OPJ_INT32 opj_close_fd(opj_handle_t fd) {
|
||||
if (!fd)
|
||||
return 0;
|
||||
return (close(fd));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static void opj_memory_map_cleanup(void* user_data) {
|
||||
if (user_data) {
|
||||
opj_buffer_info_t* buffer_info = (opj_buffer_info_t*)user_data;
|
||||
opj_unmap(buffer_info->buf, buffer_info->len);
|
||||
opj_close_fd(buffer_info->fd);
|
||||
opj_free(buffer_info);
|
||||
}
|
||||
}
|
||||
|
||||
opj_stream_t* OPJ_CALLCONV opj_stream_create_mapped_file_stream(const char *fname,
|
||||
OPJ_SIZE_T p_size,
|
||||
OPJ_BOOL p_is_read_stream)
|
||||
{
|
||||
opj_stream_t* l_stream = NULL;
|
||||
opj_buffer_info_t* buffer_info = NULL;
|
||||
void* mapped_view = NULL;
|
||||
|
||||
opj_handle_t fd = opj_open_fd(fname, p_is_read_stream ? "r" : "w");
|
||||
if (fd == (opj_handle_t)-1)
|
||||
return NULL;
|
||||
|
||||
buffer_info = (opj_buffer_info_t*)opj_malloc(sizeof(opj_buffer_info_t));
|
||||
memset(buffer_info, 0, sizeof(opj_buffer_info_t));
|
||||
buffer_info->fd = fd;
|
||||
buffer_info->len = (OPJ_SIZE_T)opj_size_proc(fd);
|
||||
|
||||
l_stream = opj_stream_create(p_size, p_is_read_stream);
|
||||
if (!l_stream) {
|
||||
opj_memory_map_cleanup(buffer_info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mapped_view = opj_map(fd, buffer_info->len);
|
||||
if (mapped_view == NULL) {
|
||||
opj_memory_map_cleanup(buffer_info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer_info->buf = mapped_view;
|
||||
buffer_info->off = 0;
|
||||
|
||||
opj_stream_set_user_data(l_stream, buffer_info, (opj_stream_free_user_data_fn)opj_memory_map_cleanup);
|
||||
opj_stream_set_user_data_length(l_stream, buffer_info->len);
|
||||
|
||||
if (p_is_read_stream)
|
||||
opj_stream_set_read_function(l_stream, (opj_stream_read_fn)opj_read_from_buffer);
|
||||
else
|
||||
opj_stream_set_write_function(l_stream, (opj_stream_write_fn)opj_write_from_buffer);
|
||||
opj_stream_set_skip_function(l_stream, (opj_stream_skip_fn)opj_skip_from_buffer);
|
||||
opj_stream_set_seek_function(l_stream, (opj_stream_seek_fn)opj_seek_from_buffer);
|
||||
|
||||
return l_stream;
|
||||
}
|
||||
|
||||
|
||||
opj_stream_t* OPJ_CALLCONV opj_stream_create_buffer_stream(OPJ_BYTE *buf,
|
||||
OPJ_SIZE_T len,
|
||||
OPJ_BOOL p_is_read_stream)
|
||||
{
|
||||
opj_stream_t* l_stream = NULL;
|
||||
opj_buffer_info_t* p_source_buffer = NULL;
|
||||
|
||||
if (!buf || !len) return NULL;
|
||||
|
||||
l_stream = opj_stream_default_create(p_is_read_stream);
|
||||
|
||||
if (!l_stream) return NULL;
|
||||
|
||||
p_source_buffer = (opj_buffer_info_t*)opj_malloc(sizeof(opj_buffer_info_t));
|
||||
if (!p_source_buffer)
|
||||
return NULL;
|
||||
|
||||
memset(p_source_buffer, 0, sizeof(opj_buffer_info_t));
|
||||
p_source_buffer->buf = buf;
|
||||
p_source_buffer->off = 0;
|
||||
p_source_buffer->len = len;
|
||||
|
||||
opj_stream_set_user_data(l_stream, p_source_buffer, opj_free_buffer_info);
|
||||
opj_stream_set_user_data_length(l_stream, p_source_buffer->len);
|
||||
|
||||
if (p_is_read_stream)
|
||||
opj_stream_set_read_function(l_stream, (opj_stream_read_fn)opj_read_from_buffer);
|
||||
else
|
||||
opj_stream_set_write_function(l_stream, (opj_stream_write_fn)opj_write_from_buffer);
|
||||
opj_stream_set_skip_function(l_stream, (opj_stream_skip_fn)opj_skip_from_buffer);
|
||||
opj_stream_set_seek_function(l_stream, (opj_stream_seek_fn)opj_seek_from_buffer);
|
||||
|
||||
return l_stream;
|
||||
}
|
||||
|
||||
|
|
|
@ -568,6 +568,7 @@ typedef struct opj_dparameters {
|
|||
} opj_dparameters_t;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* JPEG2000 codec V2.
|
||||
* */
|
||||
|
@ -1180,6 +1181,13 @@ OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_create_default_file_stream (const
|
|||
OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_create_file_stream (const char *fname,
|
||||
OPJ_SIZE_T p_buffer_size,
|
||||
OPJ_BOOL p_is_read_stream);
|
||||
OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_create_buffer_stream(OPJ_BYTE *buf,
|
||||
OPJ_SIZE_T len,
|
||||
OPJ_BOOL p_is_read_stream);
|
||||
|
||||
OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_create_mapped_file_stream(const char *fname,
|
||||
OPJ_SIZE_T p_size,
|
||||
OPJ_BOOL p_is_read_stream);
|
||||
|
||||
/*
|
||||
==========================================================
|
||||
|
|
Loading…
Reference in New Issue