Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions src/lib/openjp2/BufferStream.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright (c) Chris Hafey.
// SPDX-License-Identifier: MIT
#include "BufferStream.h"
#include <string.h>
#include "cio.h"



OPJ_SIZE_T
opj_read_from_buffer (void* pdst, OPJ_SIZE_T len, opj_buffer_info_t* psrc)
{
OPJ_SIZE_T n = (OPJ_SIZE_T) (psrc->buf + psrc->len - psrc->cur);

if (n) {
if (n > len)
n = len;

memcpy (pdst, psrc->cur, n);
psrc->cur += n;
}
else
n = (OPJ_SIZE_T)-1;

return n;
}

OPJ_SIZE_T
opj_write_to_buffer (void* p_buffer, OPJ_SIZE_T p_nb_bytes,
opj_buffer_info_t* p_source_buffer)
{

memcpy (p_source_buffer->cur, p_buffer, p_nb_bytes);
p_source_buffer->cur += p_nb_bytes;

return p_nb_bytes;
}

OPJ_SIZE_T
opj_skip_from_buffer (OPJ_SIZE_T len, opj_buffer_info_t* psrc)
{

OPJ_SIZE_T n = psrc->buf + psrc->len - psrc->cur;


if (n) {
if (n > len)
{
n = len;
}
psrc->cur += len;

}
else
{
n = (OPJ_SIZE_T)-1;
}
return n;
}

OPJ_BOOL
opj_seek_from_buffer (OPJ_OFF_T len, opj_buffer_info_t* psrc)
{
OPJ_SIZE_T n = psrc->len;

if (n > len)
n = len;

psrc->cur = psrc->buf + n;

return OPJ_TRUE;
}

opj_stream_t* OPJ_CALLCONV
opj_stream_create_buffer_stream (opj_buffer_info_t* psrc, OPJ_BOOL input)
{
opj_stream_t* ps;
if (!psrc)
return 0;

ps = opj_stream_default_create (input);

if (0 == ps)
return 0;

opj_stream_set_user_data (ps, psrc, 0);
opj_stream_set_user_data_length (ps, psrc->len);

if (input)
opj_stream_set_read_function (
ps, (opj_stream_read_fn)opj_read_from_buffer);
else
opj_stream_set_write_function(
ps,(opj_stream_write_fn) opj_write_to_buffer);

opj_stream_set_skip_function (
ps, (opj_stream_skip_fn)opj_skip_from_buffer);
opj_stream_set_use_buffered_stream (
ps, OPJ_TRUE);

opj_stream_set_seek_function (
ps, (opj_stream_seek_fn)opj_seek_from_buffer);

return ps;
}
34 changes: 34 additions & 0 deletions src/lib/openjp2/BufferStream.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// Created by skinner on 5/8/25.
//

#pragma once
#include "openjpeg.h"

typedef struct opj_buffer_info {
OPJ_BYTE* buf;
OPJ_BYTE* cur;
OPJ_SIZE_T len;
} opj_buffer_info_t;
#ifdef __cplusplus
extern "C" {
#endif
OPJ_SIZE_T
opj_read_from_buffer (void* pdst, OPJ_SIZE_T len, opj_buffer_info_t* psrc);

OPJ_SIZE_T
opj_write_to_buffer (void* p_buffer, OPJ_SIZE_T p_nb_bytes,
opj_buffer_info_t* p_source_buffer);
OPJ_SIZE_T
opj_skip_from_buffer (OPJ_SIZE_T len, opj_buffer_info_t* psrc);

OPJ_BOOL
opj_seek_from_buffer (OPJ_OFF_T len, opj_buffer_info_t* psrc);

opj_stream_t* OPJ_CALLCONV
opj_stream_create_buffer_stream (opj_buffer_info_t* psrc, OPJ_BOOL input);
void OPJ_CALLCONV opj_stream_set_use_buffered_stream(opj_stream_t* p_stream,
int use_buffered_stream);
#ifdef __cplusplus
}
#endif
2 changes: 2 additions & 0 deletions src/lib/openjp2/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ set(OPENJPEG_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/opj_stdint.h
${CMAKE_CURRENT_SOURCE_DIR}/sparse_array.c
${CMAKE_CURRENT_SOURCE_DIR}/sparse_array.h
${CMAKE_CURRENT_SOURCE_DIR}/BufferStream.c
${CMAKE_CURRENT_SOURCE_DIR}/BufferStream.h
)
if(BUILD_JPIP)
add_definitions(-DUSE_JPIP)
Expand Down
81 changes: 74 additions & 7 deletions src/lib/openjp2/cio.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,72 @@
*/

#include "opj_includes.h"
#include "BufferStream.h"

void OPJ_CALLCONV opj_stream_set_use_buffered_stream(opj_stream_t* p_stream,
OPJ_BOOL use_buffered_stream)
{
opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;

if (! l_stream) {
return;
}
printf("set m_use_buffered_stream to %d\n",use_buffered_stream);
l_stream->m_use_buffered_stream = use_buffered_stream;
}
OPJ_SIZE_T skip_stream(opj_stream_private_t * stream, OPJ_SIZE_T len, opj_buffer_info_t* psrc)
{
OPJ_SIZE_T current;
if (stream->m_use_buffered_stream) {
current = opj_skip_from_buffer(len, psrc);
}
else
{
current = (OPJ_SIZE_T) stream->m_skip_fn((OPJ_OFF_T)len, psrc);
}
return current;
}

OPJ_SIZE_T read_stream(opj_stream_private_t * stream, void* pdst,OPJ_SIZE_T len, opj_buffer_info_t* psrc)
{
OPJ_SIZE_T current;
if (stream->m_use_buffered_stream)
{
current = opj_read_from_buffer(pdst,len,psrc);
}
else
{
current = stream->m_read_fn(pdst, len, psrc);
}
return current;
}
OPJ_SIZE_T write_stream(opj_stream_private_t * stream, void* pbuffer, OPJ_SIZE_T p_nb_bytes,
opj_buffer_info_t* p_source_buffer) {
OPJ_SIZE_T current;
if (stream->m_use_buffered_stream)
{
current = opj_write_to_buffer(pbuffer,p_nb_bytes,
p_source_buffer);
}
else
{
current = stream->m_write_fn(pbuffer,p_nb_bytes,p_source_buffer);
}
return current;
}
OPJ_BOOL seek_stream(opj_stream_private_t * stream, OPJ_OFF_T len,opj_buffer_info_t* psrc)
{
OPJ_BOOL success;
if (stream->m_use_buffered_stream)
{
success = opj_seek_from_buffer(len, psrc);
}
else
{
success = stream->m_seek_fn(len, psrc);
}
return success;
};
/* ----------------------------------------------------------------------- */


Expand Down Expand Up @@ -165,6 +230,8 @@ opj_stream_t* OPJ_CALLCONV opj_stream_create(OPJ_SIZE_T p_buffer_size,
}

l_stream->m_buffer_size = p_buffer_size;
// default the cio to byte-straem mode
l_stream->m_use_buffered_stream = OPJ_TRUE;
l_stream->m_stored_data = (OPJ_BYTE *) opj_malloc(p_buffer_size);
if (! l_stream->m_stored_data) {
opj_free(l_stream);
Expand Down Expand Up @@ -321,7 +388,7 @@ OPJ_SIZE_T opj_stream_read_data(opj_stream_private_t * p_stream,
/* we should read less than a chunk -> read a chunk */
if (p_size < p_stream->m_buffer_size) {
/* we should do an actual read on the media */
p_stream->m_bytes_in_buffer = p_stream->m_read_fn(p_stream->m_stored_data,
p_stream->m_bytes_in_buffer = read_stream(p_stream, p_stream->m_stored_data,
p_stream->m_buffer_size, p_stream->m_user_data);

if (p_stream->m_bytes_in_buffer == (OPJ_SIZE_T) - 1) {
Expand Down Expand Up @@ -351,7 +418,7 @@ OPJ_SIZE_T opj_stream_read_data(opj_stream_private_t * p_stream,
}
} else {
/* direct read on the dest buffer */
p_stream->m_bytes_in_buffer = p_stream->m_read_fn(p_buffer, p_size,
p_stream->m_bytes_in_buffer = read_stream(p_stream, p_buffer, p_size,
p_stream->m_user_data);

if (p_stream->m_bytes_in_buffer == (OPJ_SIZE_T) - 1) {
Expand Down Expand Up @@ -440,7 +507,7 @@ OPJ_BOOL opj_stream_flush(opj_stream_private_t * p_stream,

while (p_stream->m_bytes_in_buffer) {
/* we should do an actual write on the media */
l_current_write_nb_bytes = p_stream->m_write_fn(p_stream->m_current_data,
l_current_write_nb_bytes = write_stream(p_stream, p_stream->m_current_data,
p_stream->m_bytes_in_buffer,
p_stream->m_user_data);

Expand Down Expand Up @@ -517,7 +584,7 @@ OPJ_OFF_T opj_stream_read_skip(opj_stream_private_t * p_stream,
}

/* we should do an actual skip on the media */
l_current_skip_nb_bytes = p_stream->m_skip_fn(p_size, p_stream->m_user_data);
l_current_skip_nb_bytes = skip_stream(p_stream, p_size, p_stream->m_user_data);
if (l_current_skip_nb_bytes == (OPJ_OFF_T) - 1) {
opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n");

Expand Down Expand Up @@ -557,7 +624,7 @@ OPJ_OFF_T opj_stream_write_skip(opj_stream_private_t * p_stream,

while (p_size > 0) {
/* we should do an actual skip on the media */
l_current_skip_nb_bytes = p_stream->m_skip_fn(p_size, p_stream->m_user_data);
l_current_skip_nb_bytes = skip_stream(p_stream, p_size, p_stream->m_user_data);

if (l_current_skip_nb_bytes == (OPJ_OFF_T) - 1) {
opj_event_msg(p_event_mgr, EVT_INFO, "Stream error!\n");
Expand Down Expand Up @@ -604,7 +671,7 @@ OPJ_BOOL opj_stream_read_seek(opj_stream_private_t * p_stream, OPJ_OFF_T p_size,
p_stream->m_current_data = p_stream->m_stored_data;
p_stream->m_bytes_in_buffer = 0;

if (!(p_stream->m_seek_fn(p_size, p_stream->m_user_data))) {
if (!(seek_stream(p_stream, p_size, p_stream->m_user_data))) {
p_stream->m_status |= OPJ_STREAM_STATUS_END;
return OPJ_FALSE;
} else {
Expand All @@ -628,7 +695,7 @@ OPJ_BOOL opj_stream_write_seek(opj_stream_private_t * p_stream,
p_stream->m_current_data = p_stream->m_stored_data;
p_stream->m_bytes_in_buffer = 0;

if (! p_stream->m_seek_fn(p_size, p_stream->m_user_data)) {
if (! seek_stream(p_stream, p_size, p_stream->m_user_data)) {
p_stream->m_status |= OPJ_STREAM_STATUS_ERROR;
return OPJ_FALSE;
} else {
Expand Down
24 changes: 24 additions & 0 deletions src/lib/openjp2/cio.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ The functions in CIO.C have for goal to realize a byte input / output process.
/*@{*/

#include "opj_config_private.h"
#include "BufferStream.h"

/* ----------------------------------------------------------------------- */

Expand Down Expand Up @@ -160,6 +161,12 @@ typedef struct opj_stream_private {
* Used with OPJ_STREAM_STATUS_* defines.
*/
OPJ_UINT32 m_status;
/**
for wasm, don't store function pointer, rather than
function pointer.
*/

OPJ_BOOL m_use_buffered_stream;

}
opj_stream_private_t;
Expand Down Expand Up @@ -397,11 +404,28 @@ OPJ_SIZE_T opj_stream_default_write(void * p_buffer, OPJ_SIZE_T p_nb_bytes,
*/
OPJ_OFF_T opj_stream_default_skip(OPJ_OFF_T p_nb_bytes, void * p_user_data);

void OPJ_CALLCONV opj_stream_set_use_buffered_stream(opj_stream_t* p_stream,
OPJ_BOOL use_buffered_stream);
/**
* FIXME DOC.
*/
OPJ_BOOL opj_stream_default_seek(OPJ_OFF_T p_nb_bytes, void * p_user_data);
/**
* The skip, read, write, and seek operations on the input stream
* are abstracted within the following skip/read/write/seek_stream functions.
* The use of pointer functions were used earlier, but when compiling to
* web-assembly, the pointer functions did not work. The web-assembly code
* is used only with buffers to date. Therefore within these 4 functions,
* the explicit call to the buffer type stream is performed when m_use_buffered_stream
* is true. Otherwise the pointer functions are used, and the option to
* introduce other types of streams beyond file streams remains.
*/

OPJ_SIZE_T skip_stream(opj_stream_private_t * stream,OPJ_SIZE_T len, opj_buffer_info_t* psrc);
OPJ_SIZE_T read_stream(opj_stream_private_t * stream, void* pcst,OPJ_SIZE_T len, opj_buffer_info_t* psrc);
OPJ_SIZE_T write_stream(opj_stream_private_t * stream, void* pbuffer, OPJ_SIZE_T p_nb_bytes,
opj_buffer_info_t* p_source_buffer);
OPJ_BOOL seek_stream(opj_stream_private_t * stream, OPJ_OFF_T len,opj_buffer_info_t* psrc);
/* ----------------------------------------------------------------------- */
/*@}*/

Expand Down