提交 5d7e2614 authored 作者: Steve Underwood's avatar Steve Underwood

Introducing T.85 encode and decodei to spandsp. This is not connected into the…

Introducing T.85 encode and decodei to spandsp. This is not connected into the FAX engine in this update.
上级 287678bc
......@@ -153,6 +153,9 @@ libspandsp_la_SOURCES = ademco_contactid.c \
t38_core.c \
t38_gateway.c \
t38_non_ecm_buffer.c \
t81_t82_arith_coding.c \
t85_decode.c \
t85_encode.c \
t38_terminal.c \
testcpuid.c \
time_scale.c \
......@@ -241,6 +244,8 @@ nobase_include_HEADERS = spandsp/ademco_contactid.h \
spandsp/t4_tx.h \
spandsp/t4_t6_decode.h \
spandsp/t4_t6_encode.h \
spandsp/t81_t82_arith_coding.h \
spandsp/t85.h \
spandsp/telephony.h \
spandsp/time_scale.h \
spandsp/timezone.h \
......@@ -305,6 +310,8 @@ nobase_include_HEADERS = spandsp/ademco_contactid.h \
spandsp/private/t4_tx.h \
spandsp/private/t4_t6_decode.h \
spandsp/private/t4_t6_encode.h \
spandsp/private/t81_t82_arith_coding.h \
spandsp/private/t85.h \
spandsp/private/time_scale.h \
spandsp/private/timezone.h \
spandsp/private/tone_detect.h \
......
......@@ -108,8 +108,8 @@
#include <spandsp/image_translate.h>
#include <spandsp/t4_t6_decode.h>
#include <spandsp/t4_t6_encode.h>
/*#include <spandsp/t81_t82_arith_coding.h>*/
/*#include <spandsp/t85.h>*/
#include <spandsp/t81_t82_arith_coding.h>
#include <spandsp/t85.h>
/*#include <spandsp/t42.h>*/
/*#include <spandsp/t43.h>*/
#include <spandsp/t30.h>
......
......@@ -78,8 +78,8 @@
#include <spandsp/private/image_translate.h>
#include <spandsp/private/t4_t6_decode.h>
#include <spandsp/private/t4_t6_encode.h>
/*#include <spandsp/private/t81_t82_arith_coding.h>*/
/*#include <spandsp/private/t85.h>*/
#include <spandsp/private/t81_t82_arith_coding.h>
#include <spandsp/private/t85.h>
/*#include <spandsp/private/t42.h>*/
/*#include <spandsp/private/t43.h>*/
#include <spandsp/private/t4_rx.h>
......
/*
* SpanDSP - a series of DSP components for telephony
*
* t81_t82_arith_coding.h - ITU T.81 and T.82 QM-coder arithmetic encoding
* and decoding
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2009 Steve Underwood
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*! \file */
#if !defined(_SPANDSP_PRIVATE_T81_T82_ARITH_CODING_H_)
#define _SPANDSP_PRIVATE_T81_T82_ARITH_CODING_H_
/* State of a working instance of the QM-coder arithmetic encoder */
struct t81_t82_arith_encode_state_s
{
/*! A register - see T.82 Table 23 */
uint32_t a;
/*! C register - see T.82 Table 23 */
uint32_t c;
/*! Probability status for contexts. MSB = MPS */
uint8_t st[4096];
/*! Number of buffered 0xFF values that might still overflow */
int32_t sc;
/*! Bit shift counter. This determines when the next byte will be written */
int ct;
/*! Buffer for the most recent output byte which is not 0xFF */
int buffer;
/*! Callback function to deliver the encoded data, byte by byte */
void (*output_byte_handler)(void *, int);
/*! Opaque pointer passed to byte_out */
void *user_data;
};
/* State of a working instance of the QM-coder arithmetic decoder */
struct t81_t82_arith_decode_state_s
{
/*! A register - see T.82 Table 25 */
uint32_t a;
/*! C register - see T.82 Table 25 */
uint32_t c;
/*! Probability status for contexts. MSB = MPS */
uint8_t st[4096];
/*! Bit-shift counter. Determines when next byte will be read.
Special value -1 signals that zero-padding has started */
int ct;
/*! Pointer to next PSCD data byte */
const uint8_t *pscd_ptr;
/*! Pointer to byte after PSCD */
const uint8_t *pscd_end;
/*! Boolean flag that controls initial fill of s->c */
int startup;
/*! Boolean flag that triggers return -2 between reaching PSCD end
and decoding the first symbol that might never have been encoded
in the first place */
int nopadding;
};
#endif
/*- End of file ------------------------------------------------------------*/
/*
* SpanDSP - a series of DSP components for telephony
*
* private/t85.h - ITU T.85 JBIG for FAX image processing
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2008, 2009 Steve Underwood
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(_SPANDSP_PRIVATE_T85_H_)
#define _SPANDSP_PRIVATE_T85_H_
/* Maximum number of ATMOVEs per stripe that the decoder can handle */
#define T85_ATMOVES_MAX 1
/* TP special pixels */
#define TPB2CX 0x195
#define TPB3CX 0x0E5
/* T.82 table 2 - symbolic constants */
enum
{
T82_STUFF = 0x00,
T82_RESERVE = 0x01,
T82_SDNORM = 0x02,
T82_SDRST = 0x03,
T82_ABORT = 0x04,
T82_NEWLEN = 0x05,
T82_ATMOVE = 0x06,
T82_COMMENT = 0x07,
T82_ESC = 0xFF
};
/* State of a working instance of the T.85 JBIG FAX encoder */
struct t85_encode_state_s
{
/*! \brief Callback function to read a row of pixels from the image source. */
t4_row_read_handler_t row_read_handler;
/*! \brief Opaque pointer passed to row_read_handler. */
void *row_read_user_data;
/*! The number of bit planes. Always 1 for true T.85 */
uint8_t bit_planes;
uint8_t current_bit_plane;
/*! The width of the full image, in pixels */
uint32_t xd;
/*! The height of the full image, in pixels */
uint32_t yd;
/*! Then number of rows per stripe */
uint32_t l0;
/*! Maximum ATMOVE window size (0 - 127) */
int mx;
/*! Encoding parameters */
int options;
/*! The contents for a COMMENT marker segment, to be added to the
image at the next opportunity. This is set to NULL when nothing is
pending. */
const uint8_t *comment;
/*! Length of data pointed to by comment */
size_t comment_len;
/*! Next row number to be encoded */
uint32_t y;
/*! Next row within current stripe */
uint32_t i;
/*! Flag for handling NEWLEN processing. */
int newlen;
/*! X-offset of adaptive template pixel */
int32_t tx;
/*! Adaptive template algorithm variables */
uint32_t c_all;
/*! Adaptive template algorithm variables */
uint32_t c[128];
/*! New TX value, or <0 for analysis in progress */
int32_t new_tx;
/*! TRUE if previous row was typical */
int prev_ltp;
/*! Pointers to the 3 row buffers */
uint8_t *prev_row[3];
/*! Pointer to a block of allocated memory 3 rows long, which
we divide up for the 3 row buffers. */
uint8_t *row_buf;
uint8_t *bitstream;
int bitstream_len;
int bitstream_iptr;
int bitstream_optr;
int fill_with_white;
/*! \brief The size of the compressed image, in bytes. */
int compressed_image_size;
/*! Arithmetic encoder state */
t81_t82_arith_encode_state_t s;
/*! \brief Error and flow logging control */
logging_state_t logging;
};
/* State of a working instance of the T.85 JBIG FAX decoder */
struct t85_decode_state_s
{
/*! A callback routine to handle decoded pixel rows */
t4_row_write_handler_t row_write_handler;
/*! An opaque pointer passed to row_write_handler() */
void *row_write_user_data;
/*! A callback routine to handle decoded comments */
t4_row_write_handler_t comment_handler;
/*! An opaque pointer passed to comment_handler() */
void *comment_user_data;
uint8_t min_bit_planes;
uint8_t max_bit_planes;
/*! The maximum length of comment to be passed to the comment handler */
uint32_t max_comment_len;
/*! The maximum permitted width of the full image, in pixels */
uint32_t max_xd;
/*! The maximum permitted height of the full image, in pixels */
uint32_t max_yd;
/*! The number of bit planes expected, according to the header. Always 1 for true T.85 */
uint8_t bit_planes;
uint8_t current_bit_plane;
/*! The width of the full image, in pixels */
uint32_t xd;
/*! The height of the full image, in pixels */
uint32_t yd;
/*! The number of rows per stripe */
uint32_t l0;
/*! Maximum ATMOVE window size */
int mx;
/*! Encoding parameters */
int options;
/*! The current row and the previous 2 rows of image data */
int p[3];
/*! Pointers to the 3 row buffers */
uint8_t *prev_row[3];
/*! Pointer to a block of allocated memory 3 rows long, which
we divide up for the 3 row buffers. */
uint8_t *row_buf;
/*! The length of the row buffer */
int row_buf_len;
/*! Bytes per pixel row */
size_t bytes_per_row;
/*! X-offset of AT pixel */
int32_t tx;
/*! Number of bytes read so far */
uint32_t bie_len;
/*! Buffer space for the BIH or marker segments fragments */
uint8_t buffer[20];
/*! Number of bytes in buffer. */
int buf_len;
/*! Required number of bytes in buffer to proceed with processing
its contents. */
int buf_needed;
/*! The content of a decoded COMMENT marker segment. */
uint8_t *comment;
/*! The expected length of a decoded COMMENT segment */
uint32_t comment_len;
/*! The length of COMMENT decoded to date */
uint32_t comment_progress;
/*! Current column */
uint32_t x;
/*! Current row */
uint32_t y;
/*! Current row within the current stripe */
uint32_t i;
/*! Number of AT moves in the current stripe */
int at_moves;
/*! Rows at which an AT move will happen */
uint32_t at_row[T85_ATMOVES_MAX];
/*! ATMOVE x-offsets in current stripe */
int at_tx[T85_ATMOVES_MAX];
/*! Working data for decode_pscd() */
uint32_t row_h[3];
/*! Flag for TPBON/TPDON: next pixel is a pseudo pixel */
int pseudo;
/*! Line is not typical flag. */
int lntp;
/*! Flag that row_write_handler() requested an interrupt. */
int interrupt;
/*! Flag that the data to be decoded has run out. */
int end_of_data;
/*! Arithmetic decoder state */
t81_t82_arith_decode_state_t s;
/*! \brief The size of the compressed image, in bytes. */
int compressed_image_size;
/*! \brief Error and flow logging control */
logging_state_t logging;
};
#endif
/*- End of file ------------------------------------------------------------*/
/*
* SpanDSP - a series of DSP components for telephony
*
* t81_t82_arith_coding.h - ITU T.81 and T.82 QM-coder arithmetic encoding
* and decoding
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2009 Steve Underwood
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*! \file */
#if !defined(_SPANDSP_T81_T82_ARITH_CODING_H_)
#define _SPANDSP_T81_T82_ARITH_CODING_H_
/*! \page t81_t82_arith_coding_page T.81 and T.82 QM-coder arithmetic encoding and decoding
\section t81_t82_arith_coding_page_sec_1 What does it do?
A similar arithmetic coder, called the QM-coder, is used by several image compression
schemes. These routines implement this coder in a (hopefully) reusable way.
\section t81_t82_arith_coding_page_sec_1 How does it work?
*/
/* State of a working instance of the arithmetic encoder */
typedef struct t81_t82_arith_encode_state_s t81_t82_arith_encode_state_t;
/* State of a working instance of the arithmetic decoder */
typedef struct t81_t82_arith_decode_state_s t81_t82_arith_decode_state_t;
#if defined(__cplusplus)
extern "C"
{
#endif
SPAN_DECLARE(t81_t82_arith_encode_state_t *) t81_t82_arith_encode_init(t81_t82_arith_encode_state_t *s,
void (*output_byte_handler)(void *, int),
void *user_data);
SPAN_DECLARE(int) t81_t82_arith_encode_restart(t81_t82_arith_encode_state_t *s, int reuse_st);
SPAN_DECLARE(int) t81_t82_arith_encode_release(t81_t82_arith_encode_state_t *s);
SPAN_DECLARE(int) t81_t82_arith_encode_free(t81_t82_arith_encode_state_t *s);
SPAN_DECLARE(void) t81_t82_arith_encode(t81_t82_arith_encode_state_t *s, int cx, int pix);
SPAN_DECLARE(void) t81_t82_arith_encode_flush(t81_t82_arith_encode_state_t *s);
SPAN_DECLARE(t81_t82_arith_decode_state_t *) t81_t82_arith_decode_init(t81_t82_arith_decode_state_t *s);
SPAN_DECLARE(int) t81_t82_arith_decode_restart(t81_t82_arith_decode_state_t *s, int reuse_st);
SPAN_DECLARE(int) t81_t82_arith_decode_release(t81_t82_arith_decode_state_t *s);
SPAN_DECLARE(int) t81_t82_arith_decode_free(t81_t82_arith_decode_state_t *s);
SPAN_DECLARE(int) t81_t82_arith_decode(t81_t82_arith_decode_state_t *s, int cx);
#if defined(__cplusplus)
}
#endif
#endif
/*- End of file ------------------------------------------------------------*/
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
......@@ -109,6 +109,8 @@ noinst_PROGRAMS = ademco_contactid_tests \
t38_decode \
t38_non_ecm_buffer_tests \
t4_tests \
t81_t82_arith_coding_tests \
t85_tests \
time_scale_tests \
timezone_tests \
tone_detect_tests \
......@@ -312,6 +314,12 @@ t38_non_ecm_buffer_tests_LDADD = $(LIBDIR) -lspandsp
t4_tests_SOURCES = t4_tests.c
t4_tests_LDADD = $(LIBDIR) -lspandsp
t81_t82_arith_coding_tests_SOURCES = t81_t82_arith_coding_tests.c
t81_t82_arith_coding_tests_LDADD = $(LIBDIR) -lspandsp
t85_tests_SOURCES = t85_tests.c
t85_tests_LDADD = $(LIBDIR) -lspandsp
time_scale_tests_SOURCES = time_scale_tests.c
time_scale_tests_LDADD = $(LIBDIR) -lspandsp
......
/*
* SpanDSP - a series of DSP components for telephony
*
* t81_t82_arith_coding_tests.c - Tests for the ITU T.81 and T.82 arithmetic
* encoder/decoder, based on the test description
* in T.82
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2009 Steve Underwood
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*! \file */
/*! \page t81_t82_arith_coding_tests_page T.81 and T.82 Arithmetic encoder/decoder tests
\section t81_t82_arith_coding_tests_pagesec_1 What does it do
These tests exercise the arithmetic encoder and decoder for T.81 and T.82. As T.85 is based
on T.82, this is also the arithmetic coder for T.85.
These tests are based on T.82 section 7. Nothing beyond the prescibed tests is performed at
the present time.
*/
#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
//#if defined(WITH_SPANDSP_INTERNALS)
#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
//#endif
#include "spandsp.h"
#define MSG_SIZE 10000
#define FALSE 0
#define TRUE (!FALSE)
uint8_t msg[MSG_SIZE];
int32_t msg_len;
static void write_byte(void *user_data, int byte)
{
if (msg_len < MSG_SIZE)
msg[msg_len++] = byte;
}
/*- End of function --------------------------------------------------------*/
int main(int argc, char *argv[])
{
t81_t82_arith_encode_state_t *se;
t81_t82_arith_decode_state_t *sd;
int i;
int j;
int test_failed;
int pix;
const uint8_t *pp;
/* Test data from T.82 7.1 */
static const uint16_t pix_7_1[16] =
{
0x05E0, 0x0000, 0x8B00, 0x01C4, 0x1700, 0x0034, 0x7FFF, 0x1A3F,
0x951B, 0x05D8, 0x1D17, 0xE770, 0x0000, 0x0000, 0x0656, 0x0E6A
};
/* Test data from T.82 7.1 */
static const uint16_t cx_7_1[16] =
{
0x0FE0, 0x0000, 0x0F00, 0x00F0, 0xFF00, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
};
/* Test data from T.82 7.1 - scd with stuffing and SDNORM termination */
static const uint8_t sde_7_1[32] =
{
0x69, 0x89, 0x99, 0x5C, 0x32, 0xEA, 0xFA, 0xA0,
0xD5, 0xFF, 0x00, 0x52, 0x7F, 0xFF, 0x00, 0xFF,
0x00, 0xFF, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x3F,
0xFF, 0x00, 0x2D, 0x20, 0x82, 0x91, 0xFF, 0x02
};
#define SDE_7_1_LEN 30 /* Don't include the termination SDNORM */
#define SDE_7_1_FULL_LEN 32 /* Include the termination SDNORM */
printf("T.81/T.82 arithmetic encoder tests, from ITU-T T.82\n\n");
printf("Arithmetic encoder tests from ITU-T T.82/7.1\n");
if ((se = t81_t82_arith_encode_init(NULL, write_byte, NULL)) == NULL)
{
fprintf(stderr, "Failed to allocate arithmetic encoder!\n");
exit(2);
}
msg_len = 0;
for (i = 0; i < 16; i++)
{
for (j = 0; j < 16; j++)
{
t81_t82_arith_encode(se,
(cx_7_1[i] >> (15 - j)) & 1,
(pix_7_1[i] >> (15 - j)) & 1);
}
}
t81_t82_arith_encode_flush(se);
if (msg_len != SDE_7_1_LEN || memcmp(msg, sde_7_1, SDE_7_1_LEN))
{
printf("Encoded data: ");
for (i = 0; i < msg_len; i++)
printf("%02X", msg[i]);
printf("\n");
printf("Expected data: ");
for (i = 0; i < SDE_7_1_LEN; i++)
printf("%02X", sde_7_1[i]);
printf("\n");
printf("Test failed\n");
exit(2);
}
printf("Test passed\n");
printf("Arithmetic decoder tests from ITU-T T.82/7.1\n");
printf("Decoding byte by byte...\n");
test_failed = FALSE;
if ((sd = t81_t82_arith_decode_init(NULL)) == NULL)
{
fprintf(stderr, "Failed to allocate arithmetic decoder!\n");
exit(2);
}
pp = sde_7_1;
sd->pscd_ptr = pp;
sd->pscd_end = pp + 1;
for (i = 0; i < 16; i++)
{
for (j = 0; j < 16; j++)
{
for (;;)
{
pix = t81_t82_arith_decode(sd, (cx_7_1[i] >> (15 - j)) & 1);
if ((pix >= 0 || sd->pscd_end >= sde_7_1 + SDE_7_1_FULL_LEN))
break;
pp++;
if (sd->pscd_ptr != pp - 1)
sd->pscd_ptr = pp;
sd->pscd_end = pp + 1;
}
if (pix < 0)
{
printf("Bad pixel %d, byte %" PRIdPTR ".\n\n",
i*16 + j + 1,
sd->pscd_ptr - sd->pscd_end);
test_failed = TRUE;
break;
}
if (pix != ((pix_7_1[i] >> (15 - j)) & 1))
{
printf("Bad PIX (%d) at pixel %d.\n\n",
pix,
i*16 + j + 1);
test_failed = TRUE;
break;
}
}
}
if (sd->pscd_ptr != sd->pscd_end - 2)
{
printf("%" PRIdPTR " bytes left after decoder finished.\n\n",
sd->pscd_end - sd->pscd_ptr - 2);
test_failed = TRUE;
}
if (test_failed)
{
printf("Test failed\n");
exit(2);
}
printf("Test passed\n");
printf("Decoding chunk by chunk...\n");
test_failed = FALSE;
t81_t82_arith_decode_init(sd);
sd->pscd_ptr = sde_7_1;
sd->pscd_end = sde_7_1 + SDE_7_1_FULL_LEN;
for (i = 0; i < 16; i++)
{
for (j = 0; j < 16; j++)
{
pix = t81_t82_arith_decode(sd, (cx_7_1[i] >> (15 - j)) & 1);
if (pix < 0)
{
printf("Bad pixel %d, byte %" PRIdPTR ".\n\n",
i*16 + j + 1,
sd->pscd_ptr - sd->pscd_end);
test_failed = TRUE;
break;
}
if (pix != ((pix_7_1[i] >> (15 - j)) & 1))
{
printf("Bad PIX (%d) at pixel %d.\n\n",
pix,
i*16 + j + 1);
test_failed = TRUE;
break;
}
}
}
if (sd->pscd_ptr != sd->pscd_end - 2)
{
printf("%" PRIdPTR " bytes left after decoder finished.\n\n",
sd->pscd_end - sd->pscd_ptr - 2);
test_failed = TRUE;
}
if (test_failed)
{
printf("Test failed\n");
exit(2);
}
printf("Test passed\n");
printf("Tests passed\n");
return 0;
}
/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/
差异被折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论