Skip to content
项目
群组
代码片段
帮助
正在加载...
登录
切换导航
F
freeswitch
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
张华
freeswitch
Commits
ccbee256
提交
ccbee256
authored
7月 24, 2010
作者:
Steve Underwood
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Added some new files for spandsp
上级
f029f7ef
显示空白字符变更
内嵌
并排
正在显示
18 个修改的文件
包含
3171 行增加
和
0 行删除
+3171
-0
fax-tests.xml
libs/spandsp/spandsp/fax-tests.xml
+96
-0
image_translate.c
libs/spandsp/src/image_translate.c
+466
-0
image_translate.h
libs/spandsp/src/spandsp/image_translate.h
+108
-0
image_translate.h
libs/spandsp/src/spandsp/private/image_translate.h
+52
-0
t4_t6_decode.h
libs/spandsp/src/spandsp/private/t4_t6_decode.h
+101
-0
t4_t6_encode.h
libs/spandsp/src/spandsp/private/t4_t6_encode.h
+59
-0
timezone.h
libs/spandsp/src/spandsp/private/timezone.h
+90
-0
t4_t6_decode.h
libs/spandsp/src/spandsp/t4_t6_decode.h
+53
-0
t4_t6_encode.h
libs/spandsp/src/spandsp/t4_t6_encode.h
+42
-0
timezone.h
libs/spandsp/src/spandsp/timezone.h
+88
-0
timezone.c
libs/spandsp/src/timezone.c
+822
-0
generate_striped_pages.c
libs/spandsp/test-data/itu/fax/generate_striped_pages.c
+123
-0
lenna-colour.tif
libs/spandsp/test-data/local/lenna-colour.tif
+0
-0
bitstream_tests.c
libs/spandsp/tests/bitstream_tests.c
+189
-0
image_translate_tests.c
libs/spandsp/tests/image_translate_tests.c
+452
-0
saturated_tests.c
libs/spandsp/tests/saturated_tests.c
+311
-0
timezone_tests.c
libs/spandsp/tests/timezone_tests.c
+86
-0
tsb85_extra_tests.sh
libs/spandsp/tests/tsb85_extra_tests.sh
+33
-0
没有找到文件。
libs/spandsp/spandsp/fax-tests.xml
0 → 100644
浏览文件 @
ccbee256
<?xml version="1.0"?>
<!DOCTYPE fax-tests SYSTEM "./fax-tests.dtd">
<fax-tests>
<config>
<path
type=
"IMAGE"
value=
"../test-data/etsi/fax"
/>
</config>
<messages>
<!-- TCF = 2700 bytes at 14400, 2250 at 12000, 1800 at 9600, 1350 at 7200, 900 at 4800 or 450 at 2400 -->
<!-- Bad TCF == 10101010.... -->
<!-- slow HDLC preamble == 37 flag bytes -->
<!-- slow HDLC inter-frame flag sequence == 1 flag byte -->
<!-- slow HDLC end flag sequence == 5 flag bytes -->
<!-- synchronisation sequence == 250ms of zeros. = 450 bytes at 14400, 375 at 12000, 300 at 9600, 225 at 7200, 150 at 4800 or 75 at 2400 -->
<!-- fast HDLC inter-frame flag sequence == 1 flag byte -->
<!-- fast HDLC end flag sequence == 10 flag bytes -->
<!-- STAIRSTEP image is 1728x1728 pixels. Its is about 15k, so an average of 68.2 bits per row. To
cook it as a 31k page requires a min_bits of 141. To cook it as a 63k page requires a min_bits of
286. To cook it as a 64k page requires a min_bits of 291 -->
</messages>
<test-group
name=
"Supplementary"
>
<test
name=
"PPS-MPS-lost-PPS"
>
<!-- Tester calls DUT and sends one 31k byte STAIRSTEP page and one 15k byte STAIRSTEP page. -->
<step
type=
"CALL"
/>
<!--<step dir="T" type="CNG"/>-->
<step
dir=
"R"
type=
"CED"
/>
<step
dir=
"R"
type=
"HDLC"
modem=
"V.21"
tag=
"DIS"
value=
"FF C8 01 ..."
timeout=
"60000"
/>
<step
dir=
"R"
type=
"SILENCE"
/>
<step
type=
"WAIT"
value=
"75"
/>
<step
dir=
"T"
type=
"PREAMBLE"
modem=
"V.21"
/>
<step
dir=
"T"
type=
"HDLC"
tag=
"DCS"
value=
"FF C8 41 00 50 1F 30"
/>
<step
dir=
"T"
type=
"POSTAMBLE"
/>
<step
type=
"WAIT"
value=
"75"
/>
<step
dir=
"T"
type=
"TCF"
modem=
"V.27ter/4800"
value=
"900"
/>
<step
dir=
"R"
type=
"HDLC"
modem=
"V.21"
tag=
"CFR"
value=
"FF C8 21"
/>
<step
dir=
"R"
type=
"SILENCE"
/>
<step
type=
"WAIT"
value=
"75"
/>
<step
dir=
"T"
type=
"PREAMBLE"
modem=
"V.27ter/4800"
/>
<step
dir=
"T"
type=
"PP"
value=
"etsi_300_242_a4_stairstep.tif"
min_bits=
"141"
/>
<step
dir=
"T"
type=
"POSTAMBLE"
/>
<step
type=
"WAIT"
value=
"75"
/>
<step
dir=
"T"
type=
"PREAMBLE"
modem=
"V.21"
/>
<step
dir=
"T"
type=
"HDLC"
tag=
"PPS-NULL"
value=
"FF C8 7D 00 00 00 08"
/>
<step
dir=
"T"
type=
"POSTAMBLE"
/>
<step
dir=
"R"
type=
"HDLC"
modem=
"V.21"
tag=
"MCF"
value=
"FF C8 31"
/>
<step
dir=
"R"
type=
"SILENCE"
/>
<step
type=
"WAIT"
value=
"75"
/>
<step
dir=
"T"
type=
"PREAMBLE"
modem=
"V.27ter/4800"
/>
<step
dir=
"T"
type=
"PP"
value=
"etsi_300_242_a4_stairstep.tif"
/>
<step
dir=
"T"
type=
"POSTAMBLE"
/>
<step
type=
"WAIT"
value=
"75"
/>
<step
dir=
"T"
type=
"PREAMBLE"
modem=
"V.21"
/>
<step
dir=
"T"
type=
"HDLC"
tag=
"PPS-MPS"
value=
"FF C8 7D 72 00 80 08"
/>
<step
dir=
"T"
type=
"POSTAMBLE"
/>
<step
dir=
"R"
type=
"HDLC"
modem=
"V.21"
tag=
"MCF"
value=
"FF C8 31"
/>
<step
dir=
"R"
type=
"SILENCE"
/>
<!-- Repeat the last chunk, as though we missed the MCF -->
<step
type=
"WAIT"
value=
"75"
/>
<step
dir=
"T"
type=
"PREAMBLE"
modem=
"V.27ter/4800"
/>
<step
dir=
"T"
type=
"PP"
value=
"etsi_300_242_a4_stairstep.tif"
/>
<step
dir=
"T"
type=
"POSTAMBLE"
/>
<step
type=
"WAIT"
value=
"75"
/>
<step
dir=
"T"
type=
"PREAMBLE"
modem=
"V.21"
/>
<step
dir=
"T"
type=
"HDLC"
tag=
"PPS-MPS"
value=
"FF C8 7D 72 00 80 08"
/>
<step
dir=
"T"
type=
"POSTAMBLE"
/>
<step
dir=
"R"
type=
"HDLC"
modem=
"V.21"
tag=
"MCF"
value=
"FF C8 31"
/>
<step
dir=
"R"
type=
"SILENCE"
/>
<step
type=
"WAIT"
value=
"75"
/>
<step
dir=
"T"
type=
"PREAMBLE"
modem=
"V.27ter/4800"
/>
<step
dir=
"T"
type=
"PP"
value=
"etsi_300_242_a4_white.tif"
/>
<step
dir=
"T"
type=
"POSTAMBLE"
/>
<step
type=
"WAIT"
value=
"75"
/>
<step
dir=
"T"
type=
"PREAMBLE"
modem=
"V.21"
/>
<step
dir=
"T"
type=
"HDLC"
tag=
"PPS-MPS"
value=
"FF C8 7D 72 80 00 08"
/>
<step
dir=
"T"
type=
"POSTAMBLE"
/>
<step
dir=
"R"
type=
"HDLC"
modem=
"V.21"
tag=
"MCF"
value=
"FF C8 31"
/>
<step
dir=
"R"
type=
"SILENCE"
/>
<step
type=
"WAIT"
value=
"75"
/>
<step
dir=
"T"
type=
"PREAMBLE"
modem=
"V.21"
/>
<step
dir=
"T"
type=
"HDLC"
tag=
"DCN"
value=
"FF C8 5F"
/>
<step
dir=
"T"
type=
"POSTAMBLE"
/>
</test>
</test-group>
</fax-tests>
libs/spandsp/src/image_translate.c
0 → 100644
浏览文件 @
ccbee256
/*
* SpanDSP - a series of DSP components for telephony
*
* image_translate.c - Image translation routines for reworking colour
* and gray scale images to be bi-level images of an
* appropriate size to be FAX compatible.
*
* 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 */
#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
#include <stdlib.h>
#include <inttypes.h>
#include <limits.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <memory.h>
#include <string.h>
#if defined(HAVE_TGMATH_H)
#include <tgmath.h>
#endif
#if defined(HAVE_MATH_H)
#include <math.h>
#endif
#include "floating_fudge.h"
#include <tiffio.h>
#include <assert.h>
#include "spandsp/telephony.h"
#include "spandsp/fast_convert.h"
#include "spandsp/logging.h"
#include "spandsp/saturated.h"
#include "spandsp/t4_rx.h"
#include "spandsp/t4_tx.h"
#if defined(SPANDSP_SUPPORT_T85)
#include "spandsp/t81_t82_arith_coding.h"
#include "spandsp/t85.h"
#endif
#include "spandsp/t4_t6_decode.h"
#include "spandsp/t4_t6_encode.h"
#include "spandsp/image_translate.h"
#include "spandsp/private/logging.h"
#if defined(SPANDSP_SUPPORT_T85)
#include "spandsp/private/t81_t82_arith_coding.h"
#include "spandsp/private/t85.h"
#endif
#include "spandsp/private/t4_t6_decode.h"
#include "spandsp/private/t4_t6_encode.h"
#include "spandsp/private/t4_rx.h"
#include "spandsp/private/t4_tx.h"
#include "spandsp/private/image_translate.h"
static
int
image_colour16_to_gray8_row
(
uint8_t
mono
[],
uint16_t
colour
[],
int
pixels
)
{
int
i
;
uint32_t
gray
;
for
(
i
=
0
;
i
<
pixels
;
i
++
)
{
gray
=
colour
[
3
*
i
]
*
19595
+
colour
[
3
*
i
+
1
]
*
38469
+
colour
[
3
*
i
+
2
]
*
7472
;
mono
[
i
]
=
saturateu8
(
gray
>>
24
);
}
return
pixels
;
}
/*- End of function --------------------------------------------------------*/
static
int
image_colour8_to_gray8_row
(
uint8_t
mono
[],
uint8_t
colour
[],
int
pixels
)
{
int
i
;
uint32_t
gray
;
for
(
i
=
0
;
i
<
pixels
;
i
++
)
{
gray
=
colour
[
3
*
i
]
*
19595
+
colour
[
3
*
i
+
1
]
*
38469
+
colour
[
3
*
i
+
2
]
*
7472
;
mono
[
i
]
=
saturateu8
(
gray
>>
16
);
}
return
pixels
;
}
/*- End of function --------------------------------------------------------*/
static
int
image_gray16_to_gray8_row
(
uint8_t
mono
[],
uint16_t
gray
[],
int
pixels
)
{
int
i
;
for
(
i
=
0
;
i
<
pixels
;
i
++
)
mono
[
i
]
=
gray
[
i
]
>>
8
;
return
pixels
;
}
/*- End of function --------------------------------------------------------*/
static
int
get_and_scrunch_row
(
image_translate_state_t
*
s
,
uint8_t
buf
[],
size_t
len
)
{
int
row_len
;
row_len
=
(
*
s
->
row_read_handler
)(
s
->
row_read_user_data
,
buf
,
s
->
input_width
*
s
->
bytes_per_pixel
);
if
(
row_len
!=
s
->
input_width
*
s
->
bytes_per_pixel
)
return
0
;
/* Scrunch colour down to gray, and scrunch 16 bit pixels down to 8 bit pixels */
switch
(
s
->
input_format
)
{
case
IMAGE_TRANSLATE_FROM_GRAY_16
:
image_gray16_to_gray8_row
(
buf
,
(
uint16_t
*
)
buf
,
s
->
input_width
);
break
;
case
IMAGE_TRANSLATE_FROM_COLOUR_16
:
image_colour16_to_gray8_row
(
buf
,
(
uint16_t
*
)
buf
,
s
->
input_width
);
break
;
case
IMAGE_TRANSLATE_FROM_COLOUR_8
:
image_colour8_to_gray8_row
(
buf
,
buf
,
s
->
input_width
);
break
;
}
return
row_len
;
}
/*- End of function --------------------------------------------------------*/
static
int
image_resize_row
(
image_translate_state_t
*
s
,
uint8_t
buf
[],
size_t
len
)
{
int
i
;
int
output_width
;
int
output_length
;
int
input_width
;
int
input_length
;
double
c1
;
double
c2
;
double
int_part
;
int
x
;
#if defined(SPANDSP_USE_FIXED_POINT)
int
frac_row
;
int
frac_col
;
#else
double
frac_row
;
double
frac_col
;
#endif
int
row_len
;
int
skip
;
uint8_t
*
p
;
if
(
s
->
raw_output_row
<
0
)
return
0
;
output_width
=
s
->
output_width
-
1
;
output_length
=
s
->
output_length
-
1
;
input_width
=
s
->
input_width
-
1
;
input_length
=
s
->
input_length
-
1
;
skip
=
s
->
raw_output_row
*
input_length
/
output_length
;
if
(
skip
>=
s
->
raw_input_row
)
{
skip
++
;
while
(
skip
>=
s
->
raw_input_row
)
{
if
(
s
->
raw_input_row
>=
s
->
input_length
)
{
s
->
raw_output_row
=
-
1
;
break
;
}
row_len
=
get_and_scrunch_row
(
s
,
s
->
raw_pixel_row
[
0
],
s
->
input_width
*
s
->
bytes_per_pixel
);
if
(
row_len
!=
s
->
input_width
*
s
->
bytes_per_pixel
)
{
s
->
raw_output_row
=
-
1
;
return
0
;
}
s
->
raw_input_row
++
;
p
=
s
->
raw_pixel_row
[
0
];
s
->
raw_pixel_row
[
0
]
=
s
->
raw_pixel_row
[
1
];
s
->
raw_pixel_row
[
1
]
=
p
;
}
}
#if defined(SPANDSP_USE_FIXED_POINT)
frac_row
=
s
->
raw_output_row
*
input_length
/
output_length
;
frac_row
=
s
->
raw_output_row
*
input_length
-
frac_row
*
output_length
;
for
(
i
=
0
;
i
<
output_width
;
i
++
)
{
x
=
i
*
input_width
/
output_width
;
frac_col
=
x
-
x
*
output_width
;
c1
=
s
->
raw_pixel_row
[
0
][
x
]
+
(
s
->
raw_pixel_row
[
0
][
x
+
1
]
-
s
->
raw_pixel_row
[
0
][
x
])
*
frac_col
;
c1
=
s
->
raw_pixel_row
[
1
][
x
]
+
(
s
->
raw_pixel_row
[
1
][
x
+
1
]
-
s
->
raw_pixel_row
[
1
][
x
])
*
frac_col
;
buf
[
i
]
=
saturateu8
(
c1
+
(
c2
-
c1
)
*
frac_row
);
}
#else
frac_row
=
modf
((
double
)
s
->
raw_output_row
*
input_length
/
output_length
,
&
int_part
);
for
(
i
=
0
;
i
<
output_width
;
i
++
)
{
frac_col
=
modf
((
double
)
i
*
input_width
/
output_width
,
&
int_part
);
x
=
int_part
;
c1
=
s
->
raw_pixel_row
[
0
][
x
]
+
(
s
->
raw_pixel_row
[
0
][
x
+
1
]
-
s
->
raw_pixel_row
[
0
][
x
])
*
frac_col
;
c2
=
s
->
raw_pixel_row
[
1
][
x
]
+
(
s
->
raw_pixel_row
[
1
][
x
+
1
]
-
s
->
raw_pixel_row
[
1
][
x
])
*
frac_col
;
buf
[
i
]
=
saturateu8
(
c1
+
(
c2
-
c1
)
*
frac_row
);
}
#endif
if
(
++
s
->
raw_output_row
>=
s
->
output_length
)
s
->
raw_output_row
=
-
1
;
return
len
;
}
/*- End of function --------------------------------------------------------*/
static
__inline__
uint8_t
find_closest_palette_color
(
int
in
)
{
return
(
in
>=
128
)
?
255
:
0
;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE
(
int
)
image_translate_row
(
image_translate_state_t
*
s
,
uint8_t
buf
[],
size_t
len
)
{
int
x
;
int
y
;
int
i
;
int
j
;
int
limit
;
int
old_pixel
;
int
new_pixel
;
int
quant_error
;
uint8_t
*
p
;
uint8_t
xx
;
if
(
s
->
output_row
<
0
)
return
0
;
y
=
s
->
output_row
++
;
/* This algorithm works over two rows, and outputs the earlier of the two. To
make this work:
- At row 0 we grab and scrunch two rows.
- From row 1 up to the last row we grab one new additional row each time.
- At the last row we dither and output, without getting an extra row in. */
for
(
i
=
(
y
==
0
)
?
0
:
1
;
i
<
2
;
i
++
)
{
p
=
s
->
pixel_row
[
0
];
s
->
pixel_row
[
0
]
=
s
->
pixel_row
[
1
];
s
->
pixel_row
[
1
]
=
p
;
/* If this is the end of the image just ignore that there is now rubbish in pixel_row[1].
Mark that the end has occurred. This row will be properly output, and the next one
will fail, with the end of image condition (i.e. returning zero length) */
if
(
s
->
resize
)
{
if
(
image_resize_row
(
s
,
s
->
pixel_row
[
1
],
s
->
output_width
*
s
->
bytes_per_pixel
)
!=
s
->
output_width
*
s
->
bytes_per_pixel
)
s
->
output_row
=
-
1
;
}
else
{
if
(
get_and_scrunch_row
(
s
,
s
->
pixel_row
[
1
],
s
->
output_width
*
s
->
bytes_per_pixel
)
!=
s
->
output_width
*
s
->
bytes_per_pixel
)
s
->
output_row
=
-
1
;
}
}
/* Apply Floyd-Steinberg dithering to the 8 bit pixels, using a bustrophodontic
scan, to reduce the grayscale image to pure black and white */
/* The first and last pixels in each row need special treatment, so we do not
step outside the row. */
if
((
y
&
1
))
{
x
=
s
->
output_width
-
1
;
old_pixel
=
s
->
pixel_row
[
0
][
x
];
new_pixel
=
find_closest_palette_color
(
old_pixel
);
quant_error
=
old_pixel
-
new_pixel
;
s
->
pixel_row
[
0
][
x
+
0
]
=
new_pixel
;
s
->
pixel_row
[
0
][
x
-
1
]
=
saturateu8
(
s
->
pixel_row
[
0
][
x
-
1
]
+
(
7
*
quant_error
)
/
16
);
s
->
pixel_row
[
1
][
x
+
0
]
=
saturateu8
(
s
->
pixel_row
[
1
][
x
+
0
]
+
(
5
*
quant_error
)
/
16
);
s
->
pixel_row
[
1
][
x
-
1
]
=
saturateu8
(
s
->
pixel_row
[
1
][
x
-
1
]
+
(
1
*
quant_error
)
/
16
);
for
(
;
x
>
0
;
x
--
)
{
old_pixel
=
s
->
pixel_row
[
0
][
x
];
new_pixel
=
find_closest_palette_color
(
old_pixel
);
quant_error
=
old_pixel
-
new_pixel
;
s
->
pixel_row
[
0
][
x
+
0
]
=
new_pixel
;
s
->
pixel_row
[
0
][
x
-
1
]
=
saturateu8
(
s
->
pixel_row
[
0
][
x
-
1
]
+
(
7
*
quant_error
)
/
16
);
s
->
pixel_row
[
1
][
x
+
1
]
=
saturateu8
(
s
->
pixel_row
[
1
][
x
+
1
]
+
(
3
*
quant_error
)
/
16
);
s
->
pixel_row
[
1
][
x
+
0
]
=
saturateu8
(
s
->
pixel_row
[
1
][
x
+
0
]
+
(
5
*
quant_error
)
/
16
);
s
->
pixel_row
[
1
][
x
-
1
]
=
saturateu8
(
s
->
pixel_row
[
1
][
x
-
1
]
+
(
1
*
quant_error
)
/
16
);
}
old_pixel
=
s
->
pixel_row
[
0
][
x
];
new_pixel
=
find_closest_palette_color
(
old_pixel
);
quant_error
=
old_pixel
-
new_pixel
;
s
->
pixel_row
[
0
][
x
+
0
]
=
new_pixel
;
s
->
pixel_row
[
1
][
x
+
1
]
=
saturateu8
(
s
->
pixel_row
[
1
][
x
+
1
]
+
(
3
*
quant_error
)
/
16
);
s
->
pixel_row
[
1
][
x
+
0
]
=
saturateu8
(
s
->
pixel_row
[
1
][
x
+
0
]
+
(
5
*
quant_error
)
/
16
);
}
else
{
x
=
0
;
old_pixel
=
s
->
pixel_row
[
0
][
x
];
new_pixel
=
find_closest_palette_color
(
old_pixel
);
quant_error
=
old_pixel
-
new_pixel
;
s
->
pixel_row
[
0
][
x
+
0
]
=
new_pixel
;
s
->
pixel_row
[
0
][
x
+
1
]
=
saturateu8
(
s
->
pixel_row
[
0
][
x
+
1
]
+
(
7
*
quant_error
)
/
16
);
s
->
pixel_row
[
1
][
x
+
0
]
=
saturateu8
(
s
->
pixel_row
[
1
][
x
+
0
]
+
(
5
*
quant_error
)
/
16
);
s
->
pixel_row
[
1
][
x
+
1
]
=
saturateu8
(
s
->
pixel_row
[
1
][
x
+
1
]
+
(
1
*
quant_error
)
/
16
);
for
(
;
x
<
s
->
output_width
-
1
;
x
++
)
{
old_pixel
=
s
->
pixel_row
[
0
][
x
];
new_pixel
=
find_closest_palette_color
(
old_pixel
);
quant_error
=
old_pixel
-
new_pixel
;
s
->
pixel_row
[
0
][
x
+
0
]
=
new_pixel
;
s
->
pixel_row
[
0
][
x
+
1
]
=
saturateu8
(
s
->
pixel_row
[
0
][
x
+
1
]
+
(
7
*
quant_error
)
/
16
);
s
->
pixel_row
[
1
][
x
-
1
]
=
saturateu8
(
s
->
pixel_row
[
1
][
x
-
1
]
+
(
3
*
quant_error
)
/
16
);
s
->
pixel_row
[
1
][
x
+
0
]
=
saturateu8
(
s
->
pixel_row
[
1
][
x
+
0
]
+
(
5
*
quant_error
)
/
16
);
s
->
pixel_row
[
1
][
x
+
1
]
=
saturateu8
(
s
->
pixel_row
[
1
][
x
+
1
]
+
(
1
*
quant_error
)
/
16
);
}
old_pixel
=
s
->
pixel_row
[
0
][
x
];
new_pixel
=
find_closest_palette_color
(
old_pixel
);
quant_error
=
old_pixel
-
new_pixel
;
s
->
pixel_row
[
0
][
x
+
0
]
=
new_pixel
;
s
->
pixel_row
[
1
][
x
-
1
]
=
saturateu8
(
s
->
pixel_row
[
1
][
x
-
1
]
+
(
3
*
quant_error
)
/
16
);
s
->
pixel_row
[
1
][
x
+
0
]
=
saturateu8
(
s
->
pixel_row
[
1
][
x
+
0
]
+
(
5
*
quant_error
)
/
16
);
}
/* Now bit pack the pixel per byte row into a pixel per bit row. */
for
(
i
=
0
,
x
=
0
;
x
<
s
->
output_width
;
i
++
,
x
+=
8
)
{
xx
=
0
;
/* Allow for the possibility that the width is not a multiple of 8 */
limit
=
(
8
<=
s
->
output_width
-
x
)
?
8
:
(
s
->
output_width
-
x
);
for
(
j
=
0
;
j
<
limit
;
j
++
)
{
if
(
s
->
pixel_row
[
0
][
x
+
j
]
<=
128
)
xx
|=
(
1
<<
(
7
-
j
));
}
buf
[
i
]
=
xx
;
}
return
i
;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE
(
int
)
image_translate_get_output_width
(
image_translate_state_t
*
s
)
{
return
s
->
output_width
;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE
(
int
)
image_translate_get_output_length
(
image_translate_state_t
*
s
)
{
return
s
->
output_length
;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE
(
image_translate_state_t
*
)
image_translate_init
(
image_translate_state_t
*
s
,
int
input_format
,
int
input_width
,
int
input_length
,
int
output_width
,
t4_row_read_handler_t
row_read_handler
,
void
*
row_read_user_data
)
{
int
i
;
if
(
s
==
NULL
)
{
if
((
s
=
(
image_translate_state_t
*
)
malloc
(
sizeof
(
*
s
)))
==
NULL
)
return
NULL
;
}
memset
(
s
,
0
,
sizeof
(
*
s
));
s
->
input_format
=
input_format
;
s
->
input_width
=
input_width
;
s
->
input_length
=
input_length
;
s
->
resize
=
(
output_width
>
0
);
s
->
output_width
=
(
s
->
resize
)
?
output_width
:
s
->
input_width
;
s
->
output_length
=
(
s
->
resize
)
?
s
->
input_length
*
s
->
output_width
/
s
->
input_width
:
s
->
input_length
;
switch
(
s
->
input_format
)
{
case
IMAGE_TRANSLATE_FROM_GRAY_8
:
s
->
bytes_per_pixel
=
1
;
break
;
case
IMAGE_TRANSLATE_FROM_GRAY_16
:
s
->
bytes_per_pixel
=
2
;
break
;
case
IMAGE_TRANSLATE_FROM_COLOUR_8
:
s
->
bytes_per_pixel
=
3
;
break
;
case
IMAGE_TRANSLATE_FROM_COLOUR_16
:
s
->
bytes_per_pixel
=
6
;
break
;
default
:
s
->
bytes_per_pixel
=
1
;
break
;
}
/* Allocate the two row buffers we need, using the space requirements we now have */
if
(
s
->
resize
)
{
for
(
i
=
0
;
i
<
2
;
i
++
)
{
if
((
s
->
raw_pixel_row
[
i
]
=
(
uint8_t
*
)
malloc
(
s
->
input_width
*
s
->
bytes_per_pixel
))
==
NULL
)
return
NULL
;
memset
(
s
->
raw_pixel_row
[
i
],
0
,
s
->
input_width
*
s
->
bytes_per_pixel
);
if
((
s
->
pixel_row
[
i
]
=
(
uint8_t
*
)
malloc
(
s
->
output_width
*
sizeof
(
uint8_t
)))
==
NULL
)
return
NULL
;
memset
(
s
->
pixel_row
[
i
],
0
,
s
->
output_width
*
sizeof
(
uint8_t
));
}
}
else
{
for
(
i
=
0
;
i
<
2
;
i
++
)
{
if
((
s
->
pixel_row
[
i
]
=
(
uint8_t
*
)
malloc
(
s
->
output_width
*
s
->
bytes_per_pixel
))
==
NULL
)
return
NULL
;
memset
(
s
->
pixel_row
[
i
],
0
,
s
->
output_width
*
s
->
bytes_per_pixel
);
}
}
s
->
row_read_handler
=
row_read_handler
;
s
->
row_read_user_data
=
row_read_user_data
;
s
->
raw_input_row
=
0
;
s
->
raw_output_row
=
0
;
s
->
output_row
=
0
;
return
s
;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE
(
int
)
image_translate_release
(
image_translate_state_t
*
s
)
{
int
i
;
for
(
i
=
0
;
i
<
2
;
i
++
)
{
if
(
s
->
raw_pixel_row
[
i
])
{
free
(
s
->
raw_pixel_row
[
i
]);
s
->
raw_pixel_row
[
i
]
=
NULL
;
}
if
(
s
->
pixel_row
[
i
])
{
free
(
s
->
pixel_row
[
i
]);
s
->
pixel_row
[
i
]
=
NULL
;
}
}
return
0
;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE
(
int
)
image_translate_free
(
image_translate_state_t
*
s
)
{
int
res
;
res
=
image_translate_release
(
s
);
free
(
s
);
return
res
;
}
/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/
libs/spandsp/src/spandsp/image_translate.h
0 → 100644
浏览文件 @
ccbee256
/*
* SpanDSP - a series of DSP components for telephony
*
* image_translate.h - Image translation routines for reworking colour
* and gray scale images to be bi-level images of an
* appropriate size to be FAX compatible.
*
* 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_IMAGE_TRANSLATE_H_)
#define _SPANDSP_IMAGE_TRANSLATE_H_
/*! \page image_translate_page Image translation
\section image_translate_page_sec_1 What does it do?
\section image_translate_page_sec_2 How does it work?
\section image_translate_page_sec_3 How do I use it?
*/
typedef
struct
image_translate_state_s
image_translate_state_t
;
enum
{
IMAGE_TRANSLATE_FROM_MONO
=
1
,
IMAGE_TRANSLATE_FROM_GRAY_8
=
2
,
IMAGE_TRANSLATE_FROM_GRAY_16
=
3
,
IMAGE_TRANSLATE_FROM_COLOUR_8
=
4
,
IMAGE_TRANSLATE_FROM_COLOUR_16
=
5
};
#if defined(__cplusplus)
extern
"C"
{
#endif
/*! \brief Get the next row of a translated image.
\param s The image translation context.
\return the length of the row buffer, in bytes */
SPAN_DECLARE
(
int
)
image_translate_row
(
image_translate_state_t
*
s
,
uint8_t
buf
[],
size_t
len
);
/*! \brief Get the width of the image being produced by an image translation context.
\param s The image translation context.
\return The width of the output image, in pixel. */
SPAN_DECLARE
(
int
)
image_translate_get_output_width
(
image_translate_state_t
*
s
);
/*! \brief Get the length of the image being produced by an image translation context.
\param s The image translation context.
\return The length of the output image, in pixel. */
SPAN_DECLARE
(
int
)
image_translate_get_output_length
(
image_translate_state_t
*
s
);
/*! \brief Initialise an image translation context for rescaling and squashing a gray scale
or colour image to a bi-level FAX type image.
\param s The image translation context.
\param input_format x
\param input_width The width of the source image, in pixels.
\param input_length The length of the source image, in pixels.
\param output_width The width of the output image, in pixels. The length of the output image
will be derived automatically from this and the source image dimension, to main the
geometry of the original image.
\param row_read_handler A callback routine used to pull rows of pixels from the source image
into the translation process.
\param row_read_user_data An opaque point passed to read_row_handler
\return A pointer to the context, or NULL if there was a problem. */
SPAN_DECLARE
(
image_translate_state_t
*
)
image_translate_init
(
image_translate_state_t
*
s
,
int
input_format
,
int
input_width
,
int
input_length
,
int
output_width
,
t4_row_read_handler_t
row_read_handler
,
void
*
row_read_user_data
);
/*! \brief Release the resources associated with an image translation context.
\param s The image translation context.
\return 0 for success, otherwise -1. */
SPAN_DECLARE
(
int
)
image_translate_release
(
image_translate_state_t
*
s
);
/*! \brief Free the resources associated with an image translation context.
\param s The image translation context.
\return 0 for success, otherwise -1. */
SPAN_DECLARE
(
int
)
image_translate_free
(
image_translate_state_t
*
s
);
#if defined(__cplusplus)
}
#endif
#endif
/*- End of file ------------------------------------------------------------*/
libs/spandsp/src/spandsp/private/image_translate.h
0 → 100644
浏览文件 @
ccbee256
/*
* SpanDSP - a series of DSP components for telephony
*
* private/image_translate.c - Image translation routines for reworking colour
* and gray scale images to be bi-level images of an
* appropriate size to be FAX compatible.
*
* 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.
*/
#if !defined(_SPANDSP_PRIVATE_IMAGE_TRANSLATE_H_)
#define _SPANDSP_PRIVATE_IMAGE_TRANSLATE_H_
struct
image_translate_state_s
{
int
input_format
;
int
input_width
;
int
input_length
;
int
output_width
;
int
output_length
;
int
resize
;
int
bytes_per_pixel
;
int
raw_input_row
;
int
raw_output_row
;
int
output_row
;
uint8_t
*
raw_pixel_row
[
2
];
uint8_t
*
pixel_row
[
2
];
t4_row_read_handler_t
row_read_handler
;
void
*
row_read_user_data
;
};
#endif
/*- End of file ------------------------------------------------------------*/
libs/spandsp/src/spandsp/private/t4_t6_decode.h
0 → 100644
浏览文件 @
ccbee256
/*
* SpanDSP - a series of DSP components for telephony
*
* private/t4_t6_decode.h - definitions for T.4/T.6 fax decoding
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2003, 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_T4_T6_DECODE_H_)
#define _SPANDSP_PRIVATE_T4_T6_DECODE_H_
/*!
T.4 1D, T4 2D and T6 decompressor state.
*/
struct
t4_t6_decode_state_s
{
/*! \brief The type of compression used between the FAX machines. */
//int encoding;
/*! \brief Width of the current page, in pixels. */
//int image_width;
/*! \brief Callback function to write a row of pixels to the image destination. */
t4_row_write_handler_t
row_write_handler
;
/*! \brief Opaque pointer passed to row_write_handler. */
void
*
row_write_user_data
;
/*! \brief A pointer into the image buffer indicating where the last row begins */
int
last_row_starts_at
;
/*! \brief This variable is used to count the consecutive EOLS we have seen. If it
reaches six, this is the end of the image. It is initially set to -1 for
1D and 2D decoding, as an indicator that we must wait for the first EOL,
before decoding any image data. */
int
consecutive_eols
;
/*! \brief The reference or starting changing element on the coding line. At the
start of the coding line, a0 is set on an imaginary white changing element
situated just before the first element on the line. During the coding of
the coding line, the position of a0 is defined by the previous coding mode.
(See T.4/4.2.1.3.2.). */
int
a0
;
/*! \brief The first changing element on the reference line to the right of a0 and of
opposite colour to a0. */
int
b1
;
/*! \brief The length of the in-progress run of black or white. */
int
run_length
;
/*! \brief 2D horizontal mode control. */
int
black_white
;
/*! \brief TRUE if the current run is black */
int
its_black
;
/*! \brief The current step into the current row run-lengths buffer. */
int
a_cursor
;
/*! \brief The current step into the reference row run-lengths buffer. */
int
b_cursor
;
/*! \brief Incoming bit buffer for decompression. */
uint32_t
rx_bitstream
;
/*! \brief The number of bits currently in rx_bitstream. */
int
rx_bits
;
/*! \brief The number of bits to be skipped before trying to match the next code word. */
int
rx_skip_bits
;
/*! \brief Decoded pixel buffer. */
//uint32_t pixel_stream;
/*! \brief The number of bits currently in pixel_stream. */
//int tx_bits;
/*! \brief Current pixel row number. */
//int row;
/*! \brief The current number of consecutive bad rows. */
int
curr_bad_row_run
;
/*! \brief The longest run of consecutive bad rows seen in the current page. */
int
longest_bad_row_run
;
/*! \brief The total number of bad rows in the current page. */
int
bad_rows
;
/*! \brief Error and flow logging control */
//logging_state_t logging;
};
#endif
/*- End of file ------------------------------------------------------------*/
libs/spandsp/src/spandsp/private/t4_t6_encode.h
0 → 100644
浏览文件 @
ccbee256
/*
* SpanDSP - a series of DSP components for telephony
*
* private/t4_t6_encode.h - definitions for T.4/T.6 fax compression
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2003 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_T4_T6_ENCODE_H_)
#define _SPANDSP_PRIVATE_T4_T6_ENCODE_H_
/*!
T.4 1D, T4 2D and T6 compressor state.
*/
struct
t4_t6_encode_state_s
{
/*! \brief The minimum number of encoded bits per row. This is a timing thing
for hardware FAX machines. */
int
min_bits_per_row
;
/*! \brief The current maximum contiguous rows that may be 2D encoded. */
int
max_rows_to_next_1d_row
;
/*! \brief Number of rows left that can be 2D encoded, before a 1D encoded row
must be used. */
int
rows_to_next_1d_row
;
/*! \brief The number of runs currently in the reference row. */
int
ref_steps
;
/*! \brief Pointer to the byte containing the next image bit to transmit. */
int
bit_pos
;
/*! \brief Pointer to the bit within the byte containing the next image bit to transmit. */
int
bit_ptr
;
/*! \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
;
};
#endif
/*- End of file ------------------------------------------------------------*/
libs/spandsp/src/spandsp/private/timezone.h
0 → 100644
浏览文件 @
ccbee256
/*
* SpanDSP - a series of DSP components for telephony
*
* private/timezone.h - Timezone handling for time interpretation
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2010 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_TIMEZONE_H_)
#define _SPANDSP_PRIVATE_TIMEZONE_H_
#define TZ_MAX_CHARS 50
/* Maximum number of abbreviation characters */
#define TZ_MAX_LEAPS 50
/* Maximum number of leap second corrections */
#define TZNAME_MAX 255
/* The TZ_MAX_TIMES value below is enough to handle a bit more than a
* year's worth of solar time (corrected daily to the nearest second) or
* 138 years of Pacific Presidential Election time
* (where there are three time zone transitions every fourth year). */
#define TZ_MAX_TIMES 370
#if !defined(NOSOLAR)
#define TZ_MAX_TYPES 256
/* Limited by what (unsigned char)'s can hold */
#else
/* Must be at least 14 for Europe/Riga as of Jan 12 1995,
* as noted by Earl Chew <earl@hpato.aus.hp.com>. */
#define TZ_MAX_TYPES 20
/* Maximum number of local time types */
#endif
#define TZ_BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
/* Time type information */
struct
tz_ttinfo_s
{
int32_t
gmtoff
;
/* UTC offset in seconds */
int
isdst
;
/* Used to set tm_isdst */
int
abbrind
;
/* Abbreviation list index */
int
ttisstd
;
/* TRUE if transition is std time */
int
ttisgmt
;
/* TRUE if transition is UTC */
};
/* Leap second information */
struct
tz_lsinfo_s
{
time_t
trans
;
/* Transition time */
int32_t
corr
;
/* Correction to apply */
};
struct
tz_state_s
{
int
leapcnt
;
int
timecnt
;
int
typecnt
;
int
charcnt
;
time_t
ats
[
TZ_MAX_TIMES
];
uint8_t
types
[
TZ_MAX_TIMES
];
struct
tz_ttinfo_s
ttis
[
TZ_MAX_TYPES
];
char
chars
[
TZ_BIGGEST
(
TZ_MAX_CHARS
+
1
,
(
2
*
(
TZNAME_MAX
+
1
)))];
struct
tz_lsinfo_s
lsis
[
TZ_MAX_LEAPS
];
};
struct
tz_s
{
struct
tz_state_s
state
;
char
lcl_tzname
[
TZNAME_MAX
+
1
];
int
lcl_is_set
;
const
char
*
tzname
[
2
];
};
#endif
/*- End of file ------------------------------------------------------------*/
libs/spandsp/src/spandsp/t4_t6_decode.h
0 → 100644
浏览文件 @
ccbee256
/*
* SpanDSP - a series of DSP components for telephony
*
* t4_t6_decode.h - definitions for T.4/T.6 fax decoding
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2003, 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_T4_T6_DECODE_H_)
#define _SPANDSP_T4_T6_DECODE_H_
/*! \page t4_t6_decode_page T.4 and T.6 FAX image decompression
\section t4_t6_decode_page_sec_1 What does it do?
The T.4 image compression and decompression routines implement the 1D and 2D
encoding methods defined in ITU specification T.4. They also implement the pure
2D encoding method defined in T.6. These are image compression algorithms used
for FAX transmission.
\section t4_t6_decode_page_sec_1 How does it work?
*/
typedef
struct
t4_t6_decode_state_s
t4_t6_decode_state_t
;
#if defined(__cplusplus)
extern
"C"
{
#endif
#if defined(__cplusplus)
}
#endif
#endif
/*- End of file ------------------------------------------------------------*/
libs/spandsp/src/spandsp/t4_t6_encode.h
0 → 100644
浏览文件 @
ccbee256
/*
* SpanDSP - a series of DSP components for telephony
*
* t4_t6_encode.h - definitions for T.4/T.6 fax encoding
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2003, 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_T4_T6_ENCODE_H_)
#define _SPANDSP_T4_T6_ENCODE_H_
typedef
struct
t4_t6_encode_state_s
t4_t6_encode_state_t
;
#if defined(__cplusplus)
extern
"C"
{
#endif
#if defined(__cplusplus)
}
#endif
#endif
/*- End of file ------------------------------------------------------------*/
libs/spandsp/src/spandsp/timezone.h
0 → 100644
浏览文件 @
ccbee256
/*
* SpanDSP - a series of DSP components for telephony
*
* timezone.h - Timezone handling for time interpretation
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2010 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_TIMEZONE_H_)
#define _SPANDSP_TIMEZONE_H_
/*! \page timezone_page Timezone handling
\section timezone_sec_1 What does it do?
\section timezone_sec_2 How does it work?
*/
typedef
struct
tz_s
tz_t
;
enum
{
TM_SUNDAY
=
0
,
TM_MONDAY
,
TM_TUESDAY
,
TM_WEDNESDAY
,
TM_THURSDAY
,
TM_FRIDAY
,
TM_SATURDAY
};
enum
{
TM_JANUARY
=
0
,
TM_FEBRUARY
,
TM_MARCH
,
TM_APRIL
,
TM_MAY
,
TM_JUNE
,
TM_JULY
,
TM_AUGUST
,
TM_SEPTEMBER
,
TM_OCTOBER
,
TM_NOVEMBER
,
TM_DECEMBER
};
#if defined(__cplusplus)
extern
"C"
{
#endif
SPAN_DECLARE
(
tz_t
*
)
tz_init
(
tz_t
*
tz
,
const
char
*
tzstring
);
SPAN_DECLARE
(
int
)
tz_release
(
tz_t
*
tz
);
SPAN_DECLARE
(
int
)
tz_free
(
tz_t
*
tz
);
SPAN_DECLARE
(
int
)
tz_localtime
(
tz_t
*
tz
,
struct
tm
*
tm
,
time_t
t
);
SPAN_DECLARE
(
const
char
*
)
tz_tzname
(
tz_t
*
tz
,
int
isdst
);
#if defined(__cplusplus)
}
#endif
#endif
/*- End of file ------------------------------------------------------------*/
libs/spandsp/src/timezone.c
0 → 100644
浏览文件 @
ccbee256
/*
* SpanDSP - a series of DSP components for telephony
*
* timezone.c - Timezone handling for time interpretation
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2010 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 */
/* Timezone processing might not seem like a DSP activity, but getting the headers
right on FAXes demands it. We need to handle multiple time zones within a process,
for FAXes related to different parts of the globe, so the system timezone handling
is not adequate. */
/* This timezone handling is derived from public domain software by Arthur David Olson
<arthur_david_olson@nih.gov> which you may download from ftp://elsie.nci.nih.gov/pub
at the time of writing. */
#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
#include <stdlib.h>
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <assert.h>
#include "spandsp/telephony.h"
#include "spandsp/timezone.h"
#include "spandsp/private/timezone.h"
#if !defined(FALSE)
#define FALSE 0
#endif
#if !defined(TRUE)
#define TRUE (!FALSE)
#endif
#define SECS_PER_MIN 60
#define MINS_PER_HOUR 60
#define HOURS_PER_DAY 24
#define DAYS_PER_WEEK 7
#define DAYS_PER_NON_LEAP_YEAR 365
#define DAYS_PER_LEAP_YEAR 366
#define SECS_PER_HOUR (SECS_PER_MIN*MINS_PER_HOUR)
#define SECS_PER_DAY ((long int) SECS_PER_HOUR*HOURS_PER_DAY)
#define MONTHS_PER_YEAR 12
#define TM_YEAR_BASE 1900
#define EPOCH_YEAR 1970
#define EPOCH_WDAY TM_THURSDAY
#define isleap(y) (((y)%4) == 0 && (((y)%100) != 0 || ((y)%400) == 0))
#define isleap_sum(a, b) isleap((a)%400 + (b)%400)
/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
#define is_digit(c) ((unsigned int) (c) - '0' <= 9)
#define TZ_DEF_RULE_STRING ",M4.1.0,M10.5.0"
#define JULIAN_DAY 0
/* Jn - Julian day */
#define DAY_OF_YEAR 1
/* n - day of year */
#define MONTH_NTH_DAY_OF_WEEK 2
/* Mm.n.d - month, week, day of week */
static
const
char
wildabbr
[]
=
" "
;
static
const
char
gmt
[]
=
"GMT"
;
struct
tz_rule_s
{
int
r_type
;
/* Type of rule--see below */
int
r_day
;
/* Day number of rule */
int
r_week
;
/* Week number of rule */
int
r_mon
;
/* Month number of rule */
long
int
r_time
;
/* Transition time of rule */
};
static
const
int
mon_lengths
[
2
][
MONTHS_PER_YEAR
]
=
{
{
31
,
28
,
31
,
30
,
31
,
30
,
31
,
31
,
30
,
31
,
30
,
31
},
{
31
,
29
,
31
,
30
,
31
,
30
,
31
,
31
,
30
,
31
,
30
,
31
}
};
static
const
int
year_lengths
[
2
]
=
{
DAYS_PER_NON_LEAP_YEAR
,
DAYS_PER_LEAP_YEAR
};
static
int
increment_overflow
(
int
*
number
,
int
delta
)
{
int
number0
;
number0
=
*
number
;
*
number
+=
delta
;
return
(
*
number
<
number0
)
!=
(
delta
<
0
);
}
/*- End of function --------------------------------------------------------*/
static
void
set_tzname
(
tz_t
*
tz
)
{
struct
tz_state_s
*
sp
;
const
struct
tz_ttinfo_s
*
ttisp
;
int
i
;
sp
=
&
tz
->
state
;
tz
->
tzname
[
0
]
=
wildabbr
;
tz
->
tzname
[
1
]
=
wildabbr
;
for
(
i
=
0
;
i
<
sp
->
typecnt
;
i
++
)
{
ttisp
=
&
sp
->
ttis
[
i
];
tz
->
tzname
[
ttisp
->
isdst
]
=
&
sp
->
chars
[
ttisp
->
abbrind
];
}
for
(
i
=
0
;
i
<
sp
->
timecnt
;
i
++
)
{
ttisp
=
&
sp
->
ttis
[
sp
->
types
[
i
]];
tz
->
tzname
[
ttisp
->
isdst
]
=
&
sp
->
chars
[
ttisp
->
abbrind
];
}
}
/*- End of function --------------------------------------------------------*/
/* Return the number of leap years through the end of the given year
where, to make the math easy, the answer for year zero is defined as zero. */
static
int
leaps_thru_end_of
(
const
int
y
)
{
return
(
y
>=
0
)
?
(
y
/
4
-
y
/
100
+
y
/
400
)
:
-
(
leaps_thru_end_of
(
-
(
y
+
1
))
+
1
);
}
/*- End of function --------------------------------------------------------*/
static
struct
tm
*
time_sub
(
const
time_t
*
const
timep
,
const
long
int
offset
,
const
struct
tz_state_s
*
const
sp
,
struct
tm
*
const
tmp
)
{
const
struct
tz_lsinfo_s
*
lp
;
time_t
tdays
;
const
int
*
ip
;
int32_t
corr
;
int32_t
seconds
;
int32_t
rem
;
int
idays
;
int
y
;
int
hit
;
int
i
;
corr
=
0
;
hit
=
0
;
i
=
sp
->
leapcnt
;
while
(
--
i
>=
0
)
{
lp
=
&
sp
->
lsis
[
i
];
if
(
*
timep
>=
lp
->
trans
)
{
if
(
*
timep
==
lp
->
trans
)
{
hit
=
((
i
==
0
&&
lp
->
corr
>
0
)
||
lp
->
corr
>
sp
->
lsis
[
i
-
1
].
corr
);
if
(
hit
)
{
while
(
i
>
0
&&
sp
->
lsis
[
i
].
trans
==
sp
->
lsis
[
i
-
1
].
trans
+
1
&&
sp
->
lsis
[
i
].
corr
==
sp
->
lsis
[
i
-
1
].
corr
+
1
)
{
hit
++
;
--
i
;
}
}
}
corr
=
lp
->
corr
;
break
;
}
}
y
=
EPOCH_YEAR
;
tdays
=
*
timep
/
SECS_PER_DAY
;
rem
=
*
timep
-
tdays
*
SECS_PER_DAY
;
while
(
tdays
<
0
||
tdays
>=
year_lengths
[
isleap
(
y
)])
{
int
newy
;
time_t
tdelta
;
int
idelta
;
int
leapdays
;
tdelta
=
tdays
/
DAYS_PER_LEAP_YEAR
;
idelta
=
tdelta
;
if
(
tdelta
-
idelta
>=
1
||
idelta
-
tdelta
>=
1
)
return
NULL
;
if
(
idelta
==
0
)
idelta
=
(
tdays
<
0
)
?
-
1
:
1
;
newy
=
y
;
if
(
increment_overflow
(
&
newy
,
idelta
))
return
NULL
;
leapdays
=
leaps_thru_end_of
(
newy
-
1
)
-
leaps_thru_end_of
(
y
-
1
);
tdays
-=
((
time_t
)
newy
-
y
)
*
DAYS_PER_NON_LEAP_YEAR
;
tdays
-=
leapdays
;
y
=
newy
;
}
seconds
=
tdays
*
SECS_PER_DAY
;
tdays
=
seconds
/
SECS_PER_DAY
;
rem
+=
seconds
-
tdays
*
SECS_PER_DAY
;
/* Given the range, we can now fearlessly cast... */
idays
=
tdays
;
rem
+=
(
offset
-
corr
);
while
(
rem
<
0
)
{
rem
+=
SECS_PER_DAY
;
idays
--
;
}
while
(
rem
>=
SECS_PER_DAY
)
{
rem
-=
SECS_PER_DAY
;
idays
++
;
}
while
(
idays
<
0
)
{
if
(
increment_overflow
(
&
y
,
-
1
))
return
NULL
;
idays
+=
year_lengths
[
isleap
(
y
)];
}
while
(
idays
>=
year_lengths
[
isleap
(
y
)])
{
idays
-=
year_lengths
[
isleap
(
y
)];
if
(
increment_overflow
(
&
y
,
1
))
return
NULL
;
}
tmp
->
tm_year
=
y
;
if
(
increment_overflow
(
&
tmp
->
tm_year
,
-
TM_YEAR_BASE
))
return
NULL
;
tmp
->
tm_yday
=
idays
;
/* The "extra" mods below avoid overflow problems. */
tmp
->
tm_wday
=
EPOCH_WDAY
+
((
y
-
EPOCH_YEAR
)
%
DAYS_PER_WEEK
)
*
(
DAYS_PER_NON_LEAP_YEAR
%
DAYS_PER_WEEK
)
+
leaps_thru_end_of
(
y
-
1
)
-
leaps_thru_end_of
(
EPOCH_YEAR
-
1
)
+
idays
;
tmp
->
tm_wday
%=
DAYS_PER_WEEK
;
if
(
tmp
->
tm_wday
<
0
)
tmp
->
tm_wday
+=
DAYS_PER_WEEK
;
tmp
->
tm_hour
=
(
int
)
(
rem
/
SECS_PER_HOUR
);
rem
%=
SECS_PER_HOUR
;
tmp
->
tm_min
=
(
int
)
(
rem
/
SECS_PER_MIN
);
/* A positive leap second requires a special
* representation. This uses "... ??:59:60" et seq. */
tmp
->
tm_sec
=
(
int
)
(
rem
%
SECS_PER_MIN
)
+
hit
;
ip
=
mon_lengths
[
isleap
(
y
)];
for
(
tmp
->
tm_mon
=
0
;
idays
>=
ip
[
tmp
->
tm_mon
];
(
tmp
->
tm_mon
)
++
)
idays
-=
ip
[
tmp
->
tm_mon
];
tmp
->
tm_mday
=
(
int
)
(
idays
+
1
);
tmp
->
tm_isdst
=
0
;
return
tmp
;
}
/*- End of function --------------------------------------------------------*/
/* Given a pointer into a time zone string, scan until a character that is not
* a valid character in a zone name is found. Return a pointer to that
* character. */
static
const
char
*
get_tzname
(
const
char
*
strp
)
{
char
c
;
while
((
c
=
*
strp
)
!=
'\0'
&&
!
is_digit
(
c
)
&&
c
!=
','
&&
c
!=
'-'
&&
c
!=
'+'
)
strp
++
;
return
strp
;
}
/*- End of function --------------------------------------------------------*/
/* Given a pointer into a time zone string, extract a number from that string.
* Check that the number is within a specified range; if it is not, return
* NULL.
* Otherwise, return a pointer to the first character not part of the number. */
static
const
char
*
get_num
(
const
char
*
strp
,
int
*
const
nump
,
const
int
min
,
const
int
max
)
{
char
c
;
int
num
;
if
(
strp
==
NULL
||
!
is_digit
(
c
=
*
strp
))
return
NULL
;
num
=
0
;
do
{
num
=
num
*
10
+
(
c
-
'0'
);
if
(
num
>
max
)
return
NULL
;
/* Illegal value */
c
=
*++
strp
;
}
while
(
is_digit
(
c
));
if
(
num
<
min
)
return
NULL
;
/* Illegal value */
*
nump
=
num
;
return
strp
;
}
/*- End of function --------------------------------------------------------*/
/* Given a pointer into a time zone string, extract a number of seconds,
* in hh[:mm[:ss]] form, from the string.
* If any error occurs, return NULL.
* Otherwise, return a pointer to the first character not part of the number
* of seconds. */
static
const
char
*
get_secs
(
const
char
*
strp
,
long
int
*
const
secsp
)
{
int
num
;
/* HOURS_PER_DAY*DAYS_PER_WEEK - 1 allows quasi-Posix rules like
* "M10.4.6/26", which does not conform to Posix,
* but which specifies the equivalent of
* "02:00 on the first Sunday on or after 23 Oct". */
strp
=
get_num
(
strp
,
&
num
,
0
,
HOURS_PER_DAY
*
DAYS_PER_WEEK
-
1
);
if
(
strp
==
NULL
)
return
NULL
;
*
secsp
=
num
*
(
long
int
)
SECS_PER_HOUR
;
if
(
*
strp
==
':'
)
{
strp
=
get_num
(
strp
+
1
,
&
num
,
0
,
MINS_PER_HOUR
-
1
);
if
(
strp
==
NULL
)
return
NULL
;
*
secsp
+=
num
*
SECS_PER_MIN
;
if
(
*
strp
==
':'
)
{
/* SECS_PER_MIN allows for leap seconds. */
strp
=
get_num
(
strp
+
1
,
&
num
,
0
,
SECS_PER_MIN
);
if
(
strp
==
NULL
)
return
NULL
;
*
secsp
+=
num
;
}
}
return
strp
;
}
/*- End of function --------------------------------------------------------*/
/* Given a pointer into a time zone string, extract an offset, in
* [+-]hh[:mm[:ss]] form, from the string.
* If any error occurs, return NULL.
* Otherwise, return a pointer to the first character not part of the time. */
static
const
char
*
get_offset
(
const
char
*
strp
,
long
int
*
const
offsetp
)
{
int
neg
=
0
;
if
(
*
strp
==
'-'
)
{
neg
=
1
;
strp
++
;
}
else
if
(
*
strp
==
'+'
)
{
strp
++
;
}
strp
=
get_secs
(
strp
,
offsetp
);
if
(
strp
==
NULL
)
return
NULL
;
/* Illegal time */
if
(
neg
)
*
offsetp
=
-*
offsetp
;
return
strp
;
}
/*- End of function --------------------------------------------------------*/
/* Given a pointer into a time zone string, extract a rule in the form
* date[/time]. See POSIX section 8 for the format of "date" and "time".
* If a valid rule is not found, return NULL.
* Otherwise, return a pointer to the first character not part of the rule. */
static
const
char
*
get_rule
(
const
char
*
strp
,
struct
tz_rule_s
*
const
rulep
)
{
if
(
*
strp
==
'J'
)
{
/* Julian day. */
rulep
->
r_type
=
JULIAN_DAY
;
strp
=
get_num
(
strp
+
1
,
&
rulep
->
r_day
,
1
,
DAYS_PER_NON_LEAP_YEAR
);
}
else
if
(
*
strp
==
'M'
)
{
/* Month, week, day. */
rulep
->
r_type
=
MONTH_NTH_DAY_OF_WEEK
;
strp
=
get_num
(
strp
+
1
,
&
rulep
->
r_mon
,
1
,
MONTHS_PER_YEAR
);
if
(
strp
==
NULL
||
*
strp
++
!=
'.'
)
return
NULL
;
strp
=
get_num
(
strp
,
&
rulep
->
r_week
,
1
,
5
);
if
(
strp
==
NULL
||
*
strp
++
!=
'.'
)
return
NULL
;
strp
=
get_num
(
strp
,
&
rulep
->
r_day
,
0
,
DAYS_PER_WEEK
-
1
);
}
else
if
(
is_digit
(
*
strp
))
{
/* Day of the year. */
rulep
->
r_type
=
DAY_OF_YEAR
;
strp
=
get_num
(
strp
,
&
rulep
->
r_day
,
0
,
DAYS_PER_LEAP_YEAR
-
1
);
}
else
{
/* Invalid format */
return
NULL
;
}
if
(
strp
==
NULL
)
return
NULL
;
if
(
*
strp
==
'/'
)
{
/* Time specified. */
strp
=
get_secs
(
strp
+
1
,
&
rulep
->
r_time
);
}
else
{
/* Default = 2:00:00 */
rulep
->
r_time
=
2
*
SECS_PER_HOUR
;
}
return
strp
;
}
/*- End of function --------------------------------------------------------*/
/* Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
* year, a rule, and the offset from UTC at the time that rule takes effect,
* calculate the Epoch-relative time that rule takes effect. */
static
time_t
trans_time
(
const
time_t
janfirst
,
const
int
year
,
const
struct
tz_rule_s
*
const
rulep
,
const
long
int
offset
)
{
int
leapyear
;
time_t
value
;
int
i
;
int
d
;
int
m1
;
int
yy0
;
int
yy1
;
int
yy2
;
int
dow
;
value
=
0
;
leapyear
=
isleap
(
year
);
switch
(
rulep
->
r_type
)
{
case
JULIAN_DAY
:
/* Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
* years.
* In non-leap years, or if the day number is 59 or less, just
* add SECS_PER_DAY times the day number-1 to the time of
* January 1, midnight, to get the day. */
value
=
janfirst
+
(
rulep
->
r_day
-
1
)
*
SECS_PER_DAY
;
if
(
leapyear
&&
rulep
->
r_day
>=
60
)
value
+=
SECS_PER_DAY
;
break
;
case
DAY_OF_YEAR
:
/* n - day of year.
* Just add SECS_PER_DAY times the day number to the time of
* January 1, midnight, to get the day. */
value
=
janfirst
+
rulep
->
r_day
*
SECS_PER_DAY
;
break
;
case
MONTH_NTH_DAY_OF_WEEK
:
/* Mm.n.d - nth "dth day" of month m. */
value
=
janfirst
;
for
(
i
=
0
;
i
<
rulep
->
r_mon
-
1
;
i
++
)
value
+=
mon_lengths
[
leapyear
][
i
]
*
SECS_PER_DAY
;
/* Use Zeller's Congruence to get day-of-week of first day of month. */
m1
=
(
rulep
->
r_mon
+
9
)
%
12
+
1
;
yy0
=
(
rulep
->
r_mon
<=
2
)
?
(
year
-
1
)
:
year
;
yy1
=
yy0
/
100
;
yy2
=
yy0
%
100
;
dow
=
((
26
*
m1
-
2
)
/
10
+
1
+
yy2
+
yy2
/
4
+
yy1
/
4
-
2
*
yy1
)
%
7
;
if
(
dow
<
0
)
dow
+=
DAYS_PER_WEEK
;
/* "dow" is the day-of-week of the first day of the month. Get
* the day-of-month (zero-origin) of the first "dow" day of the
* month. */
d
=
rulep
->
r_day
-
dow
;
if
(
d
<
0
)
d
+=
DAYS_PER_WEEK
;
for
(
i
=
1
;
i
<
rulep
->
r_week
;
i
++
)
{
if
(
d
+
DAYS_PER_WEEK
>=
mon_lengths
[
leapyear
][
rulep
->
r_mon
-
1
])
break
;
d
+=
DAYS_PER_WEEK
;
}
/* "d" is the day-of-month (zero-origin) of the day we want. */
value
+=
d
*
SECS_PER_DAY
;
break
;
}
/* "value" is the Epoch-relative time of 00:00:00 UTC on the day in
* question. To get the Epoch-relative time of the specified local
* time on that day, add the transition time and the current offset
* from UTC. */
return
value
+
rulep
->
r_time
+
offset
;
}
/*- End of function --------------------------------------------------------*/
/* Given a POSIX section 8-style TZ string, fill in the rule tables as
appropriate. */
static
int
tzparse
(
const
char
*
name
,
struct
tz_state_s
*
const
sp
,
const
int
lastditch
)
{
const
char
*
stdname
;
const
char
*
dstname
;
size_t
stdlen
;
size_t
dstlen
;
long
int
stdoffset
;
long
int
dstoffset
;
long
int
theirstdoffset
;
long
int
theirdstoffset
;
long
int
theiroffset
;
unsigned
char
*
typep
;
char
*
cp
;
int
load_result
;
int
isdst
;
int
i
;
int
j
;
int
year
;
struct
tz_rule_s
start
;
struct
tz_rule_s
end
;
time_t
*
atp
;
time_t
janfirst
;
time_t
starttime
;
time_t
endtime
;
dstname
=
NULL
;
stdname
=
name
;
if
(
lastditch
)
{
stdlen
=
strlen
(
name
);
/* Length of standard zone name */
name
+=
stdlen
;
if
(
stdlen
>=
sizeof
(
sp
->
chars
))
stdlen
=
sizeof
(
sp
->
chars
)
-
1
;
stdoffset
=
0
;
}
else
{
name
=
get_tzname
(
name
);
stdlen
=
name
-
stdname
;
if
(
stdlen
<
3
)
return
-
1
;
if
(
*
name
==
'\0'
)
return
-
1
;
name
=
get_offset
(
name
,
&
stdoffset
);
if
(
name
==
NULL
)
return
-
1
;
}
load_result
=
-
1
;
if
(
load_result
!=
0
)
sp
->
leapcnt
=
0
;
/* So, we're off a little */
if
(
*
name
!=
'\0'
)
{
dstname
=
name
;
name
=
get_tzname
(
name
);
dstlen
=
name
-
dstname
;
/* Length of DST zone name */
if
(
dstlen
<
3
)
return
-
1
;
if
(
*
name
!=
'\0'
&&
*
name
!=
','
&&
*
name
!=
';'
)
{
if
((
name
=
get_offset
(
name
,
&
dstoffset
))
==
NULL
)
return
-
1
;
}
else
{
dstoffset
=
stdoffset
-
SECS_PER_HOUR
;
}
if
(
*
name
==
'\0'
&&
load_result
!=
0
)
name
=
TZ_DEF_RULE_STRING
;
if
(
*
name
==
','
||
*
name
==
';'
)
{
if
((
name
=
get_rule
(
name
+
1
,
&
start
))
==
NULL
)
return
-
1
;
if
(
*
name
++
!=
','
)
return
-
1
;
if
((
name
=
get_rule
(
name
,
&
end
))
==
NULL
)
return
-
1
;
if
(
*
name
!=
'\0'
)
return
-
1
;
sp
->
typecnt
=
2
;
/* Standard time and DST */
/* Two transitions per year, from EPOCH_YEAR to 2037. */
sp
->
timecnt
=
2
*
(
2037
-
EPOCH_YEAR
+
1
);
if
(
sp
->
timecnt
>
TZ_MAX_TIMES
)
return
-
1
;
sp
->
ttis
[
0
].
gmtoff
=
-
dstoffset
;
sp
->
ttis
[
0
].
isdst
=
1
;
sp
->
ttis
[
0
].
abbrind
=
stdlen
+
1
;
sp
->
ttis
[
1
].
gmtoff
=
-
stdoffset
;
sp
->
ttis
[
1
].
isdst
=
0
;
sp
->
ttis
[
1
].
abbrind
=
0
;
atp
=
sp
->
ats
;
typep
=
sp
->
types
;
janfirst
=
0
;
for
(
year
=
EPOCH_YEAR
;
year
<=
2037
;
year
++
)
{
starttime
=
trans_time
(
janfirst
,
year
,
&
start
,
stdoffset
);
endtime
=
trans_time
(
janfirst
,
year
,
&
end
,
dstoffset
);
if
(
starttime
>
endtime
)
{
*
atp
++
=
endtime
;
*
typep
++
=
1
;
/* DST ends */
*
atp
++
=
starttime
;
*
typep
++
=
0
;
/* DST begins */
}
else
{
*
atp
++
=
starttime
;
*
typep
++
=
0
;
/* DST begins */
*
atp
++
=
endtime
;
*
typep
++
=
1
;
/* DST ends */
}
janfirst
+=
year_lengths
[
isleap
(
year
)]
*
SECS_PER_DAY
;
}
}
else
{
if
(
*
name
!=
'\0'
)
return
-
1
;
/* Initial values of theirstdoffset and theirdstoffset. */
theirstdoffset
=
0
;
for
(
i
=
0
;
i
<
sp
->
timecnt
;
i
++
)
{
j
=
sp
->
types
[
i
];
if
(
!
sp
->
ttis
[
j
].
isdst
)
{
theirstdoffset
=
-
sp
->
ttis
[
j
].
gmtoff
;
break
;
}
}
theirdstoffset
=
0
;
for
(
i
=
0
;
i
<
sp
->
timecnt
;
i
++
)
{
j
=
sp
->
types
[
i
];
if
(
sp
->
ttis
[
j
].
isdst
)
{
theirdstoffset
=
-
sp
->
ttis
[
j
].
gmtoff
;
break
;
}
}
/* Initially we're assumed to be in standard time. */
isdst
=
FALSE
;
theiroffset
=
theirstdoffset
;
/* Now juggle transition times and types tracking offsets as you do. */
for
(
i
=
0
;
i
<
sp
->
timecnt
;
i
++
)
{
j
=
sp
->
types
[
i
];
sp
->
types
[
i
]
=
sp
->
ttis
[
j
].
isdst
;
if
(
sp
->
ttis
[
j
].
ttisgmt
)
{
/* No adjustment to transition time */
}
else
{
/* If summer time is in effect, and the
* transition time was not specified as
* standard time, add the summer time
* offset to the transition time;
* otherwise, add the standard time
* offset to the transition time. */
/* Transitions from DST to DDST
* will effectively disappear since
* POSIX provides for only one DST
* offset. */
if
(
isdst
&&
!
sp
->
ttis
[
j
].
ttisstd
)
sp
->
ats
[
i
]
+=
(
dstoffset
-
theirdstoffset
);
else
sp
->
ats
[
i
]
+=
(
stdoffset
-
theirstdoffset
);
}
theiroffset
=
-
sp
->
ttis
[
j
].
gmtoff
;
if
(
sp
->
ttis
[
j
].
isdst
)
theirdstoffset
=
theiroffset
;
else
theirstdoffset
=
theiroffset
;
}
/* Finally, fill in ttis. ttisstd and ttisgmt need not be handled. */
sp
->
ttis
[
0
].
gmtoff
=
-
stdoffset
;
sp
->
ttis
[
0
].
isdst
=
FALSE
;
sp
->
ttis
[
0
].
abbrind
=
0
;
sp
->
ttis
[
1
].
gmtoff
=
-
dstoffset
;
sp
->
ttis
[
1
].
isdst
=
TRUE
;
sp
->
ttis
[
1
].
abbrind
=
stdlen
+
1
;
sp
->
typecnt
=
2
;
}
}
else
{
dstlen
=
0
;
sp
->
typecnt
=
1
;
/* Only standard time */
sp
->
timecnt
=
0
;
sp
->
ttis
[
0
].
gmtoff
=
-
stdoffset
;
sp
->
ttis
[
0
].
isdst
=
0
;
sp
->
ttis
[
0
].
abbrind
=
0
;
}
sp
->
charcnt
=
stdlen
+
1
;
if
(
dstlen
!=
0
)
sp
->
charcnt
+=
dstlen
+
1
;
if
((
size_t
)
sp
->
charcnt
>
sizeof
(
sp
->
chars
))
return
-
1
;
cp
=
sp
->
chars
;
strncpy
(
cp
,
stdname
,
stdlen
);
cp
+=
stdlen
;
*
cp
++
=
'\0'
;
if
(
dstlen
!=
0
)
{
strncpy
(
cp
,
dstname
,
dstlen
);
cp
[
dstlen
]
=
'\0'
;
}
return
0
;
}
/*- End of function --------------------------------------------------------*/
static
void
tz_set
(
tz_t
*
tz
,
const
char
*
tzstring
)
{
const
char
*
name
=
""
;
struct
tz_state_s
*
lclptr
=
&
tz
->
state
;
if
(
tzstring
)
name
=
tzstring
;
/* See if we are already set OK */
if
(
tz
->
lcl_is_set
>
0
&&
strcmp
(
tz
->
lcl_tzname
,
name
)
==
0
)
return
;
tz
->
lcl_is_set
=
strlen
(
name
)
<
sizeof
(
tz
->
lcl_tzname
);
if
(
tz
->
lcl_is_set
)
strcpy
(
tz
->
lcl_tzname
,
name
);
if
(
name
[
0
]
==
'\0'
)
{
/* User wants it fast rather than right, so, we're off a little. */
lclptr
->
leapcnt
=
0
;
lclptr
->
timecnt
=
0
;
lclptr
->
typecnt
=
0
;
lclptr
->
ttis
[
0
].
isdst
=
0
;
lclptr
->
ttis
[
0
].
gmtoff
=
0
;
lclptr
->
ttis
[
0
].
abbrind
=
0
;
strcpy
(
lclptr
->
chars
,
gmt
);
}
else
if
(
name
[
0
]
==
':'
||
tzparse
(
name
,
lclptr
,
FALSE
)
!=
0
)
{
tzparse
(
gmt
,
lclptr
,
TRUE
);
}
set_tzname
(
tz
);
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE
(
int
)
tz_localtime
(
tz_t
*
tz
,
struct
tm
*
tmp
,
time_t
t
)
{
struct
tz_state_s
*
sp
;
const
struct
tz_ttinfo_s
*
ttisp
;
int
i
;
sp
=
&
tz
->
state
;
if
(
sp
->
timecnt
==
0
||
t
<
sp
->
ats
[
0
])
{
i
=
0
;
while
(
sp
->
ttis
[
i
].
isdst
)
{
if
(
++
i
>=
sp
->
typecnt
)
{
i
=
0
;
break
;
}
}
}
else
{
for
(
i
=
1
;
i
<
sp
->
timecnt
;
i
++
)
{
if
(
t
<
sp
->
ats
[
i
])
break
;
}
i
=
(
int
)
sp
->
types
[
i
-
1
];
}
ttisp
=
&
sp
->
ttis
[
i
];
time_sub
(
&
t
,
ttisp
->
gmtoff
,
sp
,
tmp
);
tmp
->
tm_isdst
=
ttisp
->
isdst
;
tz
->
tzname
[
tmp
->
tm_isdst
]
=
&
sp
->
chars
[
ttisp
->
abbrind
];
return
0
;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE
(
const
char
*
)
tz_tzname
(
tz_t
*
tz
,
int
isdst
)
{
return
tz
->
tzname
[(
!
isdst
)
?
0
:
1
];
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE
(
tz_t
*
)
tz_init
(
tz_t
*
tz
,
const
char
*
tzstring
)
{
if
(
tz
==
NULL
)
{
if
((
tz
=
(
tz_t
*
)
malloc
(
sizeof
(
*
tz
)))
==
NULL
)
return
NULL
;
}
memset
(
tz
,
0
,
sizeof
(
*
tz
));
tz
->
tzname
[
0
]
=
tz
->
tzname
[
1
]
=
wildabbr
;
tz_set
(
tz
,
tzstring
);
return
tz
;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE
(
int
)
tz_release
(
tz_t
*
tz
)
{
return
0
;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE
(
int
)
tz_free
(
tz_t
*
tz
)
{
if
(
tz
)
free
(
tz
);
return
0
;
}
/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/
libs/spandsp/test-data/itu/fax/generate_striped_pages.c
0 → 100644
浏览文件 @
ccbee256
/*
* SpanDSP - a series of DSP components for telephony
*
* generate_striped_pages.c
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2010 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 */
/*
This program generates an TIFF image as a number of small image striped, rather than
the usual all in one page FAX images usually consist of in TIFF files.
*/
#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
#include <stdio.h>
#include <inttypes.h>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <time.h>
#include <memory.h>
#include <string.h>
#if defined(HAVE_TGMATH_H)
#include <tgmath.h>
#endif
#if defined(HAVE_MATH_H)
#include <math.h>
#endif
#include <tiffio.h>
#include "spandsp.h"
#define IMAGE_WIDTH 1728
#define IMAGE_LENGTH 2600
#define ROWS_PER_STRIPE 37
int
main
(
int
argc
,
char
*
argv
[])
{
TIFF
*
tiff_file
;
uint8_t
image_buffer
[
10000
];
int
image_size
;
time_t
now
;
struct
tm
*
tm
;
char
buf
[
256
+
1
];
int
i
;
if
((
tiff_file
=
TIFFOpen
(
"striped.tif"
,
"w"
))
==
NULL
)
return
-
1
;
TIFFSetField
(
tiff_file
,
TIFFTAG_COMPRESSION
,
COMPRESSION_CCITT_T6
);
TIFFSetField
(
tiff_file
,
TIFFTAG_BITSPERSAMPLE
,
1
);
TIFFSetField
(
tiff_file
,
TIFFTAG_ORIENTATION
,
ORIENTATION_TOPLEFT
);
TIFFSetField
(
tiff_file
,
TIFFTAG_SAMPLESPERPIXEL
,
1
);
TIFFSetField
(
tiff_file
,
TIFFTAG_ROWSPERSTRIP
,
(
int32_t
)
ROWS_PER_STRIPE
);
TIFFSetField
(
tiff_file
,
TIFFTAG_PLANARCONFIG
,
PLANARCONFIG_CONTIG
);
TIFFSetField
(
tiff_file
,
TIFFTAG_PHOTOMETRIC
,
PHOTOMETRIC_MINISWHITE
);
TIFFSetField
(
tiff_file
,
TIFFTAG_FILLORDER
,
FILLORDER_LSB2MSB
);
TIFFSetField
(
tiff_file
,
TIFFTAG_XRESOLUTION
,
204
.
0
f
);
TIFFSetField
(
tiff_file
,
TIFFTAG_YRESOLUTION
,
196
.
0
f
);
TIFFSetField
(
tiff_file
,
TIFFTAG_RESOLUTIONUNIT
,
RESUNIT_INCH
);
TIFFSetField
(
tiff_file
,
TIFFTAG_SOFTWARE
,
"Spandsp"
);
TIFFSetField
(
tiff_file
,
TIFFTAG_HOSTCOMPUTER
,
"host"
);
TIFFSetField
(
tiff_file
,
TIFFTAG_FAXSUBADDRESS
,
"1111"
);
TIFFSetField
(
tiff_file
,
TIFFTAG_IMAGEDESCRIPTION
,
"Image in stripes"
);
TIFFSetField
(
tiff_file
,
TIFFTAG_MAKE
,
"spandsp"
);
TIFFSetField
(
tiff_file
,
TIFFTAG_MODEL
,
"testy"
);
time
(
&
now
);
tm
=
localtime
(
&
now
);
sprintf
(
buf
,
"%4d/%02d/%02d %02d:%02d:%02d"
,
tm
->
tm_year
+
1900
,
tm
->
tm_mon
+
1
,
tm
->
tm_mday
,
tm
->
tm_hour
,
tm
->
tm_min
,
tm
->
tm_sec
);
TIFFSetField
(
tiff_file
,
TIFFTAG_DATETIME
,
buf
);
TIFFSetField
(
tiff_file
,
TIFFTAG_FAXRECVTIME
,
10
);
TIFFSetField
(
tiff_file
,
TIFFTAG_IMAGEWIDTH
,
IMAGE_WIDTH
);
TIFFSetField
(
tiff_file
,
TIFFTAG_IMAGELENGTH
,
IMAGE_LENGTH
);
TIFFSetField
(
tiff_file
,
TIFFTAG_PAGENUMBER
,
0
,
1
);
image_size
=
IMAGE_WIDTH
*
ROWS_PER_STRIPE
/
8
;
memset
(
image_buffer
,
0x18
,
image_size
);
for
(
i
=
0
;
i
<
IMAGE_LENGTH
/
ROWS_PER_STRIPE
;
i
++
)
{
if
(
IMAGE_LENGTH
>
(
i
+
1
)
*
ROWS_PER_STRIPE
)
image_size
=
IMAGE_WIDTH
*
ROWS_PER_STRIPE
/
8
;
else
image_size
=
IMAGE_WIDTH
*
(
IMAGE_LENGTH
-
i
*
ROWS_PER_STRIPE
)
/
8
;
if
(
TIFFWriteEncodedStrip
(
tiff_file
,
i
,
image_buffer
,
image_size
)
<
0
)
return
-
1
;
}
TIFFWriteDirectory
(
tiff_file
);
TIFFClose
(
tiff_file
);
return
0
;
}
libs/spandsp/test-data/local/lenna-colour.tif
0 → 100644
浏览文件 @
ccbee256
File added
libs/spandsp/tests/bitstream_tests.c
0 → 100644
浏览文件 @
ccbee256
/*
* SpanDSP - a series of DSP components for telephony
*
* bitstream_tests.c
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2007 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.
*/
/*! \page bitstream_tests_page Bitstream tests
\section bitstream_tests_page_sec_1 What does it do?
\section bitstream_tests_page_sec_2 How is it used?
*/
#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <assert.h>
//#if defined(WITH_SPANDSP_INTERNALS)
#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
//#endif
#include "spandsp.h"
uint8_t
buffer
[
256
];
#define PATTERN 0x11111111
#define SEQUENCE_LENGTH 17
uint8_t
left
[]
=
{
0x28
,
/* 2 of 4, 3, 2, 1 */
0xC8
,
/* 1 of 6, 5, 2 of 4 */
0xAE
,
/* 3 of 7, 5 of 6 */
0x67
,
/* 4 of 8, 4 of 7 */
0x74
,
/* 4 of 9, 4 of 8 */
0x43
,
/* 3 of 10, 5 of 9 */
0x32
,
/* 1 of 11, 7 of 10 */
0xAA
,
/* 8 of 11 */
0xAE
,
/* 6 of 12, 2 of 11 */
0xED
,
/* 2 of 13, 6 of 12 */
0x99
,
/* 8 of 13 */
0x8E
,
/* 5 of 14, 3 of 13 */
0xEE
,
/* 8 of 14 */
0xEE
,
/* 7 of 15, 1 of 14 */
0xEE
,
/* 8 of 15 */
0xFF
,
/* 8 of 16 */
0xFF
,
/* 8 of 16 */
0x88
,
/* 8 of 17 */
0x88
,
/* 8 of 17 */
0x00
/* 1 of 17 */
};
uint8_t
right
[]
=
{
0xD2
,
/* 1, 2, 3, 2 of 4 */
0x90
,
/* 2 of 4, 5, 1 of 6 */
0xCA
,
/* 5 of 6, 3 of 7 */
0x7C
,
/* 4 of 7, 4 of 8 */
0x87
,
/* 4 of 8, 4 of 9 */
0x28
,
/* 5 of 9, 3 of 10 */
0x33
,
/* 7 of 10, 1 of 11 */
0x55
,
/* 8 of 11 */
0xED
,
/* 2 of 11, 6 of 12 */
0x2E
,
/* 6 of 12, 2 of 13 */
0x33
,
/* 8 of 13 */
0xEB
,
/* 3 of 13, 5 of 14 */
0xEE
,
/* 8 of 14 */
0xDC
,
/* 1 of 14, 7 of 15 */
0xDD
,
/* 8 of 15 */
0xFF
,
/* 8 of 16 */
0xFF
,
/* 8 of 16 */
0x10
,
/* 8 of 17 */
0x11
,
/* 8 of 17 */
0x01
/* 1 of 17 */
};
int
main
(
int
argc
,
char
*
argv
[])
{
int
i
;
bitstream_state_t
state
;
bitstream_state_t
*
s
;
const
uint8_t
*
r
;
uint8_t
*
w
;
uint8_t
*
cc
;
unsigned
int
x
;
int
total_bits
;
s
=
bitstream_init
(
&
state
,
TRUE
);
w
=
buffer
;
total_bits
=
0
;
for
(
i
=
0
;
i
<
SEQUENCE_LENGTH
;
i
++
)
{
bitstream_put
(
s
,
&
w
,
PATTERN
*
i
,
i
+
1
);
total_bits
+=
(
i
+
1
);
}
bitstream_flush
(
s
,
&
w
);
printf
(
"%d bits written
\n
"
,
total_bits
);
for
(
cc
=
buffer
;
cc
<
w
;
cc
++
)
printf
(
"%02X "
,
*
cc
);
printf
(
"
\n
"
);
for
(
cc
=
right
;
cc
<
right
+
sizeof
(
right
);
cc
++
)
printf
(
"%02X "
,
*
cc
);
printf
(
"
\n
"
);
if
((
w
-
buffer
)
!=
sizeof
(
right
)
||
memcmp
(
buffer
,
right
,
sizeof
(
right
)))
{
printf
(
"Test failed
\n
"
);
exit
(
2
);
}
s
=
bitstream_init
(
&
state
,
TRUE
);
r
=
buffer
;
for
(
i
=
0
;
i
<
SEQUENCE_LENGTH
;
i
++
)
{
x
=
bitstream_get
(
s
,
&
r
,
i
+
1
);
if
(
x
!=
((
PATTERN
*
i
)
&
((
1
<<
(
i
+
1
))
-
1
)))
{
printf
(
"Error 0x%X 0x%X
\n
"
,
x
,
((
PATTERN
*
i
)
&
((
1
<<
(
i
+
1
))
-
1
)));
printf
(
"Test failed
\n
"
);
exit
(
2
);
}
}
s
=
bitstream_init
(
&
state
,
FALSE
);
w
=
buffer
;
total_bits
=
0
;
for
(
i
=
0
;
i
<
SEQUENCE_LENGTH
;
i
++
)
{
bitstream_put
(
s
,
&
w
,
PATTERN
*
i
,
i
+
1
);
total_bits
+=
(
i
+
1
);
}
bitstream_flush
(
s
,
&
w
);
printf
(
"%d bits written
\n
"
,
total_bits
);
for
(
cc
=
buffer
;
cc
<
w
;
cc
++
)
printf
(
"%02X "
,
*
cc
);
printf
(
"
\n
"
);
for
(
cc
=
left
;
cc
<
left
+
sizeof
(
left
);
cc
++
)
printf
(
"%02X "
,
*
cc
);
printf
(
"
\n
"
);
if
((
w
-
buffer
)
!=
sizeof
(
left
)
||
memcmp
(
buffer
,
left
,
sizeof
(
left
)))
{
printf
(
"Test failed
\n
"
);
exit
(
2
);
}
s
=
bitstream_init
(
&
state
,
FALSE
);
r
=
buffer
;
for
(
i
=
0
;
i
<
SEQUENCE_LENGTH
;
i
++
)
{
x
=
bitstream_get
(
s
,
&
r
,
i
+
1
);
if
(
x
!=
((
PATTERN
*
i
)
&
((
1
<<
(
i
+
1
))
-
1
)))
{
printf
(
"Error 0x%X 0x%X
\n
"
,
x
,
((
PATTERN
*
i
)
&
((
1
<<
(
i
+
1
))
-
1
)));
printf
(
"Test failed
\n
"
);
exit
(
2
);
}
}
printf
(
"Tests passed.
\n
"
);
return
0
;
}
/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/
libs/spandsp/tests/image_translate_tests.c
0 → 100644
浏览文件 @
ccbee256
/*
* SpanDSP - a series of DSP components for telephony
*
* image_translate_tests.c - Tests for the image translation routines.
*
* 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 image_translate_tests_page Image translation tests
\section image_translate_tests_page_sec_1 What does it do?
*/
#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include <errno.h>
//#if defined(WITH_SPANDSP_INTERNALS)
#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
//#endif
#include "spandsp.h"
#define INPUT_TIFF_FILE_NAME "../test-data/local/lenna-colour.tif"
typedef
struct
{
const
uint8_t
*
image
;
int
width
;
int
length
;
int
current_row
;
int
bytes_per_pixel
;
}
image_descriptor_t
;
static
void
display_row
(
int
row
,
int
width
,
uint8_t
buf
[])
{
int
i
;
int
test_pixel
;
printf
(
"%3d: "
,
row
);
for
(
i
=
0
;
i
<
width
;
i
++
)
{
test_pixel
=
(
buf
[
i
>>
3
]
>>
(
7
-
(
i
&
7
)))
&
0x01
;
printf
(
"%c"
,
(
test_pixel
)
?
' '
:
'@'
);
}
printf
(
"
\n
"
);
}
/*- End of function --------------------------------------------------------*/
static
int
test_dithered_50_by_50
(
int
row
,
int
width
,
uint8_t
buf
[])
{
static
const
char
*
image
[
50
]
=
{
" 0: @ @ @ @ @ @ @ @@ @@@@@@@@@@@@@@"
,
" 1: @ @ @ @ @ @ @ @ @ @@ @@ @ @ @ @ @@@@"
,
" 2: @ @ @ @ @ @ @ @@ @ @ @@@ @@@@@@ @@"
,
" 3: @ @ @ @ @ @ @ @ @ @ @@@ @@@@ @@@@@@"
,
" 4: @ @ @ @ @ @ @ @ @ @@@ @ @@ @@@@ @@@@"
,
" 5: @ @ @ @ @ @ @ @ @ @ @ @ @@ @@@ @@@@@@"
,
" 6: @ @ @ @ @ @ @@ @@@@ @@@ @@@ @@ @"
,
" 7: @ @ @ @ @ @ @ @ @ @@ @@ @ @@ @@@@@@"
,
" 8: @ @ @ @ @ @ @ @ @@@ @@@@@@@@@ @@@"
,
" 9: @ @ @ @ @ @ @ @ @ @ @ @ @ @@ @ @ @ @@@@@"
,
" 10: @ @ @ @ @ @@ @ @@ @@@@@@@@@@@@@"
,
" 11: @ @ @ @ @ @ @ @ @ @@ @@ @ @ @@ @@ @@"
,
" 12: @ @ @ @ @ @ @ @ @ @@ @@@@@@ @@@@@@@"
,
" 13: @ @ @ @ @ @ @ @ @@ @ @ @ @ @@@@@ @@@"
,
" 14: @ @ @ @ @ @ @ @@ @@@ @@@ @ @@@@@@"
,
" 15: @ @ @ @ @ @ @ @ @ @ @ @ @@ @@@@@@@ @@"
,
" 16: @ @ @ @ @ @ @ @ @@ @@ @@ @@ @@@@@"
,
" 17: @ @ @ @ @ @ @ @ @ @@ @@ @@ @@ @@@@@@@"
,
" 18: @ @ @ @ @ @ @ @ @ @ @ @@ @@@@@ @ @@@"
,
" 19: @ @ @ @ @ @ @ @ @@@ @@@ @ @@@@@@@"
,
" 20: @ @ @ @ @ @ @ @ @ @@ @ @@ @@@@@@ @@@ @"
,
" 21: @ @ @ @ @ @ @ @@ @@ @ @ @@@@@@@"
,
" 22: @ @ @ @ @ @@ @ @ @ @ @@ @@@@@@@ @@ @@"
,
" 23: @ @ @ @ @ @ @ @@ @@ @@ @ @ @@@@@@@"
,
" 24: @ @ @ @ @@ @ @ @@ @ @ @@@@@@ @@@@@"
,
" 25: @ @ @ @ @ @ @ @ @ @ @@@@@ @ @@@@ @@"
,
" 26: @ @ @ @ @ @ @ @ @ @@ @ @ @@@@ @@@@@"
,
" 27: @ @ @ @ @ @ @ @ @ @@ @ @@ @@@ @@@@@@@"
,
" 28: @ @ @ @ @ @ @ @ @@@ @@@ @@@ @@ @@"
,
" 29: @ @ @ @ @ @ @ @ @@ @ @@ @ @@ @@@@@@@"
,
" 30: @ @ @ @ @ @ @ @ @ @ @ @@@@@@@ @@@@@"
,
" 31: @ @ @ @ @ @ @ @ @ @@@@ @ @ @@@@ @@"
,
" 32: @ @ @ @ @ @ @ @ @ @@ @ @ @@@@@@@ @@@@@"
,
" 33: @ @ @ @ @ @ @ @@@ @@ @ @ @@@@@@@"
,
" 34: @ @ @ @ @ @ @ @ @ @ @ @ @@ @@@@@@ @ @@@"
,
" 35: @ @ @ @ @ @ @ @ @ @@ @ @ @@@@@@@"
,
" 36: @ @ @ @ @ @ @ @ @@ @@@ @@@@@@@ @@@ @"
,
" 37: @ @ @ @ @ @ @ @ @ @ @@ @ @ @@@@@@@"
,
" 38: @ @ @ @ @ @ @ @ @@ @@ @@@@@@@ @@ @@"
,
" 39: @ @ @ @ @ @ @ @ @ @ @@ @@ @ @ @@@@@@@"
,
" 40: @ @ @ @ @ @ @ @ @ @@ @@ @@@@ @@@@@"
,
" 41: @ @ @ @ @ @ @ @ @ @@ @ @@ @@@ @@@@ @@"
,
" 42: @ @ @ @ @ @ @@ @@ @@ @@ @@@ @@@@@"
,
" 43: @ @ @ @ @ @ @ @ @ @ @@ @@@ @@@@@@@"
,
" 44: @ @ @ @ @ @ @ @ @ @ @@@ @@@ @@@ @@ @@"
,
" 45: @ @ @ @ @ @ @@ @ @ @ @@ @@@@@@@"
,
" 46: @ @ @ @ @ @ @ @ @ @ @ @@ @@@@@@@@@ @@@@@"
,
" 47: @ @ @ @ @ @ @ @ @ @@ @ @ @ @@@@ @@"
,
" 48: @ @ @ @ @ @ @@ @ @@ @@@@@@ @@@@@"
,
" 49: @ @ @ @ @ @ @ @ @ @ @ @@ @@ @ @ @@@@@@@"
};
int
i
;
int
match
;
int
ref_pixel
;
int
test_pixel
;
match
=
0
;
for
(
i
=
0
;
i
<
width
;
i
++
)
{
ref_pixel
=
(
image
[
row
][
i
+
5
]
==
' '
);
test_pixel
=
(
buf
[
i
>>
3
]
>>
(
7
-
(
i
&
7
)))
&
0x01
;
if
(
ref_pixel
!=
test_pixel
)
match
=
-
1
;
}
return
match
;
}
/*- End of function --------------------------------------------------------*/
static
int
row_read
(
void
*
user_data
,
uint8_t
buf
[],
size_t
len
)
{
image_descriptor_t
*
im
;
im
=
(
image_descriptor_t
*
)
user_data
;
if
(
im
->
current_row
>=
im
->
length
)
return
0
;
memcpy
(
buf
,
&
im
->
image
[
im
->
current_row
*
im
->
width
*
im
->
bytes_per_pixel
],
len
);
im
->
current_row
++
;
return
len
;
}
/*- End of function --------------------------------------------------------*/
static
void
get_flattened_image
(
image_translate_state_t
*
s
,
int
compare
)
{
int
i
;
int
len
;
uint8_t
row_buf
[
5000
];
for
(
i
=
0
;
i
<
s
->
output_length
;
i
++
)
{
if
((
len
=
image_translate_row
(
s
,
row_buf
,
(
s
->
output_width
+
7
)
/
8
))
!=
(
s
->
output_width
+
7
)
/
8
)
{
printf
(
"Image finished early - %d %d
\n
"
,
len
,
(
s
->
output_width
+
7
)
/
8
);
exit
(
2
);
}
display_row
(
i
,
s
->
output_width
,
row_buf
);
if
(
compare
)
{
if
(
test_dithered_50_by_50
(
i
,
s
->
output_width
,
row_buf
))
{
printf
(
"Dithered image mismatch at row %d
\n
"
,
i
);
printf
(
"Test failed
\n
"
);
exit
(
2
);
}
}
}
if
((
len
=
image_translate_row
(
s
,
row_buf
,
(
s
->
output_width
+
7
)
/
8
))
!=
0
)
{
printf
(
"Image finished late - %d %d
\n
"
,
len
,
(
s
->
output_width
+
7
)
/
8
);
exit
(
2
);
}
}
/*- End of function --------------------------------------------------------*/
static
void
dither_tests_gray16
(
void
)
{
int
i
;
int
j
;
image_translate_state_t
bw
;
image_translate_state_t
*
s
=
&
bw
;
uint16_t
image
[
50
*
50
];
image_descriptor_t
im
;
printf
(
"Dithering from a 16 bit per sample gray scale to bi-level
\n
"
);
im
.
image
=
(
const
uint8_t
*
)
image
;
im
.
width
=
50
;
im
.
length
=
50
;
im
.
bytes_per_pixel
=
2
;
im
.
current_row
=
0
;
for
(
i
=
0
;
i
<
im
.
length
;
i
++
)
{
for
(
j
=
0
;
j
<
im
.
width
;
j
++
)
image
[
i
*
im
.
width
+
j
]
=
j
*
1200
;
}
s
=
image_translate_init
(
s
,
IMAGE_TRANSLATE_FROM_GRAY_16
,
im
.
width
,
im
.
length
,
-
1
,
row_read
,
&
im
);
get_flattened_image
(
s
,
TRUE
);
}
/*- End of function --------------------------------------------------------*/
static
void
dither_tests_gray8
(
void
)
{
int
i
;
int
j
;
image_translate_state_t
bw
;
image_translate_state_t
*
s
=
&
bw
;
uint8_t
image
[
50
*
50
];
image_descriptor_t
im
;
printf
(
"Dithering from a 8 bit per sample gray scale to bi-level
\n
"
);
im
.
image
=
image
;
im
.
width
=
50
;
im
.
length
=
50
;
im
.
bytes_per_pixel
=
1
;
im
.
current_row
=
0
;
for
(
i
=
0
;
i
<
im
.
length
;
i
++
)
{
for
(
j
=
0
;
j
<
im
.
width
;
j
++
)
image
[
i
*
im
.
width
+
j
]
=
j
*
1200
/
256
;
}
s
=
image_translate_init
(
s
,
IMAGE_TRANSLATE_FROM_GRAY_8
,
im
.
width
,
im
.
length
,
-
1
,
row_read
,
&
im
);
get_flattened_image
(
s
,
TRUE
);
}
/*- End of function --------------------------------------------------------*/
static
void
dither_tests_colour16
(
void
)
{
int
i
;
int
j
;
image_translate_state_t
bw
;
image_translate_state_t
*
s
=
&
bw
;
uint16_t
image
[
50
*
50
*
3
];
image_descriptor_t
im
;
printf
(
"Dithering from a 3x16 bit per sample colour to bi-level
\n
"
);
im
.
image
=
(
const
uint8_t
*
)
image
;
im
.
width
=
50
;
im
.
length
=
50
;
im
.
bytes_per_pixel
=
6
;
im
.
current_row
=
0
;
for
(
i
=
0
;
i
<
im
.
length
;
i
++
)
{
for
(
j
=
0
;
j
<
im
.
width
;
j
++
)
{
image
[
i
*
3
*
im
.
width
+
3
*
j
+
0
]
=
j
*
1200
;
image
[
i
*
3
*
im
.
width
+
3
*
j
+
1
]
=
j
*
1200
;
image
[
i
*
3
*
im
.
width
+
3
*
j
+
2
]
=
j
*
1200
;
}
}
s
=
image_translate_init
(
s
,
IMAGE_TRANSLATE_FROM_COLOUR_16
,
im
.
width
,
im
.
length
,
-
1
,
row_read
,
&
im
);
get_flattened_image
(
s
,
TRUE
);
}
/*- End of function --------------------------------------------------------*/
static
void
dither_tests_colour8
(
void
)
{
int
i
;
int
j
;
image_translate_state_t
bw
;
image_translate_state_t
*
s
=
&
bw
;
uint8_t
image
[
50
*
50
*
3
];
image_descriptor_t
im
;
printf
(
"Dithering from a 3x8 bit per sample colour to bi-level
\n
"
);
im
.
image
=
image
;
im
.
width
=
50
;
im
.
length
=
50
;
im
.
bytes_per_pixel
=
3
;
im
.
current_row
=
0
;
for
(
i
=
0
;
i
<
im
.
length
;
i
++
)
{
for
(
j
=
0
;
j
<
im
.
width
;
j
++
)
{
image
[
i
*
3
*
im
.
width
+
3
*
j
+
0
]
=
j
*
1200
/
256
;
image
[
i
*
3
*
im
.
width
+
3
*
j
+
1
]
=
j
*
1200
/
256
;
image
[
i
*
3
*
im
.
width
+
3
*
j
+
2
]
=
j
*
1200
/
256
;
}
}
s
=
image_translate_init
(
s
,
IMAGE_TRANSLATE_FROM_COLOUR_8
,
im
.
width
,
im
.
length
,
-
1
,
row_read
,
&
im
);
get_flattened_image
(
s
,
TRUE
);
}
/*- End of function --------------------------------------------------------*/
static
void
grow_tests_colour8
(
void
)
{
int
i
;
int
j
;
image_translate_state_t
resize
;
image_translate_state_t
*
s1
=
&
resize
;
uint8_t
image
[
50
*
50
*
3
];
image_descriptor_t
im
;
printf
(
"Image growth tests
\n
"
);
im
.
image
=
image
;
im
.
width
=
50
;
im
.
length
=
50
;
im
.
bytes_per_pixel
=
3
;
im
.
current_row
=
0
;
for
(
i
=
0
;
i
<
im
.
length
;
i
++
)
{
for
(
j
=
0
;
j
<
im
.
width
;
j
++
)
{
image
[
i
*
3
*
im
.
width
+
3
*
j
+
0
]
=
j
*
1200
/
256
;
image
[
i
*
3
*
im
.
width
+
3
*
j
+
1
]
=
j
*
1200
/
256
;
image
[
i
*
3
*
im
.
width
+
3
*
j
+
2
]
=
j
*
1200
/
256
;
}
}
s1
=
image_translate_init
(
s1
,
IMAGE_TRANSLATE_FROM_COLOUR_8
,
im
.
width
,
im
.
length
,
200
,
row_read
,
&
im
);
get_flattened_image
(
s1
,
FALSE
);
}
/*- End of function --------------------------------------------------------*/
static
void
lenna_tests
(
int
output_width
,
const
char
*
file
)
{
TIFF
*
in_file
;
TIFF
*
out_file
;
int
image_width
;
int
image_length
;
int
output_length
;
uint8_t
*
image
;
uint8_t
*
image2
;
int
len
;
int
total
;
int16_t
bits_per_sample
;
int16_t
samples_per_pixel
;
int
i
;
int
n
;
image_translate_state_t
bw
;
image_translate_state_t
*
s
=
&
bw
;
image_descriptor_t
im
;
printf
(
"Dithering Lenna from colour to bi-level test
\n
"
);
if
((
in_file
=
TIFFOpen
(
INPUT_TIFF_FILE_NAME
,
"r"
))
==
NULL
)
return
;
image_width
=
0
;
TIFFGetField
(
in_file
,
TIFFTAG_IMAGEWIDTH
,
&
image_width
);
if
(
image_width
<=
0
)
return
;
image_length
=
0
;
TIFFGetField
(
in_file
,
TIFFTAG_IMAGELENGTH
,
&
image_length
);
if
(
image_length
<=
0
)
return
;
bits_per_sample
=
0
;
TIFFGetField
(
in_file
,
TIFFTAG_BITSPERSAMPLE
,
&
bits_per_sample
);
samples_per_pixel
=
0
;
TIFFGetField
(
in_file
,
TIFFTAG_SAMPLESPERPIXEL
,
&
samples_per_pixel
);
printf
(
"Original image is %d x %d, %d bits per sample, %d samples per pixel
\n
"
,
image_width
,
image_length
,
bits_per_sample
,
samples_per_pixel
);
if
((
image
=
malloc
(
image_width
*
image_length
*
samples_per_pixel
))
==
NULL
)
return
;
for
(
total
=
0
,
i
=
0
;
i
<
1000
;
i
++
)
{
len
=
TIFFReadEncodedStrip
(
in_file
,
i
,
&
image
[
total
],
image_width
*
image_length
*
samples_per_pixel
-
total
);
if
(
len
<=
0
)
break
;
total
+=
len
;
if
(
total
==
image_width
*
image_length
*
samples_per_pixel
)
{
printf
(
"Done
\n
"
);
break
;
}
}
printf
(
"Image size %d %d
\n
"
,
total
,
image_width
*
image_length
*
samples_per_pixel
);
TIFFClose
(
in_file
);
im
.
image
=
image
;
im
.
width
=
image_width
;
im
.
length
=
image_length
;
im
.
current_row
=
0
;
im
.
bytes_per_pixel
=
samples_per_pixel
;
s
=
image_translate_init
(
s
,
IMAGE_TRANSLATE_FROM_COLOUR_8
,
image_width
,
image_length
,
output_width
,
row_read
,
&
im
);
output_width
=
image_translate_get_output_width
(
s
);
output_length
=
image_translate_get_output_length
(
s
);
if
((
out_file
=
TIFFOpen
(
file
,
"w"
))
==
NULL
)
return
;
TIFFSetField
(
out_file
,
TIFFTAG_IMAGEWIDTH
,
output_width
);
TIFFSetField
(
out_file
,
TIFFTAG_IMAGELENGTH
,
output_length
);
TIFFSetField
(
out_file
,
TIFFTAG_BITSPERSAMPLE
,
1
);
TIFFSetField
(
out_file
,
TIFFTAG_ORIENTATION
,
ORIENTATION_TOPLEFT
);
TIFFSetField
(
out_file
,
TIFFTAG_SAMPLESPERPIXEL
,
1
);
TIFFSetField
(
out_file
,
TIFFTAG_ROWSPERSTRIP
,
-
1
);
TIFFSetField
(
out_file
,
TIFFTAG_PLANARCONFIG
,
PLANARCONFIG_CONTIG
);
TIFFSetField
(
out_file
,
TIFFTAG_PHOTOMETRIC
,
PHOTOMETRIC_MINISWHITE
);
TIFFSetField
(
out_file
,
TIFFTAG_FILLORDER
,
FILLORDER_LSB2MSB
);
TIFFSetField
(
out_file
,
TIFFTAG_PAGENUMBER
,
0
,
1
);
TIFFSetField
(
out_file
,
TIFFTAG_PHOTOMETRIC
,
PHOTOMETRIC_MINISWHITE
);
TIFFSetField
(
out_file
,
TIFFTAG_FILLORDER
,
FILLORDER_LSB2MSB
);
printf
(
"Input %d x %d, output %d x %d
\n
"
,
image_width
,
image_length
,
output_width
,
output_length
);
if
((
image2
=
malloc
(
output_width
*
output_length
/
8
))
==
NULL
)
return
;
memset
(
image2
,
0
,
output_width
*
output_length
/
8
);
n
=
0
;
for
(
i
=
0
;
i
<
output_length
;
i
++
)
n
+=
image_translate_row
(
s
,
&
image2
[
n
],
output_width
/
8
);
TIFFWriteEncodedStrip
(
out_file
,
0
,
image2
,
output_width
*
output_length
/
8
);
TIFFWriteDirectory
(
out_file
);
TIFFClose
(
out_file
);
}
/*- End of function --------------------------------------------------------*/
int
main
(
int
argc
,
char
**
argv
)
{
#if 1
dither_tests_gray16
();
dither_tests_gray8
();
dither_tests_colour16
();
dither_tests_colour8
();
#endif
#if 1
grow_tests_colour8
();
#endif
#if 1
lenna_tests
(
0
,
"lenna-bw.tif"
);
lenna_tests
(
1728
,
"lenna-bw-1728.tif"
);
lenna_tests
(
200
,
"lenna-bw-200.tif"
);
#endif
printf
(
"Tests passed.
\n
"
);
return
0
;
}
/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/
libs/spandsp/tests/saturated_tests.c
0 → 100644
浏览文件 @
ccbee256
/*
* SpanDSP - a series of DSP components for telephony
*
* saturated_tests.c
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2004 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.
*/
/*! \page saturated_tests_page Saturated arithmetic function tests
\section saturated_tests_page_sec_1 What does it do?
???.
\section saturated_tests_page_sec_2 How does it work?
???.
*/
#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
#include "spandsp.h"
int
main
(
int
argc
,
char
*
argv
[])
{
printf
(
"Testing 16 bit saturation
\n
"
);
if
(
saturate16
(
10000
)
!=
10000
||
saturate16
(
-
10000
)
!=
-
10000
||
saturate16
(
32767
)
!=
32767
||
saturate16
(
-
32768
)
!=
-
32768
||
saturate16
(
32768
)
!=
32767
||
saturate16
(
-
32769
)
!=
-
32768
)
{
printf
(
"Test failed.
\n
"
);
exit
(
2
);
}
printf
(
"Testing 15 bit saturation
\n
"
);
if
(
saturate15
(
10000
)
!=
10000
||
saturate15
(
-
10000
)
!=
-
10000
||
saturate15
(
16383
)
!=
16383
||
saturate15
(
-
16384
)
!=
-
16384
||
saturate15
(
16384
)
!=
16383
||
saturate15
(
-
16385
)
!=
-
16384
)
{
printf
(
"Test failed.
\n
"
);
exit
(
2
);
}
printf
(
"Testing 16 bit unsigned saturation
\n
"
);
if
(
saturateu16
(
10000
)
!=
10000
||
saturateu16
(
32767
)
!=
32767
||
saturateu16
(
65535
)
!=
65535
||
saturateu16
(
65536
)
!=
65535
)
{
printf
(
"Test failed.
\n
"
);
exit
(
2
);
}
printf
(
"Testing 8 bit unsigned saturation
\n
"
);
if
(
saturateu8
(
100
)
!=
100
||
saturateu8
(
127
)
!=
127
||
saturateu8
(
255
)
!=
255
||
saturateu8
(
256
)
!=
255
)
{
printf
(
"Test failed.
\n
"
);
exit
(
2
);
}
printf
(
"Testing 16 bit saturation from float
\n
"
);
if
(
fsaturatef
(
10000
.
0
f
)
!=
10000
||
fsaturatef
(
-
10000
.
0
f
)
!=
-
10000
||
fsaturatef
(
32767
.
0
f
)
!=
32767
||
fsaturatef
(
-
32768
.
0
f
)
!=
-
32768
||
fsaturatef
(
32768
.
0
f
)
!=
32767
||
fsaturatef
(
-
32769
.
0
f
)
!=
-
32768
)
{
printf
(
"Test failed.
\n
"
);
exit
(
2
);
}
printf
(
"Testing 16 bit saturation from double
\n
"
);
if
(
fsaturate
(
10000
.
0
)
!=
10000
||
fsaturate
(
-
10000
.
0
)
!=
-
10000
||
fsaturate
(
32767
.
0
)
!=
32767
||
fsaturate
(
-
32768
.
0
)
!=
-
32768
||
fsaturate
(
32768
.
0
)
!=
32767
||
fsaturate
(
-
32769
.
0
)
!=
-
32768
)
{
printf
(
"Test failed.
\n
"
);
exit
(
2
);
}
printf
(
"Testing 16 bit fast saturation from float
\n
"
);
if
(
ffastsaturatef
(
10000
.
0
f
)
!=
10000
||
ffastsaturatef
(
-
10000
.
0
f
)
!=
-
10000
||
ffastsaturatef
(
32767
.
0
f
)
!=
32767
||
ffastsaturatef
(
-
32768
.
0
f
)
!=
-
32768
||
ffastsaturatef
(
32768
.
0
f
)
!=
32767
||
ffastsaturatef
(
-
32769
.
0
f
)
!=
-
32768
)
{
printf
(
"Test failed.
\n
"
);
exit
(
2
);
}
printf
(
"Testing 16 bit fast saturation from double
\n
"
);
if
(
ffastsaturate
(
10000
.
0
)
!=
10000
||
ffastsaturate
(
-
10000
.
0
)
!=
-
10000
||
ffastsaturate
(
32767
.
0
)
!=
32767
||
ffastsaturate
(
-
32768
.
0
)
!=
-
32768
||
ffastsaturate
(
32768
.
0
)
!=
32767
||
ffastsaturate
(
-
32769
.
0
)
!=
-
32768
)
{
printf
(
"Test failed.
\n
"
);
exit
(
2
);
}
printf
(
"Testing 16 bit float saturation from float
\n
"
);
if
(
ffsaturatef
(
10000
.
0
f
)
!=
10000
.
0
f
||
ffsaturatef
(
-
10000
.
0
f
)
!=
-
10000
.
0
f
||
ffsaturatef
(
32767
.
0
f
)
!=
32767
.
0
f
||
ffsaturatef
(
-
32768
.
0
f
)
!=
-
32768
.
0
f
||
ffsaturatef
(
32768
.
0
f
)
!=
32767
.
0
f
||
ffsaturatef
(
-
32769
.
0
f
)
!=
-
32768
.
0
f
)
{
printf
(
"Test failed.
\n
"
);
exit
(
2
);
}
printf
(
"Testing 16 bit double saturation from double
\n
"
);
if
(
ffsaturate
(
10000
.
0
)
!=
10000
.
0
||
ffsaturate
(
-
10000
.
0
)
!=
-
10000
.
0
||
ffsaturate
(
32767
.
0
)
!=
32767
.
0
||
ffsaturate
(
-
32768
.
0
)
!=
-
32768
.
0
||
ffsaturate
(
32768
.
0
)
!=
32767
.
0
||
ffsaturate
(
-
32769
.
0
)
!=
-
32768
.
0
)
{
printf
(
"Test failed.
\n
"
);
exit
(
2
);
}
printf
(
"Testing 16 bit add
\n
"
);
if
(
saturated_add16
(
10000
,
10000
)
!=
20000
||
saturated_add16
(
10000
,
-
10000
)
!=
0
||
saturated_add16
(
-
10000
,
10000
)
!=
0
||
saturated_add16
(
-
10000
,
-
10000
)
!=
-
20000
||
saturated_add16
(
-
30000
,
-
30000
)
!=
INT16_MIN
||
saturated_add16
(
30000
,
30000
)
!=
INT16_MAX
)
{
printf
(
"Test failed.
\n
"
);
exit
(
2
);
}
printf
(
"Testing 32 bit add
\n
"
);
if
(
saturated_add32
(
10000
,
10000
)
!=
20000
||
saturated_add32
(
10000
,
-
10000
)
!=
0
||
saturated_add32
(
-
10000
,
10000
)
!=
0
||
saturated_add32
(
-
10000
,
-
10000
)
!=
-
20000
||
saturated_add32
(
-
2000000000
,
-
2000000000
)
!=
INT32_MIN
||
saturated_add32
(
2000000000
,
2000000000
)
!=
INT32_MAX
)
{
printf
(
"Test failed.
\n
"
);
exit
(
2
);
}
printf
(
"Testing 16 bit subtract
\n
"
);
if
(
saturated_sub16
(
10000
,
10000
)
!=
0
||
saturated_sub16
(
10000
,
-
10000
)
!=
20000
||
saturated_sub16
(
-
10000
,
10000
)
!=
-
20000
||
saturated_sub16
(
-
10000
,
-
10000
)
!=
0
||
saturated_sub16
(
-
30000
,
30000
)
!=
INT16_MIN
||
saturated_sub16
(
30000
,
-
30000
)
!=
INT16_MAX
)
{
printf
(
"Test failed.
\n
"
);
exit
(
2
);
}
printf
(
"Testing 32 bit subtract
\n
"
);
if
(
saturated_sub32
(
10000
,
10000
)
!=
0
||
saturated_sub32
(
10000
,
-
10000
)
!=
20000
||
saturated_sub32
(
-
10000
,
10000
)
!=
-
20000
||
saturated_sub32
(
-
10000
,
-
10000
)
!=
0
||
saturated_sub32
(
-
2000000000
,
2000000000
)
!=
INT32_MIN
||
saturated_sub32
(
2000000000
,
-
2000000000
)
!=
INT32_MAX
)
{
printf
(
"Test failed.
\n
"
);
exit
(
2
);
}
printf
(
"Testing 16 x 16 => 16 bit multiply
\n
"
);
if
(
saturated_mul16
(
100
,
100
)
!=
0
||
saturated_mul16
(
255
,
255
)
!=
1
||
saturated_mul16
(
32767
,
-
32768
)
!=
-
32767
||
saturated_mul16
(
-
32768
,
32767
)
!=
-
32767
||
saturated_mul16
(
32767
,
32767
)
!=
32766
||
saturated_mul16
(
-
32768
,
-
32768
)
!=
32767
)
{
printf
(
"Test failed.
\n
"
);
exit
(
2
);
}
printf
(
"Testing 16 x 16 => 32 bit multiply
\n
"
);
if
(
saturated_mul16_32
(
100
,
100
)
!=
20000
||
saturated_mul16_32
(
-
100
,
100
)
!=
-
20000
||
saturated_mul16_32
(
32767
,
-
32768
)
!=
-
2147418112
||
saturated_mul16_32
(
-
32768
,
32767
)
!=
-
2147418112
||
saturated_mul16_32
(
32767
,
32767
)
!=
2147352578
||
saturated_mul16_32
(
-
32768
,
-
32768
)
!=
-
2147483648
)
{
printf
(
"Test failed.
\n
"
);
exit
(
2
);
}
printf
(
"Testing 16 bit absolute
\n
"
);
if
(
saturated_abs16
(
10000
)
!=
10000
||
saturated_abs16
(
-
10000
)
!=
10000
||
saturated_abs16
(
32767
)
!=
32767
||
saturated_abs16
(
-
32768
)
!=
32767
)
{
printf
(
"Test failed.
\n
"
);
exit
(
2
);
}
printf
(
"Tests passed.
\n
"
);
return
0
;
}
/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/
libs/spandsp/tests/timezone_tests.c
0 → 100644
浏览文件 @
ccbee256
/*
* SpanDSP - a series of DSP components for telephony
*
* timezone_tests.c - Timezone handling for time interpretation
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2010 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.
*/
/*! \page timezone_tests_page Timezone handling tests
\section timezone_tests_page_sec_1 What does it do?
*/
#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
#include <stdlib.h>
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
//#if defined(WITH_SPANDSP_INTERNALS)
#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
//#endif
#include "spandsp.h"
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE (!FALSE)
#endif
int
main
(
int
argc
,
char
*
argv
[])
{
struct
tm
tms
;
struct
tm
*
tmp
=
&
tms
;
time_t
ltime
;
tz_t
*
tz
;
/* Get the current time */
ltime
=
time
(
NULL
);
/* Compute the local current time now for several localities, based on Posix tz strings */
tz
=
tz_init
(
NULL
,
"GMT0GMT0,M10.5.0,M3.5.0"
);
tz_localtime
(
tz
,
tmp
,
ltime
);
printf
(
"Local time is %02d:%02d:%02d
\n
"
,
tmp
->
tm_hour
,
tmp
->
tm_min
,
tmp
->
tm_sec
);
printf
(
"Time zone is %s
\n
"
,
tz_tzname
(
tz
,
tmp
->
tm_isdst
));
tz_init
(
tz
,
"CST-8CST-8,M10.5.0,M3.5.0"
);
tz_localtime
(
tz
,
tmp
,
ltime
);
printf
(
"Local time is %02d:%02d:%02d
\n
"
,
tmp
->
tm_hour
,
tmp
->
tm_min
,
tmp
->
tm_sec
);
printf
(
"Time zone is %s
\n
"
,
tz_tzname
(
tz
,
tmp
->
tm_isdst
));
tz_init
(
tz
,
"AEST-10AEDT-11,M10.5.0,M3.5.0"
);
tz_localtime
(
tz
,
tmp
,
ltime
);
printf
(
"Local time is %02d:%02d:%02d
\n
"
,
tmp
->
tm_hour
,
tmp
->
tm_min
,
tmp
->
tm_sec
);
printf
(
"Time zone is %s
\n
"
,
tz_tzname
(
tz
,
tmp
->
tm_isdst
));
tz_free
(
tz
);
return
0
;
}
/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/
libs/spandsp/tests/tsb85_extra_tests.sh
0 → 100755
浏览文件 @
ccbee256
#!/bin/sh
#
# spandsp fax tests
#
# 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 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.
run_tsb85_test
()
{
rm
-f
fax_tests_1.tif
echo
./tsb85_tests
${
TEST
}
./tsb85_tests
-x
../spandsp/fax-tests.xml
${
TEST
}
2>xyzzy2
RETVAL
=
$?
if
[
$RETVAL
!=
0
]
then
echo
tsb85_tests
${
TEST
}
failed!
exit
$RETVAL
fi
}
for
TEST
in
PPS-MPS-lost-PPS
;
do
run_tsb85_test
done
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论