Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
D
dlib
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
钟尚武
dlib
Commits
747088ea
Commit
747088ea
authored
Oct 01, 2014
by
Davis King
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added save_jpeg()
parent
3bef1e6b
Hide whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
7754 additions
and
1 deletion
+7754
-1
CMakeLists.txt
dlib/CMakeLists.txt
+21
-1
source.cpp
dlib/all/source.cpp
+1
-0
jcapimin.cpp
dlib/external/libjpeg/jcapimin.cpp
+280
-0
jcapistd.cpp
dlib/external/libjpeg/jcapistd.cpp
+161
-0
jccoefct.cpp
dlib/external/libjpeg/jccoefct.cpp
+449
-0
jccolor.cpp
dlib/external/libjpeg/jccolor.cpp
+459
-0
jcdctmgr.cpp
dlib/external/libjpeg/jcdctmgr.cpp
+387
-0
jchuff.cpp
dlib/external/libjpeg/jchuff.cpp
+909
-0
jchuff.h
dlib/external/libjpeg/jchuff.h
+47
-0
jcinit.cpp
dlib/external/libjpeg/jcinit.cpp
+72
-0
jcmainct.cpp
dlib/external/libjpeg/jcmainct.cpp
+293
-0
jcmarker.cpp
dlib/external/libjpeg/jcmarker.cpp
+664
-0
jcmaster.cpp
dlib/external/libjpeg/jcmaster.cpp
+590
-0
jcparam.cpp
dlib/external/libjpeg/jcparam.cpp
+610
-0
jcphuff.cpp
dlib/external/libjpeg/jcphuff.cpp
+833
-0
jcprepct.cpp
dlib/external/libjpeg/jcprepct.cpp
+354
-0
jcsample.cpp
dlib/external/libjpeg/jcsample.cpp
+519
-0
jdatadst.cpp
dlib/external/libjpeg/jdatadst.cpp
+151
-0
jfdctflt.cpp
dlib/external/libjpeg/jfdctflt.cpp
+168
-0
jfdctfst.cpp
dlib/external/libjpeg/jfdctfst.cpp
+224
-0
jfdctint.cpp
dlib/external/libjpeg/jfdctint.cpp
+283
-0
image_io.h
dlib/image_io.h
+1
-0
save_jpeg.cpp
dlib/image_saver/save_jpeg.cpp
+147
-0
save_jpeg.h
dlib/image_saver/save_jpeg.h
+82
-0
save_jpeg_abstract.h
dlib/image_saver/save_jpeg_abstract.h
+49
-0
No files found.
dlib/CMakeLists.txt
View file @
747088ea
...
@@ -294,10 +294,30 @@ if (NOT TARGET dlib)
...
@@ -294,10 +294,30 @@ if (NOT TARGET dlib)
external/libjpeg/jmemnobs.cpp
external/libjpeg/jmemnobs.cpp
external/libjpeg/jquant1.cpp
external/libjpeg/jquant1.cpp
external/libjpeg/jquant2.cpp
external/libjpeg/jquant2.cpp
external/libjpeg/jutils.cpp
)
external/libjpeg/jutils.cpp
external/libjpeg/jcapimin.cpp
external/libjpeg/jdatadst.cpp
external/libjpeg/jcparam.cpp
external/libjpeg/jcapistd.cpp
external/libjpeg/jcmarker.cpp
external/libjpeg/jcinit.cpp
external/libjpeg/jcmaster.cpp
external/libjpeg/jcdctmgr.cpp
external/libjpeg/jccoefct.cpp
external/libjpeg/jccolor.cpp
external/libjpeg/jchuff.cpp
external/libjpeg/jcmainct.cpp
external/libjpeg/jcphuff.cpp
external/libjpeg/jcprepct.cpp
external/libjpeg/jcsample.cpp
external/libjpeg/jfdctint.cpp
external/libjpeg/jfdctflt.cpp
external/libjpeg/jfdctfst.cpp
)
endif
()
endif
()
set
(
source_files
${
source_files
}
set
(
source_files
${
source_files
}
image_loader/jpeg_loader.cpp
image_loader/jpeg_loader.cpp
image_saver/save_jpeg.cpp
)
)
endif
()
endif
()
...
...
dlib/all/source.cpp
View file @
747088ea
...
@@ -57,6 +57,7 @@
...
@@ -57,6 +57,7 @@
#ifdef DLIB_JPEG_SUPPORT
#ifdef DLIB_JPEG_SUPPORT
#include "../image_loader/jpeg_loader.cpp"
#include "../image_loader/jpeg_loader.cpp"
#include "../image_saver/save_jpeg.cpp"
#endif
#endif
#ifndef DLIB_NO_GUI_SUPPORT
#ifndef DLIB_NO_GUI_SUPPORT
...
...
dlib/external/libjpeg/jcapimin.cpp
0 → 100644
View file @
747088ea
/*
* jcapimin.c
*
* Copyright (C) 1994-1998, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains application interface code for the compression half
* of the JPEG library. These are the "minimum" API routines that may be
* needed in either the normal full-compression case or the transcoding-only
* case.
*
* Most of the routines intended to be called directly by an application
* are in this file or in jcapistd.c. But also see jcparam.c for
* parameter-setup helper routines, jcomapi.c for routines shared by
* compression and decompression, and jctrans.c for the transcoding case.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/*
* Initialization of a JPEG compression object.
* The error manager must already be set up (in case memory manager fails).
*/
GLOBAL
(
void
)
jpeg_CreateCompress
(
j_compress_ptr
cinfo
,
int
version
,
size_t
structsize
)
{
int
i
;
/* Guard against version mismatches between library and caller. */
cinfo
->
mem
=
NULL
;
/* so jpeg_destroy knows mem mgr not called */
if
(
version
!=
JPEG_LIB_VERSION
)
ERREXIT2
(
cinfo
,
JERR_BAD_LIB_VERSION
,
JPEG_LIB_VERSION
,
version
);
if
(
structsize
!=
SIZEOF
(
struct
jpeg_compress_struct
))
ERREXIT2
(
cinfo
,
JERR_BAD_STRUCT_SIZE
,
(
int
)
SIZEOF
(
struct
jpeg_compress_struct
),
(
int
)
structsize
);
/* For debugging purposes, we zero the whole master structure.
* But the application has already set the err pointer, and may have set
* client_data, so we have to save and restore those fields.
* Note: if application hasn't set client_data, tools like Purify may
* complain here.
*/
{
struct
jpeg_error_mgr
*
err
=
cinfo
->
err
;
void
*
client_data
=
cinfo
->
client_data
;
/* ignore Purify complaint here */
MEMZERO
(
cinfo
,
SIZEOF
(
struct
jpeg_compress_struct
));
cinfo
->
err
=
err
;
cinfo
->
client_data
=
client_data
;
}
cinfo
->
is_decompressor
=
FALSE
;
/* Initialize a memory manager instance for this object */
jinit_memory_mgr
((
j_common_ptr
)
cinfo
);
/* Zero out pointers to permanent structures. */
cinfo
->
progress
=
NULL
;
cinfo
->
dest
=
NULL
;
cinfo
->
comp_info
=
NULL
;
for
(
i
=
0
;
i
<
NUM_QUANT_TBLS
;
i
++
)
cinfo
->
quant_tbl_ptrs
[
i
]
=
NULL
;
for
(
i
=
0
;
i
<
NUM_HUFF_TBLS
;
i
++
)
{
cinfo
->
dc_huff_tbl_ptrs
[
i
]
=
NULL
;
cinfo
->
ac_huff_tbl_ptrs
[
i
]
=
NULL
;
}
cinfo
->
script_space
=
NULL
;
cinfo
->
input_gamma
=
1.0
;
/* in case application forgets */
/* OK, I'm ready */
cinfo
->
global_state
=
CSTATE_START
;
}
/*
* Destruction of a JPEG compression object
*/
GLOBAL
(
void
)
jpeg_destroy_compress
(
j_compress_ptr
cinfo
)
{
jpeg_destroy
((
j_common_ptr
)
cinfo
);
/* use common routine */
}
/*
* Abort processing of a JPEG compression operation,
* but don't destroy the object itself.
*/
GLOBAL
(
void
)
jpeg_abort_compress
(
j_compress_ptr
cinfo
)
{
jpeg_abort
((
j_common_ptr
)
cinfo
);
/* use common routine */
}
/*
* Forcibly suppress or un-suppress all quantization and Huffman tables.
* Marks all currently defined tables as already written (if suppress)
* or not written (if !suppress). This will control whether they get emitted
* by a subsequent jpeg_start_compress call.
*
* This routine is exported for use by applications that want to produce
* abbreviated JPEG datastreams. It logically belongs in jcparam.c, but
* since it is called by jpeg_start_compress, we put it here --- otherwise
* jcparam.o would be linked whether the application used it or not.
*/
GLOBAL
(
void
)
jpeg_suppress_tables
(
j_compress_ptr
cinfo
,
int
suppress
)
{
int
i
;
JQUANT_TBL
*
qtbl
;
JHUFF_TBL
*
htbl
;
for
(
i
=
0
;
i
<
NUM_QUANT_TBLS
;
i
++
)
{
if
((
qtbl
=
cinfo
->
quant_tbl_ptrs
[
i
])
!=
NULL
)
qtbl
->
sent_table
=
suppress
;
}
for
(
i
=
0
;
i
<
NUM_HUFF_TBLS
;
i
++
)
{
if
((
htbl
=
cinfo
->
dc_huff_tbl_ptrs
[
i
])
!=
NULL
)
htbl
->
sent_table
=
suppress
;
if
((
htbl
=
cinfo
->
ac_huff_tbl_ptrs
[
i
])
!=
NULL
)
htbl
->
sent_table
=
suppress
;
}
}
/*
* Finish JPEG compression.
*
* If a multipass operating mode was selected, this may do a great deal of
* work including most of the actual output.
*/
GLOBAL
(
void
)
jpeg_finish_compress
(
j_compress_ptr
cinfo
)
{
JDIMENSION
iMCU_row
;
if
(
cinfo
->
global_state
==
CSTATE_SCANNING
||
cinfo
->
global_state
==
CSTATE_RAW_OK
)
{
/* Terminate first pass */
if
(
cinfo
->
next_scanline
<
cinfo
->
image_height
)
ERREXIT
(
cinfo
,
JERR_TOO_LITTLE_DATA
);
(
*
cinfo
->
master
->
finish_pass
)
(
cinfo
);
}
else
if
(
cinfo
->
global_state
!=
CSTATE_WRCOEFS
)
ERREXIT1
(
cinfo
,
JERR_BAD_STATE
,
cinfo
->
global_state
);
/* Perform any remaining passes */
while
(
!
cinfo
->
master
->
is_last_pass
)
{
(
*
cinfo
->
master
->
prepare_for_pass
)
(
cinfo
);
for
(
iMCU_row
=
0
;
iMCU_row
<
cinfo
->
total_iMCU_rows
;
iMCU_row
++
)
{
if
(
cinfo
->
progress
!=
NULL
)
{
cinfo
->
progress
->
pass_counter
=
(
long
)
iMCU_row
;
cinfo
->
progress
->
pass_limit
=
(
long
)
cinfo
->
total_iMCU_rows
;
(
*
cinfo
->
progress
->
progress_monitor
)
((
j_common_ptr
)
cinfo
);
}
/* We bypass the main controller and invoke coef controller directly;
* all work is being done from the coefficient buffer.
*/
if
(
!
(
*
cinfo
->
coef
->
compress_data
)
(
cinfo
,
(
JSAMPIMAGE
)
NULL
))
ERREXIT
(
cinfo
,
JERR_CANT_SUSPEND
);
}
(
*
cinfo
->
master
->
finish_pass
)
(
cinfo
);
}
/* Write EOI, do final cleanup */
(
*
cinfo
->
marker
->
write_file_trailer
)
(
cinfo
);
(
*
cinfo
->
dest
->
term_destination
)
(
cinfo
);
/* We can use jpeg_abort to release memory and reset global_state */
jpeg_abort
((
j_common_ptr
)
cinfo
);
}
/*
* Write a special marker.
* This is only recommended for writing COM or APPn markers.
* Must be called after jpeg_start_compress() and before
* first call to jpeg_write_scanlines() or jpeg_write_raw_data().
*/
GLOBAL
(
void
)
jpeg_write_marker
(
j_compress_ptr
cinfo
,
int
marker
,
const
JOCTET
*
dataptr
,
unsigned
int
datalen
)
{
JMETHOD
(
void
,
write_marker_byte
,
(
j_compress_ptr
info
,
int
val
));
if
(
cinfo
->
next_scanline
!=
0
||
(
cinfo
->
global_state
!=
CSTATE_SCANNING
&&
cinfo
->
global_state
!=
CSTATE_RAW_OK
&&
cinfo
->
global_state
!=
CSTATE_WRCOEFS
))
ERREXIT1
(
cinfo
,
JERR_BAD_STATE
,
cinfo
->
global_state
);
(
*
cinfo
->
marker
->
write_marker_header
)
(
cinfo
,
marker
,
datalen
);
write_marker_byte
=
cinfo
->
marker
->
write_marker_byte
;
/* copy for speed */
while
(
datalen
--
)
{
(
*
write_marker_byte
)
(
cinfo
,
*
dataptr
);
dataptr
++
;
}
}
/* Same, but piecemeal. */
GLOBAL
(
void
)
jpeg_write_m_header
(
j_compress_ptr
cinfo
,
int
marker
,
unsigned
int
datalen
)
{
if
(
cinfo
->
next_scanline
!=
0
||
(
cinfo
->
global_state
!=
CSTATE_SCANNING
&&
cinfo
->
global_state
!=
CSTATE_RAW_OK
&&
cinfo
->
global_state
!=
CSTATE_WRCOEFS
))
ERREXIT1
(
cinfo
,
JERR_BAD_STATE
,
cinfo
->
global_state
);
(
*
cinfo
->
marker
->
write_marker_header
)
(
cinfo
,
marker
,
datalen
);
}
GLOBAL
(
void
)
jpeg_write_m_byte
(
j_compress_ptr
cinfo
,
int
val
)
{
(
*
cinfo
->
marker
->
write_marker_byte
)
(
cinfo
,
val
);
}
/*
* Alternate compression function: just write an abbreviated table file.
* Before calling this, all parameters and a data destination must be set up.
*
* To produce a pair of files containing abbreviated tables and abbreviated
* image data, one would proceed as follows:
*
* initialize JPEG object
* set JPEG parameters
* set destination to table file
* jpeg_write_tables(cinfo);
* set destination to image file
* jpeg_start_compress(cinfo, FALSE);
* write data...
* jpeg_finish_compress(cinfo);
*
* jpeg_write_tables has the side effect of marking all tables written
* (same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress
* will not re-emit the tables unless it is passed write_all_tables=TRUE.
*/
GLOBAL
(
void
)
jpeg_write_tables
(
j_compress_ptr
cinfo
)
{
if
(
cinfo
->
global_state
!=
CSTATE_START
)
ERREXIT1
(
cinfo
,
JERR_BAD_STATE
,
cinfo
->
global_state
);
/* (Re)initialize error mgr and destination modules */
(
*
cinfo
->
err
->
reset_error_mgr
)
((
j_common_ptr
)
cinfo
);
(
*
cinfo
->
dest
->
init_destination
)
(
cinfo
);
/* Initialize the marker writer ... bit of a crock to do it here. */
jinit_marker_writer
(
cinfo
);
/* Write them tables! */
(
*
cinfo
->
marker
->
write_tables_only
)
(
cinfo
);
/* And clean up. */
(
*
cinfo
->
dest
->
term_destination
)
(
cinfo
);
/*
* In library releases up through v6a, we called jpeg_abort() here to free
* any working memory allocated by the destination manager and marker
* writer. Some applications had a problem with that: they allocated space
* of their own from the library memory manager, and didn't want it to go
* away during write_tables. So now we do nothing. This will cause a
* memory leak if an app calls write_tables repeatedly without doing a full
* compression cycle or otherwise resetting the JPEG object. However, that
* seems less bad than unexpectedly freeing memory in the normal case.
* An app that prefers the old behavior can call jpeg_abort for itself after
* each call to jpeg_write_tables().
*/
}
dlib/external/libjpeg/jcapistd.cpp
0 → 100644
View file @
747088ea
/*
* jcapistd.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains application interface code for the compression half
* of the JPEG library. These are the "standard" API routines that are
* used in the normal full-compression case. They are not used by a
* transcoding-only application. Note that if an application links in
* jpeg_start_compress, it will end up linking in the entire compressor.
* We thus must separate this file from jcapimin.c to avoid linking the
* whole compression library into a transcoder.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/*
* Compression initialization.
* Before calling this, all parameters and a data destination must be set up.
*
* We require a write_all_tables parameter as a failsafe check when writing
* multiple datastreams from the same compression object. Since prior runs
* will have left all the tables marked sent_table=TRUE, a subsequent run
* would emit an abbreviated stream (no tables) by default. This may be what
* is wanted, but for safety's sake it should not be the default behavior:
* programmers should have to make a deliberate choice to emit abbreviated
* images. Therefore the documentation and examples should encourage people
* to pass write_all_tables=TRUE; then it will take active thought to do the
* wrong thing.
*/
GLOBAL
(
void
)
jpeg_start_compress
(
j_compress_ptr
cinfo
,
int
write_all_tables
)
{
if
(
cinfo
->
global_state
!=
CSTATE_START
)
ERREXIT1
(
cinfo
,
JERR_BAD_STATE
,
cinfo
->
global_state
);
if
(
write_all_tables
)
jpeg_suppress_tables
(
cinfo
,
FALSE
);
/* mark all tables to be written */
/* (Re)initialize error mgr and destination modules */
(
*
cinfo
->
err
->
reset_error_mgr
)
((
j_common_ptr
)
cinfo
);
(
*
cinfo
->
dest
->
init_destination
)
(
cinfo
);
/* Perform master selection of active modules */
jinit_compress_master
(
cinfo
);
/* Set up for the first pass */
(
*
cinfo
->
master
->
prepare_for_pass
)
(
cinfo
);
/* Ready for application to drive first pass through jpeg_write_scanlines
* or jpeg_write_raw_data.
*/
cinfo
->
next_scanline
=
0
;
cinfo
->
global_state
=
(
cinfo
->
raw_data_in
?
CSTATE_RAW_OK
:
CSTATE_SCANNING
);
}
/*
* Write some scanlines of data to the JPEG compressor.
*
* The return value will be the number of lines actually written.
* This should be less than the supplied num_lines only in case that
* the data destination module has requested suspension of the compressor,
* or if more than image_height scanlines are passed in.
*
* Note: we warn about excess calls to jpeg_write_scanlines() since
* this likely signals an application programmer error. However,
* excess scanlines passed in the last valid call are *silently* ignored,
* so that the application need not adjust num_lines for end-of-image
* when using a multiple-scanline buffer.
*/
GLOBAL
(
JDIMENSION
)
jpeg_write_scanlines
(
j_compress_ptr
cinfo
,
JSAMPARRAY
scanlines
,
JDIMENSION
num_lines
)
{
JDIMENSION
row_ctr
,
rows_left
;
if
(
cinfo
->
global_state
!=
CSTATE_SCANNING
)
ERREXIT1
(
cinfo
,
JERR_BAD_STATE
,
cinfo
->
global_state
);
if
(
cinfo
->
next_scanline
>=
cinfo
->
image_height
)
WARNMS
(
cinfo
,
JWRN_TOO_MUCH_DATA
);
/* Call progress monitor hook if present */
if
(
cinfo
->
progress
!=
NULL
)
{
cinfo
->
progress
->
pass_counter
=
(
long
)
cinfo
->
next_scanline
;
cinfo
->
progress
->
pass_limit
=
(
long
)
cinfo
->
image_height
;
(
*
cinfo
->
progress
->
progress_monitor
)
((
j_common_ptr
)
cinfo
);
}
/* Give master control module another chance if this is first call to
* jpeg_write_scanlines. This lets output of the frame/scan headers be
* delayed so that application can write COM, etc, markers between
* jpeg_start_compress and jpeg_write_scanlines.
*/
if
(
cinfo
->
master
->
call_pass_startup
)
(
*
cinfo
->
master
->
pass_startup
)
(
cinfo
);
/* Ignore any extra scanlines at bottom of image. */
rows_left
=
cinfo
->
image_height
-
cinfo
->
next_scanline
;
if
(
num_lines
>
rows_left
)
num_lines
=
rows_left
;
row_ctr
=
0
;
(
*
cinfo
->
main
->
process_data
)
(
cinfo
,
scanlines
,
&
row_ctr
,
num_lines
);
cinfo
->
next_scanline
+=
row_ctr
;
return
row_ctr
;
}
/*
* Alternate entry point to write raw data.
* Processes exactly one iMCU row per call, unless suspended.
*/
GLOBAL
(
JDIMENSION
)
jpeg_write_raw_data
(
j_compress_ptr
cinfo
,
JSAMPIMAGE
data
,
JDIMENSION
num_lines
)
{
JDIMENSION
lines_per_iMCU_row
;
if
(
cinfo
->
global_state
!=
CSTATE_RAW_OK
)
ERREXIT1
(
cinfo
,
JERR_BAD_STATE
,
cinfo
->
global_state
);
if
(
cinfo
->
next_scanline
>=
cinfo
->
image_height
)
{
WARNMS
(
cinfo
,
JWRN_TOO_MUCH_DATA
);
return
0
;
}
/* Call progress monitor hook if present */
if
(
cinfo
->
progress
!=
NULL
)
{
cinfo
->
progress
->
pass_counter
=
(
long
)
cinfo
->
next_scanline
;
cinfo
->
progress
->
pass_limit
=
(
long
)
cinfo
->
image_height
;
(
*
cinfo
->
progress
->
progress_monitor
)
((
j_common_ptr
)
cinfo
);
}
/* Give master control module another chance if this is first call to
* jpeg_write_raw_data. This lets output of the frame/scan headers be
* delayed so that application can write COM, etc, markers between
* jpeg_start_compress and jpeg_write_raw_data.
*/
if
(
cinfo
->
master
->
call_pass_startup
)
(
*
cinfo
->
master
->
pass_startup
)
(
cinfo
);
/* Verify that at least one iMCU row has been passed. */
lines_per_iMCU_row
=
cinfo
->
max_v_samp_factor
*
DCTSIZE
;
if
(
num_lines
<
lines_per_iMCU_row
)
ERREXIT
(
cinfo
,
JERR_BUFFER_SIZE
);
/* Directly compress the row. */
if
(
!
(
*
cinfo
->
coef
->
compress_data
)
(
cinfo
,
data
))
{
/* If compressor did not consume the whole row, suspend processing. */
return
0
;
}
/* OK, we processed one iMCU row. */
cinfo
->
next_scanline
+=
lines_per_iMCU_row
;
return
lines_per_iMCU_row
;
}
dlib/external/libjpeg/jccoefct.cpp
0 → 100644
View file @
747088ea
/*
* jccoefct.c
*
* Copyright (C) 1994-1997, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains the coefficient buffer controller for compression.
* This controller is the top level of the JPEG compressor proper.
* The coefficient buffer lies between forward-DCT and entropy encoding steps.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/* We use a full-image coefficient buffer when doing Huffman optimization,
* and also for writing multiple-scan JPEG files. In all cases, the DCT
* step is run during the first pass, and subsequent passes need only read
* the buffered coefficients.
*/
#ifdef ENTROPY_OPT_SUPPORTED
#define FULL_COEF_BUFFER_SUPPORTED
#else
#ifdef C_MULTISCAN_FILES_SUPPORTED
#define FULL_COEF_BUFFER_SUPPORTED
#endif
#endif
/* Private buffer controller object */
typedef
struct
{
struct
jpeg_c_coef_controller
pub
;
/* public fields */
JDIMENSION
iMCU_row_num
;
/* iMCU row # within image */
JDIMENSION
mcu_ctr
;
/* counts MCUs processed in current row */
int
MCU_vert_offset
;
/* counts MCU rows within iMCU row */
int
MCU_rows_per_iMCU_row
;
/* number of such rows needed */
/* For single-pass compression, it's sufficient to buffer just one MCU
* (although this may prove a bit slow in practice). We allocate a
* workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it for each
* MCU constructed and sent. (On 80x86, the workspace is FAR even though
* it's not really very big; this is to keep the module interfaces unchanged
* when a large coefficient buffer is necessary.)
* In multi-pass modes, this array points to the current MCU's blocks
* within the virtual arrays.
*/
JBLOCKROW
MCU_buffer
[
C_MAX_BLOCKS_IN_MCU
];
/* In multi-pass modes, we need a virtual block array for each component. */
jvirt_barray_ptr
whole_image
[
MAX_COMPONENTS
];
}
my_coef_controller
;
typedef
my_coef_controller
*
my_coef_ptr
;
/* Forward declarations */
METHODDEF
(
int
)
compress_data
JPP
((
j_compress_ptr
cinfo
,
JSAMPIMAGE
input_buf
));
#ifdef FULL_COEF_BUFFER_SUPPORTED
METHODDEF
(
int
)
compress_first_pass
JPP
((
j_compress_ptr
cinfo
,
JSAMPIMAGE
input_buf
));
METHODDEF
(
int
)
compress_output
JPP
((
j_compress_ptr
cinfo
,
JSAMPIMAGE
input_buf
));
#endif
LOCAL
(
void
)
start_iMCU_row
(
j_compress_ptr
cinfo
)
/* Reset within-iMCU-row counters for a new row */
{
my_coef_ptr
coef
=
(
my_coef_ptr
)
cinfo
->
coef
;
/* In an interleaved scan, an MCU row is the same as an iMCU row.
* In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
* But at the bottom of the image, process only what's left.
*/
if
(
cinfo
->
comps_in_scan
>
1
)
{
coef
->
MCU_rows_per_iMCU_row
=
1
;
}
else
{
if
(
coef
->
iMCU_row_num
<
(
cinfo
->
total_iMCU_rows
-
1
))
coef
->
MCU_rows_per_iMCU_row
=
cinfo
->
cur_comp_info
[
0
]
->
v_samp_factor
;
else
coef
->
MCU_rows_per_iMCU_row
=
cinfo
->
cur_comp_info
[
0
]
->
last_row_height
;
}
coef
->
mcu_ctr
=
0
;
coef
->
MCU_vert_offset
=
0
;
}
/*
* Initialize for a processing pass.
*/
METHODDEF
(
void
)
start_pass_coef
(
j_compress_ptr
cinfo
,
J_BUF_MODE
pass_mode
)
{
my_coef_ptr
coef
=
(
my_coef_ptr
)
cinfo
->
coef
;
coef
->
iMCU_row_num
=
0
;
start_iMCU_row
(
cinfo
);
switch
(
pass_mode
)
{
case
JBUF_PASS_THRU
:
if
(
coef
->
whole_image
[
0
]
!=
NULL
)
ERREXIT
(
cinfo
,
JERR_BAD_BUFFER_MODE
);
coef
->
pub
.
compress_data
=
compress_data
;
break
;
#ifdef FULL_COEF_BUFFER_SUPPORTED
case
JBUF_SAVE_AND_PASS
:
if
(
coef
->
whole_image
[
0
]
==
NULL
)
ERREXIT
(
cinfo
,
JERR_BAD_BUFFER_MODE
);
coef
->
pub
.
compress_data
=
compress_first_pass
;
break
;
case
JBUF_CRANK_DEST
:
if
(
coef
->
whole_image
[
0
]
==
NULL
)
ERREXIT
(
cinfo
,
JERR_BAD_BUFFER_MODE
);
coef
->
pub
.
compress_data
=
compress_output
;
break
;
#endif
default
:
ERREXIT
(
cinfo
,
JERR_BAD_BUFFER_MODE
);
break
;
}
}
/*
* Process some data in the single-pass case.
* We process the equivalent of one fully interleaved MCU row ("iMCU" row)
* per call, ie, v_samp_factor block rows for each component in the image.
* Returns TRUE if the iMCU row is completed, FALSE if suspended.
*
* NB: input_buf contains a plane for each component in image,
* which we index according to the component's SOF position.
*/
METHODDEF
(
int
)
compress_data
(
j_compress_ptr
cinfo
,
JSAMPIMAGE
input_buf
)
{
my_coef_ptr
coef
=
(
my_coef_ptr
)
cinfo
->
coef
;
JDIMENSION
MCU_col_num
;
/* index of current MCU within row */
JDIMENSION
last_MCU_col
=
cinfo
->
MCUs_per_row
-
1
;
JDIMENSION
last_iMCU_row
=
cinfo
->
total_iMCU_rows
-
1
;
int
blkn
,
bi
,
ci
,
yindex
,
yoffset
,
blockcnt
;
JDIMENSION
ypos
,
xpos
;
jpeg_component_info
*
compptr
;
/* Loop to write as much as one whole iMCU row */
for
(
yoffset
=
coef
->
MCU_vert_offset
;
yoffset
<
coef
->
MCU_rows_per_iMCU_row
;
yoffset
++
)
{
for
(
MCU_col_num
=
coef
->
mcu_ctr
;
MCU_col_num
<=
last_MCU_col
;
MCU_col_num
++
)
{
/* Determine where data comes from in input_buf and do the DCT thing.
* Each call on forward_DCT processes a horizontal row of DCT blocks
* as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks
* sequentially. Dummy blocks at the right or bottom edge are filled in
* specially. The data in them does not matter for image reconstruction,
* so we fill them with values that will encode to the smallest amount of
* data, viz: all zeroes in the AC entries, DC entries equal to previous
* block's DC value. (Thanks to Thomas Kinsman for this idea.)
*/
blkn
=
0
;
for
(
ci
=
0
;
ci
<
cinfo
->
comps_in_scan
;
ci
++
)
{
compptr
=
cinfo
->
cur_comp_info
[
ci
];
blockcnt
=
(
MCU_col_num
<
last_MCU_col
)
?
compptr
->
MCU_width
:
compptr
->
last_col_width
;
xpos
=
MCU_col_num
*
compptr
->
MCU_sample_width
;
ypos
=
yoffset
*
DCTSIZE
;
/* ypos == (yoffset+yindex) * DCTSIZE */
for
(
yindex
=
0
;
yindex
<
compptr
->
MCU_height
;
yindex
++
)
{
if
(
coef
->
iMCU_row_num
<
last_iMCU_row
||
yoffset
+
yindex
<
compptr
->
last_row_height
)
{
(
*
cinfo
->
fdct
->
forward_DCT
)
(
cinfo
,
compptr
,
input_buf
[
compptr
->
component_index
],
coef
->
MCU_buffer
[
blkn
],
ypos
,
xpos
,
(
JDIMENSION
)
blockcnt
);
if
(
blockcnt
<
compptr
->
MCU_width
)
{
/* Create some dummy blocks at the right edge of the image. */
jzero_far
((
void
FAR
*
)
coef
->
MCU_buffer
[
blkn
+
blockcnt
],
(
compptr
->
MCU_width
-
blockcnt
)
*
SIZEOF
(
JBLOCK
));
for
(
bi
=
blockcnt
;
bi
<
compptr
->
MCU_width
;
bi
++
)
{
coef
->
MCU_buffer
[
blkn
+
bi
][
0
][
0
]
=
coef
->
MCU_buffer
[
blkn
+
bi
-
1
][
0
][
0
];
}
}
}
else
{
/* Create a row of dummy blocks at the bottom of the image. */
jzero_far
((
void
FAR
*
)
coef
->
MCU_buffer
[
blkn
],
compptr
->
MCU_width
*
SIZEOF
(
JBLOCK
));
for
(
bi
=
0
;
bi
<
compptr
->
MCU_width
;
bi
++
)
{
coef
->
MCU_buffer
[
blkn
+
bi
][
0
][
0
]
=
coef
->
MCU_buffer
[
blkn
-
1
][
0
][
0
];
}
}
blkn
+=
compptr
->
MCU_width
;
ypos
+=
DCTSIZE
;
}
}
/* Try to write the MCU. In event of a suspension failure, we will
* re-DCT the MCU on restart (a bit inefficient, could be fixed...)
*/
if
(
!
(
*
cinfo
->
entropy
->
encode_mcu
)
(
cinfo
,
coef
->
MCU_buffer
))
{
/* Suspension forced; update state counters and exit */
coef
->
MCU_vert_offset
=
yoffset
;
coef
->
mcu_ctr
=
MCU_col_num
;
return
FALSE
;
}
}
/* Completed an MCU row, but perhaps not an iMCU row */
coef
->
mcu_ctr
=
0
;
}
/* Completed the iMCU row, advance counters for next one */
coef
->
iMCU_row_num
++
;
start_iMCU_row
(
cinfo
);
return
TRUE
;
}
#ifdef FULL_COEF_BUFFER_SUPPORTED
/*
* Process some data in the first pass of a multi-pass case.
* We process the equivalent of one fully interleaved MCU row ("iMCU" row)
* per call, ie, v_samp_factor block rows for each component in the image.
* This amount of data is read from the source buffer, DCT'd and quantized,
* and saved into the virtual arrays. We also generate suitable dummy blocks
* as needed at the right and lower edges. (The dummy blocks are constructed
* in the virtual arrays, which have been padded appropriately.) This makes
* it possible for subsequent passes not to worry about real vs. dummy blocks.
*
* We must also emit the data to the entropy encoder. This is conveniently
* done by calling compress_output() after we've loaded the current strip
* of the virtual arrays.
*
* NB: input_buf contains a plane for each component in image. All
* components are DCT'd and loaded into the virtual arrays in this pass.
* However, it may be that only a subset of the components are emitted to
* the entropy encoder during this first pass; be careful about looking
* at the scan-dependent variables (MCU dimensions, etc).
*/
METHODDEF
(
int
)
compress_first_pass
(
j_compress_ptr
cinfo
,
JSAMPIMAGE
input_buf
)
{
my_coef_ptr
coef
=
(
my_coef_ptr
)
cinfo
->
coef
;
JDIMENSION
last_iMCU_row
=
cinfo
->
total_iMCU_rows
-
1
;
JDIMENSION
blocks_across
,
MCUs_across
,
MCUindex
;
int
bi
,
ci
,
h_samp_factor
,
block_row
,
block_rows
,
ndummy
;
JCOEF
lastDC
;
jpeg_component_info
*
compptr
;
JBLOCKARRAY
buffer
;
JBLOCKROW
thisblockrow
,
lastblockrow
;
for
(
ci
=
0
,
compptr
=
cinfo
->
comp_info
;
ci
<
cinfo
->
num_components
;
ci
++
,
compptr
++
)
{
/* Align the virtual buffer for this component. */
buffer
=
(
*
cinfo
->
mem
->
access_virt_barray
)
((
j_common_ptr
)
cinfo
,
coef
->
whole_image
[
ci
],
coef
->
iMCU_row_num
*
compptr
->
v_samp_factor
,
(
JDIMENSION
)
compptr
->
v_samp_factor
,
TRUE
);
/* Count non-dummy DCT block rows in this iMCU row. */
if
(
coef
->
iMCU_row_num
<
last_iMCU_row
)
block_rows
=
compptr
->
v_samp_factor
;
else
{
/* NB: can't use last_row_height here, since may not be set! */
block_rows
=
(
int
)
(
compptr
->
height_in_blocks
%
compptr
->
v_samp_factor
);
if
(
block_rows
==
0
)
block_rows
=
compptr
->
v_samp_factor
;
}
blocks_across
=
compptr
->
width_in_blocks
;
h_samp_factor
=
compptr
->
h_samp_factor
;
/* Count number of dummy blocks to be added at the right margin. */
ndummy
=
(
int
)
(
blocks_across
%
h_samp_factor
);
if
(
ndummy
>
0
)
ndummy
=
h_samp_factor
-
ndummy
;
/* Perform DCT for all non-dummy blocks in this iMCU row. Each call
* on forward_DCT processes a complete horizontal row of DCT blocks.
*/
for
(
block_row
=
0
;
block_row
<
block_rows
;
block_row
++
)
{
thisblockrow
=
buffer
[
block_row
];
(
*
cinfo
->
fdct
->
forward_DCT
)
(
cinfo
,
compptr
,
input_buf
[
ci
],
thisblockrow
,
(
JDIMENSION
)
(
block_row
*
DCTSIZE
),
(
JDIMENSION
)
0
,
blocks_across
);
if
(
ndummy
>
0
)
{
/* Create dummy blocks at the right edge of the image. */
thisblockrow
+=
blocks_across
;
/* => first dummy block */
jzero_far
((
void
FAR
*
)
thisblockrow
,
ndummy
*
SIZEOF
(
JBLOCK
));
lastDC
=
thisblockrow
[
-
1
][
0
];
for
(
bi
=
0
;
bi
<
ndummy
;
bi
++
)
{
thisblockrow
[
bi
][
0
]
=
lastDC
;
}
}
}
/* If at end of image, create dummy block rows as needed.
* The tricky part here is that within each MCU, we want the DC values
* of the dummy blocks to match the last real block's DC value.
* This squeezes a few more bytes out of the resulting file...
*/
if
(
coef
->
iMCU_row_num
==
last_iMCU_row
)
{
blocks_across
+=
ndummy
;
/* include lower right corner */
MCUs_across
=
blocks_across
/
h_samp_factor
;
for
(
block_row
=
block_rows
;
block_row
<
compptr
->
v_samp_factor
;
block_row
++
)
{
thisblockrow
=
buffer
[
block_row
];
lastblockrow
=
buffer
[
block_row
-
1
];
jzero_far
((
void
FAR
*
)
thisblockrow
,
(
size_t
)
(
blocks_across
*
SIZEOF
(
JBLOCK
)));
for
(
MCUindex
=
0
;
MCUindex
<
MCUs_across
;
MCUindex
++
)
{
lastDC
=
lastblockrow
[
h_samp_factor
-
1
][
0
];
for
(
bi
=
0
;
bi
<
h_samp_factor
;
bi
++
)
{
thisblockrow
[
bi
][
0
]
=
lastDC
;
}
thisblockrow
+=
h_samp_factor
;
/* advance to next MCU in row */
lastblockrow
+=
h_samp_factor
;
}
}
}
}
/* NB: compress_output will increment iMCU_row_num if successful.
* A suspension return will result in redoing all the work above next time.
*/
/* Emit data to the entropy encoder, sharing code with subsequent passes */
return
compress_output
(
cinfo
,
input_buf
);
}
/*
* Process some data in subsequent passes of a multi-pass case.
* We process the equivalent of one fully interleaved MCU row ("iMCU" row)
* per call, ie, v_samp_factor block rows for each component in the scan.
* The data is obtained from the virtual arrays and fed to the entropy coder.
* Returns TRUE if the iMCU row is completed, FALSE if suspended.
*
* NB: input_buf is ignored; it is likely to be a NULL pointer.
*/
METHODDEF
(
int
)
compress_output
(
j_compress_ptr
cinfo
,
JSAMPIMAGE
input_buf
)
{
my_coef_ptr
coef
=
(
my_coef_ptr
)
cinfo
->
coef
;
JDIMENSION
MCU_col_num
;
/* index of current MCU within row */
int
blkn
,
ci
,
xindex
,
yindex
,
yoffset
;
JDIMENSION
start_col
;
JBLOCKARRAY
buffer
[
MAX_COMPS_IN_SCAN
];
JBLOCKROW
buffer_ptr
;
jpeg_component_info
*
compptr
;
/* Align the virtual buffers for the components used in this scan.
* NB: during first pass, this is safe only because the buffers will
* already be aligned properly, so jmemmgr.c won't need to do any I/O.
*/
for
(
ci
=
0
;
ci
<
cinfo
->
comps_in_scan
;
ci
++
)
{
compptr
=
cinfo
->
cur_comp_info
[
ci
];
buffer
[
ci
]
=
(
*
cinfo
->
mem
->
access_virt_barray
)
((
j_common_ptr
)
cinfo
,
coef
->
whole_image
[
compptr
->
component_index
],
coef
->
iMCU_row_num
*
compptr
->
v_samp_factor
,
(
JDIMENSION
)
compptr
->
v_samp_factor
,
FALSE
);
}
/* Loop to process one whole iMCU row */
for
(
yoffset
=
coef
->
MCU_vert_offset
;
yoffset
<
coef
->
MCU_rows_per_iMCU_row
;
yoffset
++
)
{
for
(
MCU_col_num
=
coef
->
mcu_ctr
;
MCU_col_num
<
cinfo
->
MCUs_per_row
;
MCU_col_num
++
)
{
/* Construct list of pointers to DCT blocks belonging to this MCU */
blkn
=
0
;
/* index of current DCT block within MCU */
for
(
ci
=
0
;
ci
<
cinfo
->
comps_in_scan
;
ci
++
)
{
compptr
=
cinfo
->
cur_comp_info
[
ci
];
start_col
=
MCU_col_num
*
compptr
->
MCU_width
;
for
(
yindex
=
0
;
yindex
<
compptr
->
MCU_height
;
yindex
++
)
{
buffer_ptr
=
buffer
[
ci
][
yindex
+
yoffset
]
+
start_col
;
for
(
xindex
=
0
;
xindex
<
compptr
->
MCU_width
;
xindex
++
)
{
coef
->
MCU_buffer
[
blkn
++
]
=
buffer_ptr
++
;
}
}
}
/* Try to write the MCU. */
if
(
!
(
*
cinfo
->
entropy
->
encode_mcu
)
(
cinfo
,
coef
->
MCU_buffer
))
{
/* Suspension forced; update state counters and exit */
coef
->
MCU_vert_offset
=
yoffset
;
coef
->
mcu_ctr
=
MCU_col_num
;
return
FALSE
;
}
}
/* Completed an MCU row, but perhaps not an iMCU row */
coef
->
mcu_ctr
=
0
;
}
/* Completed the iMCU row, advance counters for next one */
coef
->
iMCU_row_num
++
;
start_iMCU_row
(
cinfo
);
return
TRUE
;
}
#endif
/* FULL_COEF_BUFFER_SUPPORTED */
/*
* Initialize coefficient buffer controller.
*/
GLOBAL
(
void
)
jinit_c_coef_controller
(
j_compress_ptr
cinfo
,
int
need_full_buffer
)
{
my_coef_ptr
coef
;
coef
=
(
my_coef_ptr
)
(
*
cinfo
->
mem
->
alloc_small
)
((
j_common_ptr
)
cinfo
,
JPOOL_IMAGE
,
SIZEOF
(
my_coef_controller
));
cinfo
->
coef
=
(
struct
jpeg_c_coef_controller
*
)
coef
;
coef
->
pub
.
start_pass
=
start_pass_coef
;
/* Create the coefficient buffer. */
if
(
need_full_buffer
)
{
#ifdef FULL_COEF_BUFFER_SUPPORTED
/* Allocate a full-image virtual array for each component, */
/* padded to a multiple of samp_factor DCT blocks in each direction. */
int
ci
;
jpeg_component_info
*
compptr
;
for
(
ci
=
0
,
compptr
=
cinfo
->
comp_info
;
ci
<
cinfo
->
num_components
;
ci
++
,
compptr
++
)
{
coef
->
whole_image
[
ci
]
=
(
*
cinfo
->
mem
->
request_virt_barray
)
((
j_common_ptr
)
cinfo
,
JPOOL_IMAGE
,
FALSE
,
(
JDIMENSION
)
jround_up
((
long
)
compptr
->
width_in_blocks
,
(
long
)
compptr
->
h_samp_factor
),
(
JDIMENSION
)
jround_up
((
long
)
compptr
->
height_in_blocks
,
(
long
)
compptr
->
v_samp_factor
),
(
JDIMENSION
)
compptr
->
v_samp_factor
);
}
#else
ERREXIT
(
cinfo
,
JERR_BAD_BUFFER_MODE
);
#endif
}
else
{
/* We only need a single-MCU buffer. */
JBLOCKROW
buffer
;
int
i
;
buffer
=
(
JBLOCKROW
)
(
*
cinfo
->
mem
->
alloc_large
)
((
j_common_ptr
)
cinfo
,
JPOOL_IMAGE
,
C_MAX_BLOCKS_IN_MCU
*
SIZEOF
(
JBLOCK
));
for
(
i
=
0
;
i
<
C_MAX_BLOCKS_IN_MCU
;
i
++
)
{
coef
->
MCU_buffer
[
i
]
=
buffer
+
i
;
}
coef
->
whole_image
[
0
]
=
NULL
;
/* flag for no virtual arrays */
}
}
dlib/external/libjpeg/jccolor.cpp
0 → 100644
View file @
747088ea
/*
* jccolor.c
*
* Copyright (C) 1991-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains input colorspace conversion routines.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/* Private subobject */
typedef
struct
{
struct
jpeg_color_converter
pub
;
/* public fields */
/* Private state for RGB->YCC conversion */
long
*
rgb_ycc_tab
;
/* => table for RGB to YCbCr conversion */
}
my_color_converter
;
typedef
my_color_converter
*
my_cconvert_ptr
;
/**************** RGB -> YCbCr conversion: most common case **************/
/*
* YCbCr is defined per CCIR 601-1, except that Cb and Cr are
* normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
* The conversion equations to be implemented are therefore
* Y = 0.29900 * R + 0.58700 * G + 0.11400 * B
* Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE
* Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE
* (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
* Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2,
* rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and
* negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0)
* were not represented exactly. Now we sacrifice exact representation of
* maximum red and maximum blue in order to get exact grayscales.
*
* To avoid floating-point arithmetic, we represent the fractional constants
* as integers scaled up by 2^16 (about 4 digits precision); we have to divide
* the products by 2^16, with appropriate rounding, to get the correct answer.
*
* For even more speed, we avoid doing any multiplications in the inner loop
* by precalculating the constants times R,G,B for all possible values.
* For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
* for 12-bit samples it is still acceptable. It's not very reasonable for
* 16-bit samples, but if you want lossless storage you shouldn't be changing
* colorspace anyway.
* The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included
* in the tables to save adding them separately in the inner loop.
*/
#define SCALEBITS 16
/* speediest right-shift on some machines */
#define CBCR_OFFSET ((long) CENTERJSAMPLE << SCALEBITS)
#define ONE_HALF ((long) 1 << (SCALEBITS-1))
#define FIX(x) ((long) ((x) * (1L<<SCALEBITS) + 0.5))
/* We allocate one big table and divide it up into eight parts, instead of
* doing eight alloc_small requests. This lets us use a single table base
* address, which can be held in a register in the inner loops on many
* machines (more than can hold all eight addresses, anyway).
*/
#define R_Y_OFF 0
/* offset to R => Y section */
#define G_Y_OFF (1*(MAXJSAMPLE+1))
/* offset to G => Y section */
#define B_Y_OFF (2*(MAXJSAMPLE+1))
/* etc. */
#define R_CB_OFF (3*(MAXJSAMPLE+1))
#define G_CB_OFF (4*(MAXJSAMPLE+1))
#define B_CB_OFF (5*(MAXJSAMPLE+1))
#define R_CR_OFF B_CB_OFF
/* B=>Cb, R=>Cr are the same */
#define G_CR_OFF (6*(MAXJSAMPLE+1))
#define B_CR_OFF (7*(MAXJSAMPLE+1))
#define TABLE_SIZE (8*(MAXJSAMPLE+1))
/*
* Initialize for RGB->YCC colorspace conversion.
*/
METHODDEF
(
void
)
rgb_ycc_start
(
j_compress_ptr
cinfo
)
{
my_cconvert_ptr
cconvert
=
(
my_cconvert_ptr
)
cinfo
->
cconvert
;
long
*
rgb_ycc_tab
;
long
i
;
/* Allocate and fill in the conversion tables. */
cconvert
->
rgb_ycc_tab
=
rgb_ycc_tab
=
(
long
*
)
(
*
cinfo
->
mem
->
alloc_small
)
((
j_common_ptr
)
cinfo
,
JPOOL_IMAGE
,
(
TABLE_SIZE
*
SIZEOF
(
long
)));
for
(
i
=
0
;
i
<=
MAXJSAMPLE
;
i
++
)
{
rgb_ycc_tab
[
i
+
R_Y_OFF
]
=
FIX
(
0.29900
)
*
i
;
rgb_ycc_tab
[
i
+
G_Y_OFF
]
=
FIX
(
0.58700
)
*
i
;
rgb_ycc_tab
[
i
+
B_Y_OFF
]
=
FIX
(
0.11400
)
*
i
+
ONE_HALF
;
rgb_ycc_tab
[
i
+
R_CB_OFF
]
=
(
-
FIX
(
0.16874
))
*
i
;
rgb_ycc_tab
[
i
+
G_CB_OFF
]
=
(
-
FIX
(
0.33126
))
*
i
;
/* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr.
* This ensures that the maximum output will round to MAXJSAMPLE
* not MAXJSAMPLE+1, and thus that we don't have to range-limit.
*/
rgb_ycc_tab
[
i
+
B_CB_OFF
]
=
FIX
(
0.50000
)
*
i
+
CBCR_OFFSET
+
ONE_HALF
-
1
;
/* B=>Cb and R=>Cr tables are the same
rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1;
*/
rgb_ycc_tab
[
i
+
G_CR_OFF
]
=
(
-
FIX
(
0.41869
))
*
i
;
rgb_ycc_tab
[
i
+
B_CR_OFF
]
=
(
-
FIX
(
0.08131
))
*
i
;
}
}
/*
* Convert some rows of samples to the JPEG colorspace.
*
* Note that we change from the application's interleaved-pixel format
* to our internal noninterleaved, one-plane-per-component format.
* The input buffer is therefore three times as wide as the output buffer.
*
* A starting row offset is provided only for the output buffer. The caller
* can easily adjust the passed input_buf value to accommodate any row
* offset required on that side.
*/
METHODDEF
(
void
)
rgb_ycc_convert
(
j_compress_ptr
cinfo
,
JSAMPARRAY
input_buf
,
JSAMPIMAGE
output_buf
,
JDIMENSION
output_row
,
int
num_rows
)
{
my_cconvert_ptr
cconvert
=
(
my_cconvert_ptr
)
cinfo
->
cconvert
;
register
int
r
,
g
,
b
;
register
long
*
ctab
=
cconvert
->
rgb_ycc_tab
;
register
JSAMPROW
inptr
;
register
JSAMPROW
outptr0
,
outptr1
,
outptr2
;
register
JDIMENSION
col
;
JDIMENSION
num_cols
=
cinfo
->
image_width
;
while
(
--
num_rows
>=
0
)
{
inptr
=
*
input_buf
++
;
outptr0
=
output_buf
[
0
][
output_row
];
outptr1
=
output_buf
[
1
][
output_row
];
outptr2
=
output_buf
[
2
][
output_row
];
output_row
++
;
for
(
col
=
0
;
col
<
num_cols
;
col
++
)
{
r
=
GETJSAMPLE
(
inptr
[
RGB_RED
]);
g
=
GETJSAMPLE
(
inptr
[
RGB_GREEN
]);
b
=
GETJSAMPLE
(
inptr
[
RGB_BLUE
]);
inptr
+=
RGB_PIXELSIZE
;
/* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
* must be too; we do not need an explicit range-limiting operation.
* Hence the value being shifted is never negative, and we don't
* need the general RIGHT_SHIFT macro.
*/
/* Y */
outptr0
[
col
]
=
(
JSAMPLE
)
((
ctab
[
r
+
R_Y_OFF
]
+
ctab
[
g
+
G_Y_OFF
]
+
ctab
[
b
+
B_Y_OFF
])
>>
SCALEBITS
);
/* Cb */
outptr1
[
col
]
=
(
JSAMPLE
)
((
ctab
[
r
+
R_CB_OFF
]
+
ctab
[
g
+
G_CB_OFF
]
+
ctab
[
b
+
B_CB_OFF
])
>>
SCALEBITS
);
/* Cr */
outptr2
[
col
]
=
(
JSAMPLE
)
((
ctab
[
r
+
R_CR_OFF
]
+
ctab
[
g
+
G_CR_OFF
]
+
ctab
[
b
+
B_CR_OFF
])
>>
SCALEBITS
);
}
}
}
/**************** Cases other than RGB -> YCbCr **************/
/*
* Convert some rows of samples to the JPEG colorspace.
* This version handles RGB->grayscale conversion, which is the same
* as the RGB->Y portion of RGB->YCbCr.
* We assume rgb_ycc_start has been called (we only use the Y tables).
*/
METHODDEF
(
void
)
rgb_gray_convert
(
j_compress_ptr
cinfo
,
JSAMPARRAY
input_buf
,
JSAMPIMAGE
output_buf
,
JDIMENSION
output_row
,
int
num_rows
)
{
my_cconvert_ptr
cconvert
=
(
my_cconvert_ptr
)
cinfo
->
cconvert
;
register
int
r
,
g
,
b
;
register
long
*
ctab
=
cconvert
->
rgb_ycc_tab
;
register
JSAMPROW
inptr
;
register
JSAMPROW
outptr
;
register
JDIMENSION
col
;
JDIMENSION
num_cols
=
cinfo
->
image_width
;
while
(
--
num_rows
>=
0
)
{
inptr
=
*
input_buf
++
;
outptr
=
output_buf
[
0
][
output_row
];
output_row
++
;
for
(
col
=
0
;
col
<
num_cols
;
col
++
)
{
r
=
GETJSAMPLE
(
inptr
[
RGB_RED
]);
g
=
GETJSAMPLE
(
inptr
[
RGB_GREEN
]);
b
=
GETJSAMPLE
(
inptr
[
RGB_BLUE
]);
inptr
+=
RGB_PIXELSIZE
;
/* Y */
outptr
[
col
]
=
(
JSAMPLE
)
((
ctab
[
r
+
R_Y_OFF
]
+
ctab
[
g
+
G_Y_OFF
]
+
ctab
[
b
+
B_Y_OFF
])
>>
SCALEBITS
);
}
}
}
/*
* Convert some rows of samples to the JPEG colorspace.
* This version handles Adobe-style CMYK->YCCK conversion,
* where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same
* conversion as above, while passing K (black) unchanged.
* We assume rgb_ycc_start has been called.
*/
METHODDEF
(
void
)
cmyk_ycck_convert
(
j_compress_ptr
cinfo
,
JSAMPARRAY
input_buf
,
JSAMPIMAGE
output_buf
,
JDIMENSION
output_row
,
int
num_rows
)
{
my_cconvert_ptr
cconvert
=
(
my_cconvert_ptr
)
cinfo
->
cconvert
;
register
int
r
,
g
,
b
;
register
long
*
ctab
=
cconvert
->
rgb_ycc_tab
;
register
JSAMPROW
inptr
;
register
JSAMPROW
outptr0
,
outptr1
,
outptr2
,
outptr3
;
register
JDIMENSION
col
;
JDIMENSION
num_cols
=
cinfo
->
image_width
;
while
(
--
num_rows
>=
0
)
{
inptr
=
*
input_buf
++
;
outptr0
=
output_buf
[
0
][
output_row
];
outptr1
=
output_buf
[
1
][
output_row
];
outptr2
=
output_buf
[
2
][
output_row
];
outptr3
=
output_buf
[
3
][
output_row
];
output_row
++
;
for
(
col
=
0
;
col
<
num_cols
;
col
++
)
{
r
=
MAXJSAMPLE
-
GETJSAMPLE
(
inptr
[
0
]);
g
=
MAXJSAMPLE
-
GETJSAMPLE
(
inptr
[
1
]);
b
=
MAXJSAMPLE
-
GETJSAMPLE
(
inptr
[
2
]);
/* K passes through as-is */
outptr3
[
col
]
=
inptr
[
3
];
/* don't need GETJSAMPLE here */
inptr
+=
4
;
/* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
* must be too; we do not need an explicit range-limiting operation.
* Hence the value being shifted is never negative, and we don't
* need the general RIGHT_SHIFT macro.
*/
/* Y */
outptr0
[
col
]
=
(
JSAMPLE
)
((
ctab
[
r
+
R_Y_OFF
]
+
ctab
[
g
+
G_Y_OFF
]
+
ctab
[
b
+
B_Y_OFF
])
>>
SCALEBITS
);
/* Cb */
outptr1
[
col
]
=
(
JSAMPLE
)
((
ctab
[
r
+
R_CB_OFF
]
+
ctab
[
g
+
G_CB_OFF
]
+
ctab
[
b
+
B_CB_OFF
])
>>
SCALEBITS
);
/* Cr */
outptr2
[
col
]
=
(
JSAMPLE
)
((
ctab
[
r
+
R_CR_OFF
]
+
ctab
[
g
+
G_CR_OFF
]
+
ctab
[
b
+
B_CR_OFF
])
>>
SCALEBITS
);
}
}
}
/*
* Convert some rows of samples to the JPEG colorspace.
* This version handles grayscale output with no conversion.
* The source can be either plain grayscale or YCbCr (since Y == gray).
*/
METHODDEF
(
void
)
grayscale_convert
(
j_compress_ptr
cinfo
,
JSAMPARRAY
input_buf
,
JSAMPIMAGE
output_buf
,
JDIMENSION
output_row
,
int
num_rows
)
{
register
JSAMPROW
inptr
;
register
JSAMPROW
outptr
;
register
JDIMENSION
col
;
JDIMENSION
num_cols
=
cinfo
->
image_width
;
int
instride
=
cinfo
->
input_components
;
while
(
--
num_rows
>=
0
)
{
inptr
=
*
input_buf
++
;
outptr
=
output_buf
[
0
][
output_row
];
output_row
++
;
for
(
col
=
0
;
col
<
num_cols
;
col
++
)
{
outptr
[
col
]
=
inptr
[
0
];
/* don't need GETJSAMPLE() here */
inptr
+=
instride
;
}
}
}
/*
* Convert some rows of samples to the JPEG colorspace.
* This version handles multi-component colorspaces without conversion.
* We assume input_components == num_components.
*/
METHODDEF
(
void
)
null_convert
(
j_compress_ptr
cinfo
,
JSAMPARRAY
input_buf
,
JSAMPIMAGE
output_buf
,
JDIMENSION
output_row
,
int
num_rows
)
{
register
JSAMPROW
inptr
;
register
JSAMPROW
outptr
;
register
JDIMENSION
col
;
register
int
ci
;
int
nc
=
cinfo
->
num_components
;
JDIMENSION
num_cols
=
cinfo
->
image_width
;
while
(
--
num_rows
>=
0
)
{
/* It seems fastest to make a separate pass for each component. */
for
(
ci
=
0
;
ci
<
nc
;
ci
++
)
{
inptr
=
*
input_buf
;
outptr
=
output_buf
[
ci
][
output_row
];
for
(
col
=
0
;
col
<
num_cols
;
col
++
)
{
outptr
[
col
]
=
inptr
[
ci
];
/* don't need GETJSAMPLE() here */
inptr
+=
nc
;
}
}
input_buf
++
;
output_row
++
;
}
}
/*
* Empty method for start_pass.
*/
METHODDEF
(
void
)
null_method
(
j_compress_ptr
cinfo
)
{
/* no work needed */
}
/*
* Module initialization routine for input colorspace conversion.
*/
GLOBAL
(
void
)
jinit_color_converter
(
j_compress_ptr
cinfo
)
{
my_cconvert_ptr
cconvert
;
cconvert
=
(
my_cconvert_ptr
)
(
*
cinfo
->
mem
->
alloc_small
)
((
j_common_ptr
)
cinfo
,
JPOOL_IMAGE
,
SIZEOF
(
my_color_converter
));
cinfo
->
cconvert
=
(
struct
jpeg_color_converter
*
)
cconvert
;
/* set start_pass to null method until we find out differently */
cconvert
->
pub
.
start_pass
=
null_method
;
/* Make sure input_components agrees with in_color_space */
switch
(
cinfo
->
in_color_space
)
{
case
JCS_GRAYSCALE
:
if
(
cinfo
->
input_components
!=
1
)
ERREXIT
(
cinfo
,
JERR_BAD_IN_COLORSPACE
);
break
;
case
JCS_RGB
:
#if RGB_PIXELSIZE != 3
if
(
cinfo
->
input_components
!=
RGB_PIXELSIZE
)
ERREXIT
(
cinfo
,
JERR_BAD_IN_COLORSPACE
);
break
;
#endif
/* else share code with YCbCr */
case
JCS_YCbCr
:
if
(
cinfo
->
input_components
!=
3
)
ERREXIT
(
cinfo
,
JERR_BAD_IN_COLORSPACE
);
break
;
case
JCS_CMYK
:
case
JCS_YCCK
:
if
(
cinfo
->
input_components
!=
4
)
ERREXIT
(
cinfo
,
JERR_BAD_IN_COLORSPACE
);
break
;
default
:
/* JCS_UNKNOWN can be anything */
if
(
cinfo
->
input_components
<
1
)
ERREXIT
(
cinfo
,
JERR_BAD_IN_COLORSPACE
);
break
;
}
/* Check num_components, set conversion method based on requested space */
switch
(
cinfo
->
jpeg_color_space
)
{
case
JCS_GRAYSCALE
:
if
(
cinfo
->
num_components
!=
1
)
ERREXIT
(
cinfo
,
JERR_BAD_J_COLORSPACE
);
if
(
cinfo
->
in_color_space
==
JCS_GRAYSCALE
)
cconvert
->
pub
.
color_convert
=
grayscale_convert
;
else
if
(
cinfo
->
in_color_space
==
JCS_RGB
)
{
cconvert
->
pub
.
start_pass
=
rgb_ycc_start
;
cconvert
->
pub
.
color_convert
=
rgb_gray_convert
;
}
else
if
(
cinfo
->
in_color_space
==
JCS_YCbCr
)
cconvert
->
pub
.
color_convert
=
grayscale_convert
;
else
ERREXIT
(
cinfo
,
JERR_CONVERSION_NOTIMPL
);
break
;
case
JCS_RGB
:
if
(
cinfo
->
num_components
!=
3
)
ERREXIT
(
cinfo
,
JERR_BAD_J_COLORSPACE
);
if
(
cinfo
->
in_color_space
==
JCS_RGB
&&
RGB_PIXELSIZE
==
3
)
cconvert
->
pub
.
color_convert
=
null_convert
;
else
ERREXIT
(
cinfo
,
JERR_CONVERSION_NOTIMPL
);
break
;
case
JCS_YCbCr
:
if
(
cinfo
->
num_components
!=
3
)
ERREXIT
(
cinfo
,
JERR_BAD_J_COLORSPACE
);
if
(
cinfo
->
in_color_space
==
JCS_RGB
)
{
cconvert
->
pub
.
start_pass
=
rgb_ycc_start
;
cconvert
->
pub
.
color_convert
=
rgb_ycc_convert
;
}
else
if
(
cinfo
->
in_color_space
==
JCS_YCbCr
)
cconvert
->
pub
.
color_convert
=
null_convert
;
else
ERREXIT
(
cinfo
,
JERR_CONVERSION_NOTIMPL
);
break
;
case
JCS_CMYK
:
if
(
cinfo
->
num_components
!=
4
)
ERREXIT
(
cinfo
,
JERR_BAD_J_COLORSPACE
);
if
(
cinfo
->
in_color_space
==
JCS_CMYK
)
cconvert
->
pub
.
color_convert
=
null_convert
;
else
ERREXIT
(
cinfo
,
JERR_CONVERSION_NOTIMPL
);
break
;
case
JCS_YCCK
:
if
(
cinfo
->
num_components
!=
4
)
ERREXIT
(
cinfo
,
JERR_BAD_J_COLORSPACE
);
if
(
cinfo
->
in_color_space
==
JCS_CMYK
)
{
cconvert
->
pub
.
start_pass
=
rgb_ycc_start
;
cconvert
->
pub
.
color_convert
=
cmyk_ycck_convert
;
}
else
if
(
cinfo
->
in_color_space
==
JCS_YCCK
)
cconvert
->
pub
.
color_convert
=
null_convert
;
else
ERREXIT
(
cinfo
,
JERR_CONVERSION_NOTIMPL
);
break
;
default
:
/* allow null conversion of JCS_UNKNOWN */
if
(
cinfo
->
jpeg_color_space
!=
cinfo
->
in_color_space
||
cinfo
->
num_components
!=
cinfo
->
input_components
)
ERREXIT
(
cinfo
,
JERR_CONVERSION_NOTIMPL
);
cconvert
->
pub
.
color_convert
=
null_convert
;
break
;
}
}
dlib/external/libjpeg/jcdctmgr.cpp
0 → 100644
View file @
747088ea
/*
* jcdctmgr.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains the forward-DCT management logic.
* This code selects a particular DCT implementation to be used,
* and it performs related housekeeping chores including coefficient
* quantization.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jdct.h"
/* Private declarations for DCT subsystem */
/* Private subobject for this module */
typedef
struct
{
struct
jpeg_forward_dct
pub
;
/* public fields */
/* Pointer to the DCT routine actually in use */
forward_DCT_method_ptr
do_dct
;
/* The actual post-DCT divisors --- not identical to the quant table
* entries, because of scaling (especially for an unnormalized DCT).
* Each table is given in normal array order.
*/
DCTELEM
*
divisors
[
NUM_QUANT_TBLS
];
#ifdef DCT_FLOAT_SUPPORTED
/* Same as above for the floating-point case. */
float_DCT_method_ptr
do_float_dct
;
FAST_FLOAT
*
float_divisors
[
NUM_QUANT_TBLS
];
#endif
}
my_fdct_controller
;
typedef
my_fdct_controller
*
my_fdct_ptr
;
/*
* Initialize for a processing pass.
* Verify that all referenced Q-tables are present, and set up
* the divisor table for each one.
* In the current implementation, DCT of all components is done during
* the first pass, even if only some components will be output in the
* first scan. Hence all components should be examined here.
*/
METHODDEF
(
void
)
start_pass_fdctmgr
(
j_compress_ptr
cinfo
)
{
my_fdct_ptr
fdct
=
(
my_fdct_ptr
)
cinfo
->
fdct
;
int
ci
,
qtblno
,
i
;
jpeg_component_info
*
compptr
;
JQUANT_TBL
*
qtbl
;
DCTELEM
*
dtbl
;
for
(
ci
=
0
,
compptr
=
cinfo
->
comp_info
;
ci
<
cinfo
->
num_components
;
ci
++
,
compptr
++
)
{
qtblno
=
compptr
->
quant_tbl_no
;
/* Make sure specified quantization table is present */
if
(
qtblno
<
0
||
qtblno
>=
NUM_QUANT_TBLS
||
cinfo
->
quant_tbl_ptrs
[
qtblno
]
==
NULL
)
ERREXIT1
(
cinfo
,
JERR_NO_QUANT_TABLE
,
qtblno
);
qtbl
=
cinfo
->
quant_tbl_ptrs
[
qtblno
];
/* Compute divisors for this quant table */
/* We may do this more than once for same table, but it's not a big deal */
switch
(
cinfo
->
dct_method
)
{
#ifdef DCT_ISLOW_SUPPORTED
case
JDCT_ISLOW
:
/* For LL&M IDCT method, divisors are equal to raw quantization
* coefficients multiplied by 8 (to counteract scaling).
*/
if
(
fdct
->
divisors
[
qtblno
]
==
NULL
)
{
fdct
->
divisors
[
qtblno
]
=
(
DCTELEM
*
)
(
*
cinfo
->
mem
->
alloc_small
)
((
j_common_ptr
)
cinfo
,
JPOOL_IMAGE
,
DCTSIZE2
*
SIZEOF
(
DCTELEM
));
}
dtbl
=
fdct
->
divisors
[
qtblno
];
for
(
i
=
0
;
i
<
DCTSIZE2
;
i
++
)
{
dtbl
[
i
]
=
((
DCTELEM
)
qtbl
->
quantval
[
i
])
<<
3
;
}
break
;
#endif
#ifdef DCT_IFAST_SUPPORTED
case
JDCT_IFAST
:
{
/* For AA&N IDCT method, divisors are equal to quantization
* coefficients scaled by scalefactor[row]*scalefactor[col], where
* scalefactor[0] = 1
* scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
* We apply a further scale factor of 8.
*/
#define CONST_BITS 14
static
const
short
aanscales
[
DCTSIZE2
]
=
{
/* precomputed values scaled up by 14 bits */
16384
,
22725
,
21407
,
19266
,
16384
,
12873
,
8867
,
4520
,
22725
,
31521
,
29692
,
26722
,
22725
,
17855
,
12299
,
6270
,
21407
,
29692
,
27969
,
25172
,
21407
,
16819
,
11585
,
5906
,
19266
,
26722
,
25172
,
22654
,
19266
,
15137
,
10426
,
5315
,
16384
,
22725
,
21407
,
19266
,
16384
,
12873
,
8867
,
4520
,
12873
,
17855
,
16819
,
15137
,
12873
,
10114
,
6967
,
3552
,
8867
,
12299
,
11585
,
10426
,
8867
,
6967
,
4799
,
2446
,
4520
,
6270
,
5906
,
5315
,
4520
,
3552
,
2446
,
1247
};
SHIFT_TEMPS
if
(
fdct
->
divisors
[
qtblno
]
==
NULL
)
{
fdct
->
divisors
[
qtblno
]
=
(
DCTELEM
*
)
(
*
cinfo
->
mem
->
alloc_small
)
((
j_common_ptr
)
cinfo
,
JPOOL_IMAGE
,
DCTSIZE2
*
SIZEOF
(
DCTELEM
));
}
dtbl
=
fdct
->
divisors
[
qtblno
];
for
(
i
=
0
;
i
<
DCTSIZE2
;
i
++
)
{
dtbl
[
i
]
=
(
DCTELEM
)
DESCALE
(
MULTIPLY16V16
((
long
)
qtbl
->
quantval
[
i
],
(
long
)
aanscales
[
i
]),
CONST_BITS
-
3
);
}
}
break
;
#endif
#ifdef DCT_FLOAT_SUPPORTED
case
JDCT_FLOAT
:
{
/* For float AA&N IDCT method, divisors are equal to quantization
* coefficients scaled by scalefactor[row]*scalefactor[col], where
* scalefactor[0] = 1
* scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
* We apply a further scale factor of 8.
* What's actually stored is 1/divisor so that the inner loop can
* use a multiplication rather than a division.
*/
FAST_FLOAT
*
fdtbl
;
int
row
,
col
;
static
const
double
aanscalefactor
[
DCTSIZE
]
=
{
1.0
,
1.387039845
,
1.306562965
,
1.175875602
,
1.0
,
0.785694958
,
0.541196100
,
0.275899379
};
if
(
fdct
->
float_divisors
[
qtblno
]
==
NULL
)
{
fdct
->
float_divisors
[
qtblno
]
=
(
FAST_FLOAT
*
)
(
*
cinfo
->
mem
->
alloc_small
)
((
j_common_ptr
)
cinfo
,
JPOOL_IMAGE
,
DCTSIZE2
*
SIZEOF
(
FAST_FLOAT
));
}
fdtbl
=
fdct
->
float_divisors
[
qtblno
];
i
=
0
;
for
(
row
=
0
;
row
<
DCTSIZE
;
row
++
)
{
for
(
col
=
0
;
col
<
DCTSIZE
;
col
++
)
{
fdtbl
[
i
]
=
(
FAST_FLOAT
)
(
1.0
/
(((
double
)
qtbl
->
quantval
[
i
]
*
aanscalefactor
[
row
]
*
aanscalefactor
[
col
]
*
8.0
)));
i
++
;
}
}
}
break
;
#endif
default
:
ERREXIT
(
cinfo
,
JERR_NOT_COMPILED
);
break
;
}
}
}
/*
* Perform forward DCT on one or more blocks of a component.
*
* The input samples are taken from the sample_data[] array starting at
* position start_row/start_col, and moving to the right for any additional
* blocks. The quantized coefficients are returned in coef_blocks[].
*/
METHODDEF
(
void
)
forward_DCT
(
j_compress_ptr
cinfo
,
jpeg_component_info
*
compptr
,
JSAMPARRAY
sample_data
,
JBLOCKROW
coef_blocks
,
JDIMENSION
start_row
,
JDIMENSION
start_col
,
JDIMENSION
num_blocks
)
/* This version is used for integer DCT implementations. */
{
/* This routine is heavily used, so it's worth coding it tightly. */
my_fdct_ptr
fdct
=
(
my_fdct_ptr
)
cinfo
->
fdct
;
forward_DCT_method_ptr
do_dct
=
fdct
->
do_dct
;
DCTELEM
*
divisors
=
fdct
->
divisors
[
compptr
->
quant_tbl_no
];
DCTELEM
workspace
[
DCTSIZE2
];
/* work area for FDCT subroutine */
JDIMENSION
bi
;
sample_data
+=
start_row
;
/* fold in the vertical offset once */
for
(
bi
=
0
;
bi
<
num_blocks
;
bi
++
,
start_col
+=
DCTSIZE
)
{
/* Load data into workspace, applying unsigned->signed conversion */
{
register
DCTELEM
*
workspaceptr
;
register
JSAMPROW
elemptr
;
register
int
elemr
;
workspaceptr
=
workspace
;
for
(
elemr
=
0
;
elemr
<
DCTSIZE
;
elemr
++
)
{
elemptr
=
sample_data
[
elemr
]
+
start_col
;
#if DCTSIZE == 8
/* unroll the inner loop */
*
workspaceptr
++
=
GETJSAMPLE
(
*
elemptr
++
)
-
CENTERJSAMPLE
;
*
workspaceptr
++
=
GETJSAMPLE
(
*
elemptr
++
)
-
CENTERJSAMPLE
;
*
workspaceptr
++
=
GETJSAMPLE
(
*
elemptr
++
)
-
CENTERJSAMPLE
;
*
workspaceptr
++
=
GETJSAMPLE
(
*
elemptr
++
)
-
CENTERJSAMPLE
;
*
workspaceptr
++
=
GETJSAMPLE
(
*
elemptr
++
)
-
CENTERJSAMPLE
;
*
workspaceptr
++
=
GETJSAMPLE
(
*
elemptr
++
)
-
CENTERJSAMPLE
;
*
workspaceptr
++
=
GETJSAMPLE
(
*
elemptr
++
)
-
CENTERJSAMPLE
;
*
workspaceptr
++
=
GETJSAMPLE
(
*
elemptr
++
)
-
CENTERJSAMPLE
;
#else
{
register
int
elemc
;
for
(
elemc
=
DCTSIZE
;
elemc
>
0
;
elemc
--
)
{
*
workspaceptr
++
=
GETJSAMPLE
(
*
elemptr
++
)
-
CENTERJSAMPLE
;
}
}
#endif
}
}
/* Perform the DCT */
(
*
do_dct
)
(
workspace
);
/* Quantize/descale the coefficients, and store into coef_blocks[] */
{
register
DCTELEM
temp
,
qval
;
register
int
i
;
register
JCOEFPTR
output_ptr
=
coef_blocks
[
bi
];
for
(
i
=
0
;
i
<
DCTSIZE2
;
i
++
)
{
qval
=
divisors
[
i
];
temp
=
workspace
[
i
];
/* Divide the coefficient value by qval, ensuring proper rounding.
* Since C does not specify the direction of rounding for negative
* quotients, we have to force the dividend positive for portability.
*
* In most files, at least half of the output values will be zero
* (at default quantization settings, more like three-quarters...)
* so we should ensure that this case is fast. On many machines,
* a comparison is enough cheaper than a divide to make a special test
* a win. Since both inputs will be nonnegative, we need only test
* for a < b to discover whether a/b is 0.
* If your machine's division is fast enough, define FAST_DIVIDE.
*/
#ifdef FAST_DIVIDE
#define DIVIDE_BY(a,b) a /= b
#else
#define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0
#endif
if
(
temp
<
0
)
{
temp
=
-
temp
;
temp
+=
qval
>>
1
;
/* for rounding */
DIVIDE_BY
(
temp
,
qval
);
temp
=
-
temp
;
}
else
{
temp
+=
qval
>>
1
;
/* for rounding */
DIVIDE_BY
(
temp
,
qval
);
}
output_ptr
[
i
]
=
(
JCOEF
)
temp
;
}
}
}
}
#ifdef DCT_FLOAT_SUPPORTED
METHODDEF
(
void
)
forward_DCT_float
(
j_compress_ptr
cinfo
,
jpeg_component_info
*
compptr
,
JSAMPARRAY
sample_data
,
JBLOCKROW
coef_blocks
,
JDIMENSION
start_row
,
JDIMENSION
start_col
,
JDIMENSION
num_blocks
)
/* This version is used for floating-point DCT implementations. */
{
/* This routine is heavily used, so it's worth coding it tightly. */
my_fdct_ptr
fdct
=
(
my_fdct_ptr
)
cinfo
->
fdct
;
float_DCT_method_ptr
do_dct
=
fdct
->
do_float_dct
;
FAST_FLOAT
*
divisors
=
fdct
->
float_divisors
[
compptr
->
quant_tbl_no
];
FAST_FLOAT
workspace
[
DCTSIZE2
];
/* work area for FDCT subroutine */
JDIMENSION
bi
;
sample_data
+=
start_row
;
/* fold in the vertical offset once */
for
(
bi
=
0
;
bi
<
num_blocks
;
bi
++
,
start_col
+=
DCTSIZE
)
{
/* Load data into workspace, applying unsigned->signed conversion */
{
register
FAST_FLOAT
*
workspaceptr
;
register
JSAMPROW
elemptr
;
register
int
elemr
;
workspaceptr
=
workspace
;
for
(
elemr
=
0
;
elemr
<
DCTSIZE
;
elemr
++
)
{
elemptr
=
sample_data
[
elemr
]
+
start_col
;
#if DCTSIZE == 8
/* unroll the inner loop */
*
workspaceptr
++
=
(
FAST_FLOAT
)(
GETJSAMPLE
(
*
elemptr
++
)
-
CENTERJSAMPLE
);
*
workspaceptr
++
=
(
FAST_FLOAT
)(
GETJSAMPLE
(
*
elemptr
++
)
-
CENTERJSAMPLE
);
*
workspaceptr
++
=
(
FAST_FLOAT
)(
GETJSAMPLE
(
*
elemptr
++
)
-
CENTERJSAMPLE
);
*
workspaceptr
++
=
(
FAST_FLOAT
)(
GETJSAMPLE
(
*
elemptr
++
)
-
CENTERJSAMPLE
);
*
workspaceptr
++
=
(
FAST_FLOAT
)(
GETJSAMPLE
(
*
elemptr
++
)
-
CENTERJSAMPLE
);
*
workspaceptr
++
=
(
FAST_FLOAT
)(
GETJSAMPLE
(
*
elemptr
++
)
-
CENTERJSAMPLE
);
*
workspaceptr
++
=
(
FAST_FLOAT
)(
GETJSAMPLE
(
*
elemptr
++
)
-
CENTERJSAMPLE
);
*
workspaceptr
++
=
(
FAST_FLOAT
)(
GETJSAMPLE
(
*
elemptr
++
)
-
CENTERJSAMPLE
);
#else
{
register
int
elemc
;
for
(
elemc
=
DCTSIZE
;
elemc
>
0
;
elemc
--
)
{
*
workspaceptr
++
=
(
FAST_FLOAT
)
(
GETJSAMPLE
(
*
elemptr
++
)
-
CENTERJSAMPLE
);
}
}
#endif
}
}
/* Perform the DCT */
(
*
do_dct
)
(
workspace
);
/* Quantize/descale the coefficients, and store into coef_blocks[] */
{
register
FAST_FLOAT
temp
;
register
int
i
;
register
JCOEFPTR
output_ptr
=
coef_blocks
[
bi
];
for
(
i
=
0
;
i
<
DCTSIZE2
;
i
++
)
{
/* Apply the quantization and scaling factor */
temp
=
workspace
[
i
]
*
divisors
[
i
];
/* Round to nearest integer.
* Since C does not specify the direction of rounding for negative
* quotients, we have to force the dividend positive for portability.
* The maximum coefficient size is +-16K (for 12-bit data), so this
* code should work for either 16-bit or 32-bit ints.
*/
output_ptr
[
i
]
=
(
JCOEF
)
((
int
)
(
temp
+
(
FAST_FLOAT
)
16384.5
)
-
16384
);
}
}
}
}
#endif
/* DCT_FLOAT_SUPPORTED */
/*
* Initialize FDCT manager.
*/
GLOBAL
(
void
)
jinit_forward_dct
(
j_compress_ptr
cinfo
)
{
my_fdct_ptr
fdct
;
int
i
;
fdct
=
(
my_fdct_ptr
)
(
*
cinfo
->
mem
->
alloc_small
)
((
j_common_ptr
)
cinfo
,
JPOOL_IMAGE
,
SIZEOF
(
my_fdct_controller
));
cinfo
->
fdct
=
(
struct
jpeg_forward_dct
*
)
fdct
;
fdct
->
pub
.
start_pass
=
start_pass_fdctmgr
;
switch
(
cinfo
->
dct_method
)
{
#ifdef DCT_ISLOW_SUPPORTED
case
JDCT_ISLOW
:
fdct
->
pub
.
forward_DCT
=
forward_DCT
;
fdct
->
do_dct
=
jpeg_fdct_islow
;
break
;
#endif
#ifdef DCT_IFAST_SUPPORTED
case
JDCT_IFAST
:
fdct
->
pub
.
forward_DCT
=
forward_DCT
;
fdct
->
do_dct
=
jpeg_fdct_ifast
;
break
;
#endif
#ifdef DCT_FLOAT_SUPPORTED
case
JDCT_FLOAT
:
fdct
->
pub
.
forward_DCT
=
forward_DCT_float
;
fdct
->
do_float_dct
=
jpeg_fdct_float
;
break
;
#endif
default
:
ERREXIT
(
cinfo
,
JERR_NOT_COMPILED
);
break
;
}
/* Mark divisor tables unallocated */
for
(
i
=
0
;
i
<
NUM_QUANT_TBLS
;
i
++
)
{
fdct
->
divisors
[
i
]
=
NULL
;
#ifdef DCT_FLOAT_SUPPORTED
fdct
->
float_divisors
[
i
]
=
NULL
;
#endif
}
}
dlib/external/libjpeg/jchuff.cpp
0 → 100644
View file @
747088ea
/*
* jchuff.c
*
* Copyright (C) 1991-1997, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains Huffman entropy encoding routines.
*
* Much of the complexity here has to do with supporting output suspension.
* If the data destination module demands suspension, we want to be able to
* back up to the start of the current MCU. To do this, we copy state
* variables into local working storage, and update them back to the
* permanent JPEG objects only upon successful completion of an MCU.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jchuff.h"
/* Declarations shared with jcphuff.c */
/* Expanded entropy encoder object for Huffman encoding.
*
* The savable_state subrecord contains fields that change within an MCU,
* but must not be updated permanently until we complete the MCU.
*/
typedef
struct
{
long
put_buffer
;
/* current bit-accumulation buffer */
int
put_bits
;
/* # of bits now in it */
int
last_dc_val
[
MAX_COMPS_IN_SCAN
];
/* last DC coef for each component */
}
savable_state
;
/* This macro is to work around compilers with missing or broken
* structure assignment. You'll need to fix this code if you have
* such a compiler and you change MAX_COMPS_IN_SCAN.
*/
#ifndef NO_STRUCT_ASSIGN
#define ASSIGN_STATE(dest,src) ((dest) = (src))
#else
#if MAX_COMPS_IN_SCAN == 4
#define ASSIGN_STATE(dest,src) \
((dest).put_buffer = (src).put_buffer, \
(dest).put_bits = (src).put_bits, \
(dest).last_dc_val[0] = (src).last_dc_val[0], \
(dest).last_dc_val[1] = (src).last_dc_val[1], \
(dest).last_dc_val[2] = (src).last_dc_val[2], \
(dest).last_dc_val[3] = (src).last_dc_val[3])
#endif
#endif
typedef
struct
{
struct
jpeg_entropy_encoder
pub
;
/* public fields */
savable_state
saved
;
/* Bit buffer & DC state at start of MCU */
/* These fields are NOT loaded into local working state. */
unsigned
int
restarts_to_go
;
/* MCUs left in this restart interval */
int
next_restart_num
;
/* next restart number to write (0-7) */
/* Pointers to derived tables (these workspaces have image lifespan) */
c_derived_tbl
*
dc_derived_tbls
[
NUM_HUFF_TBLS
];
c_derived_tbl
*
ac_derived_tbls
[
NUM_HUFF_TBLS
];
#ifdef ENTROPY_OPT_SUPPORTED
/* Statistics tables for optimization */
long
*
dc_count_ptrs
[
NUM_HUFF_TBLS
];
long
*
ac_count_ptrs
[
NUM_HUFF_TBLS
];
#endif
}
huff_entropy_encoder
;
typedef
huff_entropy_encoder
*
huff_entropy_ptr
;
/* Working state while writing an MCU.
* This struct contains all the fields that are needed by subroutines.
*/
typedef
struct
{
JOCTET
*
next_output_byte
;
/* => next byte to write in buffer */
size_t
free_in_buffer
;
/* # of byte spaces remaining in buffer */
savable_state
cur
;
/* Current bit buffer & DC state */
j_compress_ptr
cinfo
;
/* dump_buffer needs access to this */
}
working_state
;
/* Forward declarations */
METHODDEF
(
int
)
encode_mcu_huff
JPP
((
j_compress_ptr
cinfo
,
JBLOCKROW
*
MCU_data
));
METHODDEF
(
void
)
finish_pass_huff
JPP
((
j_compress_ptr
cinfo
));
#ifdef ENTROPY_OPT_SUPPORTED
METHODDEF
(
int
)
encode_mcu_gather
JPP
((
j_compress_ptr
cinfo
,
JBLOCKROW
*
MCU_data
));
METHODDEF
(
void
)
finish_pass_gather
JPP
((
j_compress_ptr
cinfo
));
#endif
/*
* Initialize for a Huffman-compressed scan.
* If gather_statistics is TRUE, we do not output anything during the scan,
* just count the Huffman symbols used and generate Huffman code tables.
*/
METHODDEF
(
void
)
start_pass_huff
(
j_compress_ptr
cinfo
,
int
gather_statistics
)
{
huff_entropy_ptr
entropy
=
(
huff_entropy_ptr
)
cinfo
->
entropy
;
int
ci
,
dctbl
,
actbl
;
jpeg_component_info
*
compptr
;
if
(
gather_statistics
)
{
#ifdef ENTROPY_OPT_SUPPORTED
entropy
->
pub
.
encode_mcu
=
encode_mcu_gather
;
entropy
->
pub
.
finish_pass
=
finish_pass_gather
;
#else
ERREXIT
(
cinfo
,
JERR_NOT_COMPILED
);
#endif
}
else
{
entropy
->
pub
.
encode_mcu
=
encode_mcu_huff
;
entropy
->
pub
.
finish_pass
=
finish_pass_huff
;
}
for
(
ci
=
0
;
ci
<
cinfo
->
comps_in_scan
;
ci
++
)
{
compptr
=
cinfo
->
cur_comp_info
[
ci
];
dctbl
=
compptr
->
dc_tbl_no
;
actbl
=
compptr
->
ac_tbl_no
;
if
(
gather_statistics
)
{
#ifdef ENTROPY_OPT_SUPPORTED
/* Check for invalid table indexes */
/* (make_c_derived_tbl does this in the other path) */
if
(
dctbl
<
0
||
dctbl
>=
NUM_HUFF_TBLS
)
ERREXIT1
(
cinfo
,
JERR_NO_HUFF_TABLE
,
dctbl
);
if
(
actbl
<
0
||
actbl
>=
NUM_HUFF_TBLS
)
ERREXIT1
(
cinfo
,
JERR_NO_HUFF_TABLE
,
actbl
);
/* Allocate and zero the statistics tables */
/* Note that jpeg_gen_optimal_table expects 257 entries in each table! */
if
(
entropy
->
dc_count_ptrs
[
dctbl
]
==
NULL
)
entropy
->
dc_count_ptrs
[
dctbl
]
=
(
long
*
)
(
*
cinfo
->
mem
->
alloc_small
)
((
j_common_ptr
)
cinfo
,
JPOOL_IMAGE
,
257
*
SIZEOF
(
long
));
MEMZERO
(
entropy
->
dc_count_ptrs
[
dctbl
],
257
*
SIZEOF
(
long
));
if
(
entropy
->
ac_count_ptrs
[
actbl
]
==
NULL
)
entropy
->
ac_count_ptrs
[
actbl
]
=
(
long
*
)
(
*
cinfo
->
mem
->
alloc_small
)
((
j_common_ptr
)
cinfo
,
JPOOL_IMAGE
,
257
*
SIZEOF
(
long
));
MEMZERO
(
entropy
->
ac_count_ptrs
[
actbl
],
257
*
SIZEOF
(
long
));
#endif
}
else
{
/* Compute derived values for Huffman tables */
/* We may do this more than once for a table, but it's not expensive */
jpeg_make_c_derived_tbl
(
cinfo
,
TRUE
,
dctbl
,
&
entropy
->
dc_derived_tbls
[
dctbl
]);
jpeg_make_c_derived_tbl
(
cinfo
,
FALSE
,
actbl
,
&
entropy
->
ac_derived_tbls
[
actbl
]);
}
/* Initialize DC predictions to 0 */
entropy
->
saved
.
last_dc_val
[
ci
]
=
0
;
}
/* Initialize bit buffer to empty */
entropy
->
saved
.
put_buffer
=
0
;
entropy
->
saved
.
put_bits
=
0
;
/* Initialize restart stuff */
entropy
->
restarts_to_go
=
cinfo
->
restart_interval
;
entropy
->
next_restart_num
=
0
;
}
/*
* Compute the derived values for a Huffman table.
* This routine also performs some validation checks on the table.
*
* Note this is also used by jcphuff.c.
*/
GLOBAL
(
void
)
jpeg_make_c_derived_tbl
(
j_compress_ptr
cinfo
,
int
isDC
,
int
tblno
,
c_derived_tbl
**
pdtbl
)
{
JHUFF_TBL
*
htbl
;
c_derived_tbl
*
dtbl
;
int
p
,
i
,
l
,
lastp
,
si
,
maxsymbol
;
char
huffsize
[
257
];
unsigned
int
huffcode
[
257
];
unsigned
int
code
;
/* Note that huffsize[] and huffcode[] are filled in code-length order,
* paralleling the order of the symbols themselves in htbl->huffval[].
*/
/* Find the input Huffman table */
if
(
tblno
<
0
||
tblno
>=
NUM_HUFF_TBLS
)
ERREXIT1
(
cinfo
,
JERR_NO_HUFF_TABLE
,
tblno
);
htbl
=
isDC
?
cinfo
->
dc_huff_tbl_ptrs
[
tblno
]
:
cinfo
->
ac_huff_tbl_ptrs
[
tblno
];
if
(
htbl
==
NULL
)
ERREXIT1
(
cinfo
,
JERR_NO_HUFF_TABLE
,
tblno
);
/* Allocate a workspace if we haven't already done so. */
if
(
*
pdtbl
==
NULL
)
*
pdtbl
=
(
c_derived_tbl
*
)
(
*
cinfo
->
mem
->
alloc_small
)
((
j_common_ptr
)
cinfo
,
JPOOL_IMAGE
,
SIZEOF
(
c_derived_tbl
));
dtbl
=
*
pdtbl
;
/* Figure C.1: make table of Huffman code length for each symbol */
p
=
0
;
for
(
l
=
1
;
l
<=
16
;
l
++
)
{
i
=
(
int
)
htbl
->
bits
[
l
];
if
(
i
<
0
||
p
+
i
>
256
)
/* protect against table overrun */
ERREXIT
(
cinfo
,
JERR_BAD_HUFF_TABLE
);
while
(
i
--
)
huffsize
[
p
++
]
=
(
char
)
l
;
}
huffsize
[
p
]
=
0
;
lastp
=
p
;
/* Figure C.2: generate the codes themselves */
/* We also validate that the counts represent a legal Huffman code tree. */
code
=
0
;
si
=
huffsize
[
0
];
p
=
0
;
while
(
huffsize
[
p
])
{
while
(((
int
)
huffsize
[
p
])
==
si
)
{
huffcode
[
p
++
]
=
code
;
code
++
;
}
/* code is now 1 more than the last code used for codelength si; but
* it must still fit in si bits, since no code is allowed to be all ones.
*/
if
(((
long
)
code
)
>=
(((
long
)
1
)
<<
si
))
ERREXIT
(
cinfo
,
JERR_BAD_HUFF_TABLE
);
code
<<=
1
;
si
++
;
}
/* Figure C.3: generate encoding tables */
/* These are code and size indexed by symbol value */
/* Set all codeless symbols to have code length 0;
* this lets us detect duplicate VAL entries here, and later
* allows emit_bits to detect any attempt to emit such symbols.
*/
MEMZERO
(
dtbl
->
ehufsi
,
SIZEOF
(
dtbl
->
ehufsi
));
/* This is also a convenient place to check for out-of-range
* and duplicated VAL entries. We allow 0..255 for AC symbols
* but only 0..15 for DC. (We could constrain them further
* based on data depth and mode, but this seems enough.)
*/
maxsymbol
=
isDC
?
15
:
255
;
for
(
p
=
0
;
p
<
lastp
;
p
++
)
{
i
=
htbl
->
huffval
[
p
];
if
(
i
<
0
||
i
>
maxsymbol
||
dtbl
->
ehufsi
[
i
])
ERREXIT
(
cinfo
,
JERR_BAD_HUFF_TABLE
);
dtbl
->
ehufco
[
i
]
=
huffcode
[
p
];
dtbl
->
ehufsi
[
i
]
=
huffsize
[
p
];
}
}
/* Outputting bytes to the file */
/* Emit a byte, taking 'action' if must suspend. */
#define emit_byte(state,val,action) \
{ *(state)->next_output_byte++ = (JOCTET) (val); \
if (--(state)->free_in_buffer == 0) \
if (! dump_buffer(state)) \
{ action; } }
LOCAL
(
int
)
dump_buffer
(
working_state
*
state
)
/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */
{
struct
jpeg_destination_mgr
*
dest
=
state
->
cinfo
->
dest
;
if
(
!
(
*
dest
->
empty_output_buffer
)
(
state
->
cinfo
))
return
FALSE
;
/* After a successful buffer dump, must reset buffer pointers */
state
->
next_output_byte
=
dest
->
next_output_byte
;
state
->
free_in_buffer
=
dest
->
free_in_buffer
;
return
TRUE
;
}
/* Outputting bits to the file */
/* Only the right 24 bits of put_buffer are used; the valid bits are
* left-justified in this part. At most 16 bits can be passed to emit_bits
* in one call, and we never retain more than 7 bits in put_buffer
* between calls, so 24 bits are sufficient.
*/
INLINE
LOCAL
(
int
)
emit_bits
(
working_state
*
state
,
unsigned
int
code
,
int
size
)
/* Emit some bits; return TRUE if successful, FALSE if must suspend */
{
/* This routine is heavily used, so it's worth coding tightly. */
register
long
put_buffer
=
(
long
)
code
;
register
int
put_bits
=
state
->
cur
.
put_bits
;
/* if size is 0, caller used an invalid Huffman table entry */
if
(
size
==
0
)
ERREXIT
(
state
->
cinfo
,
JERR_HUFF_MISSING_CODE
);
put_buffer
&=
(((
long
)
1
)
<<
size
)
-
1
;
/* mask off any extra bits in code */
put_bits
+=
size
;
/* new number of bits in buffer */
put_buffer
<<=
24
-
put_bits
;
/* align incoming bits */
put_buffer
|=
state
->
cur
.
put_buffer
;
/* and merge with old buffer contents */
while
(
put_bits
>=
8
)
{
int
c
=
(
int
)
((
put_buffer
>>
16
)
&
0xFF
);
emit_byte
(
state
,
c
,
return
FALSE
);
if
(
c
==
0xFF
)
{
/* need to stuff a zero byte? */
emit_byte
(
state
,
0
,
return
FALSE
);
}
put_buffer
<<=
8
;
put_bits
-=
8
;
}
state
->
cur
.
put_buffer
=
put_buffer
;
/* update state variables */
state
->
cur
.
put_bits
=
put_bits
;
return
TRUE
;
}
LOCAL
(
int
)
flush_bits
(
working_state
*
state
)
{
if
(
!
emit_bits
(
state
,
0x7F
,
7
))
/* fill any partial byte with ones */
return
FALSE
;
state
->
cur
.
put_buffer
=
0
;
/* and reset bit-buffer to empty */
state
->
cur
.
put_bits
=
0
;
return
TRUE
;
}
/* Encode a single block's worth of coefficients */
LOCAL
(
int
)
encode_one_block
(
working_state
*
state
,
JCOEFPTR
block
,
int
last_dc_val
,
c_derived_tbl
*
dctbl
,
c_derived_tbl
*
actbl
)
{
register
int
temp
,
temp2
;
register
int
nbits
;
register
int
k
,
r
,
i
;
/* Encode the DC coefficient difference per section F.1.2.1 */
temp
=
temp2
=
block
[
0
]
-
last_dc_val
;
if
(
temp
<
0
)
{
temp
=
-
temp
;
/* temp is abs value of input */
/* For a negative input, want temp2 = bitwise complement of abs(input) */
/* This code assumes we are on a two's complement machine */
temp2
--
;
}
/* Find the number of bits needed for the magnitude of the coefficient */
nbits
=
0
;
while
(
temp
)
{
nbits
++
;
temp
>>=
1
;
}
/* Check for out-of-range coefficient values.
* Since we're encoding a difference, the range limit is twice as much.
*/
if
(
nbits
>
MAX_COEF_BITS
+
1
)
ERREXIT
(
state
->
cinfo
,
JERR_BAD_DCT_COEF
);
/* Emit the Huffman-coded symbol for the number of bits */
if
(
!
emit_bits
(
state
,
dctbl
->
ehufco
[
nbits
],
dctbl
->
ehufsi
[
nbits
]))
return
FALSE
;
/* Emit that number of bits of the value, if positive, */
/* or the complement of its magnitude, if negative. */
if
(
nbits
)
/* emit_bits rejects calls with size 0 */
if
(
!
emit_bits
(
state
,
(
unsigned
int
)
temp2
,
nbits
))
return
FALSE
;
/* Encode the AC coefficients per section F.1.2.2 */
r
=
0
;
/* r = run length of zeros */
for
(
k
=
1
;
k
<
DCTSIZE2
;
k
++
)
{
if
((
temp
=
block
[
jpeg_natural_order
[
k
]])
==
0
)
{
r
++
;
}
else
{
/* if run length > 15, must emit special run-length-16 codes (0xF0) */
while
(
r
>
15
)
{
if
(
!
emit_bits
(
state
,
actbl
->
ehufco
[
0xF0
],
actbl
->
ehufsi
[
0xF0
]))
return
FALSE
;
r
-=
16
;
}
temp2
=
temp
;
if
(
temp
<
0
)
{
temp
=
-
temp
;
/* temp is abs value of input */
/* This code assumes we are on a two's complement machine */
temp2
--
;
}
/* Find the number of bits needed for the magnitude of the coefficient */
nbits
=
1
;
/* there must be at least one 1 bit */
while
((
temp
>>=
1
))
nbits
++
;
/* Check for out-of-range coefficient values */
if
(
nbits
>
MAX_COEF_BITS
)
ERREXIT
(
state
->
cinfo
,
JERR_BAD_DCT_COEF
);
/* Emit Huffman symbol for run length / number of bits */
i
=
(
r
<<
4
)
+
nbits
;
if
(
!
emit_bits
(
state
,
actbl
->
ehufco
[
i
],
actbl
->
ehufsi
[
i
]))
return
FALSE
;
/* Emit that number of bits of the value, if positive, */
/* or the complement of its magnitude, if negative. */
if
(
!
emit_bits
(
state
,
(
unsigned
int
)
temp2
,
nbits
))
return
FALSE
;
r
=
0
;
}
}
/* If the last coef(s) were zero, emit an end-of-block code */
if
(
r
>
0
)
if
(
!
emit_bits
(
state
,
actbl
->
ehufco
[
0
],
actbl
->
ehufsi
[
0
]))
return
FALSE
;
return
TRUE
;
}
/*
* Emit a restart marker & resynchronize predictions.
*/
LOCAL
(
int
)
emit_restart
(
working_state
*
state
,
int
restart_num
)
{
int
ci
;
if
(
!
flush_bits
(
state
))
return
FALSE
;
emit_byte
(
state
,
0xFF
,
return
FALSE
);
emit_byte
(
state
,
JPEG_RST0
+
restart_num
,
return
FALSE
);
/* Re-initialize DC predictions to 0 */
for
(
ci
=
0
;
ci
<
state
->
cinfo
->
comps_in_scan
;
ci
++
)
state
->
cur
.
last_dc_val
[
ci
]
=
0
;
/* The restart counter is not updated until we successfully write the MCU. */
return
TRUE
;
}
/*
* Encode and output one MCU's worth of Huffman-compressed coefficients.
*/
METHODDEF
(
int
)
encode_mcu_huff
(
j_compress_ptr
cinfo
,
JBLOCKROW
*
MCU_data
)
{
huff_entropy_ptr
entropy
=
(
huff_entropy_ptr
)
cinfo
->
entropy
;
working_state
state
;
int
blkn
,
ci
;
jpeg_component_info
*
compptr
;
/* Load up working state */
state
.
next_output_byte
=
cinfo
->
dest
->
next_output_byte
;
state
.
free_in_buffer
=
cinfo
->
dest
->
free_in_buffer
;
ASSIGN_STATE
(
state
.
cur
,
entropy
->
saved
);
state
.
cinfo
=
cinfo
;
/* Emit restart marker if needed */
if
(
cinfo
->
restart_interval
)
{
if
(
entropy
->
restarts_to_go
==
0
)
if
(
!
emit_restart
(
&
state
,
entropy
->
next_restart_num
))
return
FALSE
;
}
/* Encode the MCU data blocks */
for
(
blkn
=
0
;
blkn
<
cinfo
->
blocks_in_MCU
;
blkn
++
)
{
ci
=
cinfo
->
MCU_membership
[
blkn
];
compptr
=
cinfo
->
cur_comp_info
[
ci
];
if
(
!
encode_one_block
(
&
state
,
MCU_data
[
blkn
][
0
],
state
.
cur
.
last_dc_val
[
ci
],
entropy
->
dc_derived_tbls
[
compptr
->
dc_tbl_no
],
entropy
->
ac_derived_tbls
[
compptr
->
ac_tbl_no
]))
return
FALSE
;
/* Update last_dc_val */
state
.
cur
.
last_dc_val
[
ci
]
=
MCU_data
[
blkn
][
0
][
0
];
}
/* Completed MCU, so update state */
cinfo
->
dest
->
next_output_byte
=
state
.
next_output_byte
;
cinfo
->
dest
->
free_in_buffer
=
state
.
free_in_buffer
;
ASSIGN_STATE
(
entropy
->
saved
,
state
.
cur
);
/* Update restart-interval state too */
if
(
cinfo
->
restart_interval
)
{
if
(
entropy
->
restarts_to_go
==
0
)
{
entropy
->
restarts_to_go
=
cinfo
->
restart_interval
;
entropy
->
next_restart_num
++
;
entropy
->
next_restart_num
&=
7
;
}
entropy
->
restarts_to_go
--
;
}
return
TRUE
;
}
/*
* Finish up at the end of a Huffman-compressed scan.
*/
METHODDEF
(
void
)
finish_pass_huff
(
j_compress_ptr
cinfo
)
{
huff_entropy_ptr
entropy
=
(
huff_entropy_ptr
)
cinfo
->
entropy
;
working_state
state
;
/* Load up working state ... flush_bits needs it */
state
.
next_output_byte
=
cinfo
->
dest
->
next_output_byte
;
state
.
free_in_buffer
=
cinfo
->
dest
->
free_in_buffer
;
ASSIGN_STATE
(
state
.
cur
,
entropy
->
saved
);
state
.
cinfo
=
cinfo
;
/* Flush out the last data */
if
(
!
flush_bits
(
&
state
))
ERREXIT
(
cinfo
,
JERR_CANT_SUSPEND
);
/* Update state */
cinfo
->
dest
->
next_output_byte
=
state
.
next_output_byte
;
cinfo
->
dest
->
free_in_buffer
=
state
.
free_in_buffer
;
ASSIGN_STATE
(
entropy
->
saved
,
state
.
cur
);
}
/*
* Huffman coding optimization.
*
* We first scan the supplied data and count the number of uses of each symbol
* that is to be Huffman-coded. (This process MUST agree with the code above.)
* Then we build a Huffman coding tree for the observed counts.
* Symbols which are not needed at all for the particular image are not
* assigned any code, which saves space in the DHT marker as well as in
* the compressed data.
*/
#ifdef ENTROPY_OPT_SUPPORTED
/* Process a single block's worth of coefficients */
LOCAL
(
void
)
htest_one_block
(
j_compress_ptr
cinfo
,
JCOEFPTR
block
,
int
last_dc_val
,
long
dc_counts
[],
long
ac_counts
[])
{
register
int
temp
;
register
int
nbits
;
register
int
k
,
r
;
/* Encode the DC coefficient difference per section F.1.2.1 */
temp
=
block
[
0
]
-
last_dc_val
;
if
(
temp
<
0
)
temp
=
-
temp
;
/* Find the number of bits needed for the magnitude of the coefficient */
nbits
=
0
;
while
(
temp
)
{
nbits
++
;
temp
>>=
1
;
}
/* Check for out-of-range coefficient values.
* Since we're encoding a difference, the range limit is twice as much.
*/
if
(
nbits
>
MAX_COEF_BITS
+
1
)
ERREXIT
(
cinfo
,
JERR_BAD_DCT_COEF
);
/* Count the Huffman symbol for the number of bits */
dc_counts
[
nbits
]
++
;
/* Encode the AC coefficients per section F.1.2.2 */
r
=
0
;
/* r = run length of zeros */
for
(
k
=
1
;
k
<
DCTSIZE2
;
k
++
)
{
if
((
temp
=
block
[
jpeg_natural_order
[
k
]])
==
0
)
{
r
++
;
}
else
{
/* if run length > 15, must emit special run-length-16 codes (0xF0) */
while
(
r
>
15
)
{
ac_counts
[
0xF0
]
++
;
r
-=
16
;
}
/* Find the number of bits needed for the magnitude of the coefficient */
if
(
temp
<
0
)
temp
=
-
temp
;
/* Find the number of bits needed for the magnitude of the coefficient */
nbits
=
1
;
/* there must be at least one 1 bit */
while
((
temp
>>=
1
))
nbits
++
;
/* Check for out-of-range coefficient values */
if
(
nbits
>
MAX_COEF_BITS
)
ERREXIT
(
cinfo
,
JERR_BAD_DCT_COEF
);
/* Count Huffman symbol for run length / number of bits */
ac_counts
[(
r
<<
4
)
+
nbits
]
++
;
r
=
0
;
}
}
/* If the last coef(s) were zero, emit an end-of-block code */
if
(
r
>
0
)
ac_counts
[
0
]
++
;
}
/*
* Trial-encode one MCU's worth of Huffman-compressed coefficients.
* No data is actually output, so no suspension return is possible.
*/
METHODDEF
(
int
)
encode_mcu_gather
(
j_compress_ptr
cinfo
,
JBLOCKROW
*
MCU_data
)
{
huff_entropy_ptr
entropy
=
(
huff_entropy_ptr
)
cinfo
->
entropy
;
int
blkn
,
ci
;
jpeg_component_info
*
compptr
;
/* Take care of restart intervals if needed */
if
(
cinfo
->
restart_interval
)
{
if
(
entropy
->
restarts_to_go
==
0
)
{
/* Re-initialize DC predictions to 0 */
for
(
ci
=
0
;
ci
<
cinfo
->
comps_in_scan
;
ci
++
)
entropy
->
saved
.
last_dc_val
[
ci
]
=
0
;
/* Update restart state */
entropy
->
restarts_to_go
=
cinfo
->
restart_interval
;
}
entropy
->
restarts_to_go
--
;
}
for
(
blkn
=
0
;
blkn
<
cinfo
->
blocks_in_MCU
;
blkn
++
)
{
ci
=
cinfo
->
MCU_membership
[
blkn
];
compptr
=
cinfo
->
cur_comp_info
[
ci
];
htest_one_block
(
cinfo
,
MCU_data
[
blkn
][
0
],
entropy
->
saved
.
last_dc_val
[
ci
],
entropy
->
dc_count_ptrs
[
compptr
->
dc_tbl_no
],
entropy
->
ac_count_ptrs
[
compptr
->
ac_tbl_no
]);
entropy
->
saved
.
last_dc_val
[
ci
]
=
MCU_data
[
blkn
][
0
][
0
];
}
return
TRUE
;
}
/*
* Generate the best Huffman code table for the given counts, fill htbl.
* Note this is also used by jcphuff.c.
*
* The JPEG standard requires that no symbol be assigned a codeword of all
* one bits (so that padding bits added at the end of a compressed segment
* can't look like a valid code). Because of the canonical ordering of
* codewords, this just means that there must be an unused slot in the
* longest codeword length category. Section K.2 of the JPEG spec suggests
* reserving such a slot by pretending that symbol 256 is a valid symbol
* with count 1. In theory that's not optimal; giving it count zero but
* including it in the symbol set anyway should give a better Huffman code.
* But the theoretically better code actually seems to come out worse in
* practice, because it produces more all-ones bytes (which incur stuffed
* zero bytes in the final file). In any case the difference is tiny.
*
* The JPEG standard requires Huffman codes to be no more than 16 bits long.
* If some symbols have a very small but nonzero probability, the Huffman tree
* must be adjusted to meet the code length restriction. We currently use
* the adjustment method suggested in JPEG section K.2. This method is *not*
* optimal; it may not choose the best possible limited-length code. But
* typically only very-low-frequency symbols will be given less-than-optimal
* lengths, so the code is almost optimal. Experimental comparisons against
* an optimal limited-length-code algorithm indicate that the difference is
* microscopic --- usually less than a hundredth of a percent of total size.
* So the extra complexity of an optimal algorithm doesn't seem worthwhile.
*/
GLOBAL
(
void
)
jpeg_gen_optimal_table
(
j_compress_ptr
cinfo
,
JHUFF_TBL
*
htbl
,
long
freq
[])
{
#define MAX_CLEN 32
/* assumed maximum initial code length */
unsigned
short
bits
[
MAX_CLEN
+
1
];
/* bits[k] = # of symbols with code length k */
int
codesize
[
257
];
/* codesize[k] = code length of symbol k */
int
others
[
257
];
/* next symbol in current branch of tree */
int
c1
,
c2
;
int
p
,
i
,
j
;
long
v
;
/* This algorithm is explained in section K.2 of the JPEG standard */
MEMZERO
(
bits
,
SIZEOF
(
bits
));
MEMZERO
(
codesize
,
SIZEOF
(
codesize
));
for
(
i
=
0
;
i
<
257
;
i
++
)
others
[
i
]
=
-
1
;
/* init links to empty */
freq
[
256
]
=
1
;
/* make sure 256 has a nonzero count */
/* Including the pseudo-symbol 256 in the Huffman procedure guarantees
* that no real symbol is given code-value of all ones, because 256
* will be placed last in the largest codeword category.
*/
/* Huffman's basic algorithm to assign optimal code lengths to symbols */
for
(;;)
{
/* Find the smallest nonzero frequency, set c1 = its symbol */
/* In case of ties, take the larger symbol number */
c1
=
-
1
;
v
=
1000000000L
;
for
(
i
=
0
;
i
<=
256
;
i
++
)
{
if
(
freq
[
i
]
&&
freq
[
i
]
<=
v
)
{
v
=
freq
[
i
];
c1
=
i
;
}
}
/* Find the next smallest nonzero frequency, set c2 = its symbol */
/* In case of ties, take the larger symbol number */
c2
=
-
1
;
v
=
1000000000L
;
for
(
i
=
0
;
i
<=
256
;
i
++
)
{
if
(
freq
[
i
]
&&
freq
[
i
]
<=
v
&&
i
!=
c1
)
{
v
=
freq
[
i
];
c2
=
i
;
}
}
/* Done if we've merged everything into one frequency */
if
(
c2
<
0
)
break
;
/* Else merge the two counts/trees */
freq
[
c1
]
+=
freq
[
c2
];
freq
[
c2
]
=
0
;
/* Increment the codesize of everything in c1's tree branch */
codesize
[
c1
]
++
;
while
(
others
[
c1
]
>=
0
)
{
c1
=
others
[
c1
];
codesize
[
c1
]
++
;
}
others
[
c1
]
=
c2
;
/* chain c2 onto c1's tree branch */
/* Increment the codesize of everything in c2's tree branch */
codesize
[
c2
]
++
;
while
(
others
[
c2
]
>=
0
)
{
c2
=
others
[
c2
];
codesize
[
c2
]
++
;
}
}
/* Now count the number of symbols of each code length */
for
(
i
=
0
;
i
<=
256
;
i
++
)
{
if
(
codesize
[
i
])
{
/* The JPEG standard seems to think that this can't happen, */
/* but I'm paranoid... */
if
(
codesize
[
i
]
>
MAX_CLEN
)
ERREXIT
(
cinfo
,
JERR_HUFF_CLEN_OVERFLOW
);
bits
[
codesize
[
i
]]
++
;
}
}
/* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure
* Huffman procedure assigned any such lengths, we must adjust the coding.
* Here is what the JPEG spec says about how this next bit works:
* Since symbols are paired for the longest Huffman code, the symbols are
* removed from this length category two at a time. The prefix for the pair
* (which is one bit shorter) is allocated to one of the pair; then,
* skipping the BITS entry for that prefix length, a code word from the next
* shortest nonzero BITS entry is converted into a prefix for two code words
* one bit longer.
*/
for
(
i
=
MAX_CLEN
;
i
>
16
;
i
--
)
{
while
(
bits
[
i
]
>
0
)
{
j
=
i
-
2
;
/* find length of new prefix to be used */
while
(
bits
[
j
]
==
0
)
j
--
;
bits
[
i
]
-=
2
;
/* remove two symbols */
bits
[
i
-
1
]
++
;
/* one goes in this length */
bits
[
j
+
1
]
+=
2
;
/* two new symbols in this length */
bits
[
j
]
--
;
/* symbol of this length is now a prefix */
}
}
/* Remove the count for the pseudo-symbol 256 from the largest codelength */
while
(
bits
[
i
]
==
0
)
/* find largest codelength still in use */
i
--
;
bits
[
i
]
--
;
/* Return final symbol counts (only for lengths 0..16) */
MEMCOPY
(
htbl
->
bits
,
bits
,
SIZEOF
(
htbl
->
bits
));
/* Return a list of the symbols sorted by code length */
/* It's not real clear to me why we don't need to consider the codelength
* changes made above, but the JPEG spec seems to think this works.
*/
p
=
0
;
for
(
i
=
1
;
i
<=
MAX_CLEN
;
i
++
)
{
for
(
j
=
0
;
j
<=
255
;
j
++
)
{
if
(
codesize
[
j
]
==
i
)
{
htbl
->
huffval
[
p
]
=
(
unsigned
short
)
j
;
p
++
;
}
}
}
/* Set sent_table FALSE so updated table will be written to JPEG file. */
htbl
->
sent_table
=
FALSE
;
}
/*
* Finish up a statistics-gathering pass and create the new Huffman tables.
*/
METHODDEF
(
void
)
finish_pass_gather
(
j_compress_ptr
cinfo
)
{
huff_entropy_ptr
entropy
=
(
huff_entropy_ptr
)
cinfo
->
entropy
;
int
ci
,
dctbl
,
actbl
;
jpeg_component_info
*
compptr
;
JHUFF_TBL
**
htblptr
;
int
did_dc
[
NUM_HUFF_TBLS
];
int
did_ac
[
NUM_HUFF_TBLS
];
/* It's important not to apply jpeg_gen_optimal_table more than once
* per table, because it clobbers the input frequency counts!
*/
MEMZERO
(
did_dc
,
SIZEOF
(
did_dc
));
MEMZERO
(
did_ac
,
SIZEOF
(
did_ac
));
for
(
ci
=
0
;
ci
<
cinfo
->
comps_in_scan
;
ci
++
)
{
compptr
=
cinfo
->
cur_comp_info
[
ci
];
dctbl
=
compptr
->
dc_tbl_no
;
actbl
=
compptr
->
ac_tbl_no
;
if
(
!
did_dc
[
dctbl
])
{
htblptr
=
&
cinfo
->
dc_huff_tbl_ptrs
[
dctbl
];
if
(
*
htblptr
==
NULL
)
*
htblptr
=
jpeg_alloc_huff_table
((
j_common_ptr
)
cinfo
);
jpeg_gen_optimal_table
(
cinfo
,
*
htblptr
,
entropy
->
dc_count_ptrs
[
dctbl
]);
did_dc
[
dctbl
]
=
TRUE
;
}
if
(
!
did_ac
[
actbl
])
{
htblptr
=
&
cinfo
->
ac_huff_tbl_ptrs
[
actbl
];
if
(
*
htblptr
==
NULL
)
*
htblptr
=
jpeg_alloc_huff_table
((
j_common_ptr
)
cinfo
);
jpeg_gen_optimal_table
(
cinfo
,
*
htblptr
,
entropy
->
ac_count_ptrs
[
actbl
]);
did_ac
[
actbl
]
=
TRUE
;
}
}
}
#endif
/* ENTROPY_OPT_SUPPORTED */
/*
* Module initialization routine for Huffman entropy encoding.
*/
GLOBAL
(
void
)
jinit_huff_encoder
(
j_compress_ptr
cinfo
)
{
huff_entropy_ptr
entropy
;
int
i
;
entropy
=
(
huff_entropy_ptr
)
(
*
cinfo
->
mem
->
alloc_small
)
((
j_common_ptr
)
cinfo
,
JPOOL_IMAGE
,
SIZEOF
(
huff_entropy_encoder
));
cinfo
->
entropy
=
(
struct
jpeg_entropy_encoder
*
)
entropy
;
entropy
->
pub
.
start_pass
=
start_pass_huff
;
/* Mark tables unallocated */
for
(
i
=
0
;
i
<
NUM_HUFF_TBLS
;
i
++
)
{
entropy
->
dc_derived_tbls
[
i
]
=
entropy
->
ac_derived_tbls
[
i
]
=
NULL
;
#ifdef ENTROPY_OPT_SUPPORTED
entropy
->
dc_count_ptrs
[
i
]
=
entropy
->
ac_count_ptrs
[
i
]
=
NULL
;
#endif
}
}
dlib/external/libjpeg/jchuff.h
0 → 100644
View file @
747088ea
/*
* jchuff.h
*
* Copyright (C) 1991-1997, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains declarations for Huffman entropy encoding routines
* that are shared between the sequential encoder (jchuff.c) and the
* progressive encoder (jcphuff.c). No other modules need to see these.
*/
/* The legal range of a DCT coefficient is
* -1024 .. +1023 for 8-bit data;
* -16384 .. +16383 for 12-bit data.
* Hence the magnitude should always fit in 10 or 14 bits respectively.
*/
#if BITS_IN_JSAMPLE == 8
#define MAX_COEF_BITS 10
#else
#define MAX_COEF_BITS 14
#endif
/* Derived data constructed for each Huffman table */
typedef
struct
{
unsigned
int
ehufco
[
256
];
/* code for each symbol */
char
ehufsi
[
256
];
/* length of code for each symbol */
/* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */
}
c_derived_tbl
;
/* Short forms of external names for systems with brain-damaged linkers. */
#ifdef NEED_SHORT_EXTERNAL_NAMES
#define jpeg_make_c_derived_tbl jMkCDerived
#define jpeg_gen_optimal_table jGenOptTbl
#endif
/* NEED_SHORT_EXTERNAL_NAMES */
/* Expand a Huffman table definition into the derived format */
EXTERN
(
void
)
jpeg_make_c_derived_tbl
JPP
((
j_compress_ptr
cinfo
,
int
isDC
,
int
tblno
,
c_derived_tbl
**
pdtbl
));
/* Generate an optimal table definition given the specified counts */
EXTERN
(
void
)
jpeg_gen_optimal_table
JPP
((
j_compress_ptr
cinfo
,
JHUFF_TBL
*
htbl
,
long
freq
[]));
dlib/external/libjpeg/jcinit.cpp
0 → 100644
View file @
747088ea
/*
* jcinit.c
*
* Copyright (C) 1991-1997, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains initialization logic for the JPEG compressor.
* This routine is in charge of selecting the modules to be executed and
* making an initialization call to each one.
*
* Logically, this code belongs in jcmaster.c. It's split out because
* linking this routine implies linking the entire compression library.
* For a transcoding-only application, we want to be able to use jcmaster.c
* without linking in the whole library.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/*
* Master selection of compression modules.
* This is done once at the start of processing an image. We determine
* which modules will be used and give them appropriate initialization calls.
*/
GLOBAL
(
void
)
jinit_compress_master
(
j_compress_ptr
cinfo
)
{
/* Initialize master control (includes parameter checking/processing) */
jinit_c_master_control
(
cinfo
,
FALSE
/* full compression */
);
/* Preprocessing */
if
(
!
cinfo
->
raw_data_in
)
{
jinit_color_converter
(
cinfo
);
jinit_downsampler
(
cinfo
);
jinit_c_prep_controller
(
cinfo
,
FALSE
/* never need full buffer here */
);
}
/* Forward DCT */
jinit_forward_dct
(
cinfo
);
/* Entropy encoding: either Huffman or arithmetic coding. */
if
(
cinfo
->
arith_code
)
{
ERREXIT
(
cinfo
,
JERR_ARITH_NOTIMPL
);
}
else
{
if
(
cinfo
->
progressive_mode
)
{
#ifdef C_PROGRESSIVE_SUPPORTED
jinit_phuff_encoder
(
cinfo
);
#else
ERREXIT
(
cinfo
,
JERR_NOT_COMPILED
);
#endif
}
else
jinit_huff_encoder
(
cinfo
);
}
/* Need a full-image coefficient buffer in any multi-pass mode. */
jinit_c_coef_controller
(
cinfo
,
(
int
)
(
cinfo
->
num_scans
>
1
||
cinfo
->
optimize_coding
));
jinit_c_main_controller
(
cinfo
,
FALSE
/* never need full buffer here */
);
jinit_marker_writer
(
cinfo
);
/* We can now tell the memory manager to allocate virtual arrays. */
(
*
cinfo
->
mem
->
realize_virt_arrays
)
((
j_common_ptr
)
cinfo
);
/* Write the datastream header (SOI) immediately.
* Frame and scan headers are postponed till later.
* This lets application insert special markers after the SOI.
*/
(
*
cinfo
->
marker
->
write_file_header
)
(
cinfo
);
}
dlib/external/libjpeg/jcmainct.cpp
0 → 100644
View file @
747088ea
/*
* jcmainct.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains the main buffer controller for compression.
* The main buffer lies between the pre-processor and the JPEG
* compressor proper; it holds downsampled data in the JPEG colorspace.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/* Note: currently, there is no operating mode in which a full-image buffer
* is needed at this step. If there were, that mode could not be used with
* "raw data" input, since this module is bypassed in that case. However,
* we've left the code here for possible use in special applications.
*/
#undef FULL_MAIN_BUFFER_SUPPORTED
/* Private buffer controller object */
typedef
struct
{
struct
jpeg_c_main_controller
pub
;
/* public fields */
JDIMENSION
cur_iMCU_row
;
/* number of current iMCU row */
JDIMENSION
rowgroup_ctr
;
/* counts row groups received in iMCU row */
int
suspended
;
/* remember if we suspended output */
J_BUF_MODE
pass_mode
;
/* current operating mode */
/* If using just a strip buffer, this points to the entire set of buffers
* (we allocate one for each component). In the full-image case, this
* points to the currently accessible strips of the virtual arrays.
*/
JSAMPARRAY
buffer
[
MAX_COMPONENTS
];
#ifdef FULL_MAIN_BUFFER_SUPPORTED
/* If using full-image storage, this array holds pointers to virtual-array
* control blocks for each component. Unused if not full-image storage.
*/
jvirt_sarray_ptr
whole_image
[
MAX_COMPONENTS
];
#endif
}
my_main_controller
;
typedef
my_main_controller
*
my_main_ptr
;
/* Forward declarations */
METHODDEF
(
void
)
process_data_simple_main
JPP
((
j_compress_ptr
cinfo
,
JSAMPARRAY
input_buf
,
JDIMENSION
*
in_row_ctr
,
JDIMENSION
in_rows_avail
));
#ifdef FULL_MAIN_BUFFER_SUPPORTED
METHODDEF
(
void
)
process_data_buffer_main
JPP
((
j_compress_ptr
cinfo
,
JSAMPARRAY
input_buf
,
JDIMENSION
*
in_row_ctr
,
JDIMENSION
in_rows_avail
));
#endif
/*
* Initialize for a processing pass.
*/
METHODDEF
(
void
)
start_pass_main
(
j_compress_ptr
cinfo
,
J_BUF_MODE
pass_mode
)
{
my_main_ptr
main
=
(
my_main_ptr
)
cinfo
->
main
;
/* Do nothing in raw-data mode. */
if
(
cinfo
->
raw_data_in
)
return
;
main
->
cur_iMCU_row
=
0
;
/* initialize counters */
main
->
rowgroup_ctr
=
0
;
main
->
suspended
=
FALSE
;
main
->
pass_mode
=
pass_mode
;
/* save mode for use by process_data */
switch
(
pass_mode
)
{
case
JBUF_PASS_THRU
:
#ifdef FULL_MAIN_BUFFER_SUPPORTED
if
(
main
->
whole_image
[
0
]
!=
NULL
)
ERREXIT
(
cinfo
,
JERR_BAD_BUFFER_MODE
);
#endif
main
->
pub
.
process_data
=
process_data_simple_main
;
break
;
#ifdef FULL_MAIN_BUFFER_SUPPORTED
case
JBUF_SAVE_SOURCE
:
case
JBUF_CRANK_DEST
:
case
JBUF_SAVE_AND_PASS
:
if
(
main
->
whole_image
[
0
]
==
NULL
)
ERREXIT
(
cinfo
,
JERR_BAD_BUFFER_MODE
);
main
->
pub
.
process_data
=
process_data_buffer_main
;
break
;
#endif
default
:
ERREXIT
(
cinfo
,
JERR_BAD_BUFFER_MODE
);
break
;
}
}
/*
* Process some data.
* This routine handles the simple pass-through mode,
* where we have only a strip buffer.
*/
METHODDEF
(
void
)
process_data_simple_main
(
j_compress_ptr
cinfo
,
JSAMPARRAY
input_buf
,
JDIMENSION
*
in_row_ctr
,
JDIMENSION
in_rows_avail
)
{
my_main_ptr
main
=
(
my_main_ptr
)
cinfo
->
main
;
while
(
main
->
cur_iMCU_row
<
cinfo
->
total_iMCU_rows
)
{
/* Read input data if we haven't filled the main buffer yet */
if
(
main
->
rowgroup_ctr
<
DCTSIZE
)
(
*
cinfo
->
prep
->
pre_process_data
)
(
cinfo
,
input_buf
,
in_row_ctr
,
in_rows_avail
,
main
->
buffer
,
&
main
->
rowgroup_ctr
,
(
JDIMENSION
)
DCTSIZE
);
/* If we don't have a full iMCU row buffered, return to application for
* more data. Note that preprocessor will always pad to fill the iMCU row
* at the bottom of the image.
*/
if
(
main
->
rowgroup_ctr
!=
DCTSIZE
)
return
;
/* Send the completed row to the compressor */
if
(
!
(
*
cinfo
->
coef
->
compress_data
)
(
cinfo
,
main
->
buffer
))
{
/* If compressor did not consume the whole row, then we must need to
* suspend processing and return to the application. In this situation
* we pretend we didn't yet consume the last input row; otherwise, if
* it happened to be the last row of the image, the application would
* think we were done.
*/
if
(
!
main
->
suspended
)
{
(
*
in_row_ctr
)
--
;
main
->
suspended
=
TRUE
;
}
return
;
}
/* We did finish the row. Undo our little suspension hack if a previous
* call suspended; then mark the main buffer empty.
*/
if
(
main
->
suspended
)
{
(
*
in_row_ctr
)
++
;
main
->
suspended
=
FALSE
;
}
main
->
rowgroup_ctr
=
0
;
main
->
cur_iMCU_row
++
;
}
}
#ifdef FULL_MAIN_BUFFER_SUPPORTED
/*
* Process some data.
* This routine handles all of the modes that use a full-size buffer.
*/
METHODDEF
(
void
)
process_data_buffer_main
(
j_compress_ptr
cinfo
,
JSAMPARRAY
input_buf
,
JDIMENSION
*
in_row_ctr
,
JDIMENSION
in_rows_avail
)
{
my_main_ptr
main
=
(
my_main_ptr
)
cinfo
->
main
;
int
ci
;
jpeg_component_info
*
compptr
;
int
writing
=
(
main
->
pass_mode
!=
JBUF_CRANK_DEST
);
while
(
main
->
cur_iMCU_row
<
cinfo
->
total_iMCU_rows
)
{
/* Realign the virtual buffers if at the start of an iMCU row. */
if
(
main
->
rowgroup_ctr
==
0
)
{
for
(
ci
=
0
,
compptr
=
cinfo
->
comp_info
;
ci
<
cinfo
->
num_components
;
ci
++
,
compptr
++
)
{
main
->
buffer
[
ci
]
=
(
*
cinfo
->
mem
->
access_virt_sarray
)
((
j_common_ptr
)
cinfo
,
main
->
whole_image
[
ci
],
main
->
cur_iMCU_row
*
(
compptr
->
v_samp_factor
*
DCTSIZE
),
(
JDIMENSION
)
(
compptr
->
v_samp_factor
*
DCTSIZE
),
writing
);
}
/* In a read pass, pretend we just read some source data. */
if
(
!
writing
)
{
*
in_row_ctr
+=
cinfo
->
max_v_samp_factor
*
DCTSIZE
;
main
->
rowgroup_ctr
=
DCTSIZE
;
}
}
/* If a write pass, read input data until the current iMCU row is full. */
/* Note: preprocessor will pad if necessary to fill the last iMCU row. */
if
(
writing
)
{
(
*
cinfo
->
prep
->
pre_process_data
)
(
cinfo
,
input_buf
,
in_row_ctr
,
in_rows_avail
,
main
->
buffer
,
&
main
->
rowgroup_ctr
,
(
JDIMENSION
)
DCTSIZE
);
/* Return to application if we need more data to fill the iMCU row. */
if
(
main
->
rowgroup_ctr
<
DCTSIZE
)
return
;
}
/* Emit data, unless this is a sink-only pass. */
if
(
main
->
pass_mode
!=
JBUF_SAVE_SOURCE
)
{
if
(
!
(
*
cinfo
->
coef
->
compress_data
)
(
cinfo
,
main
->
buffer
))
{
/* If compressor did not consume the whole row, then we must need to
* suspend processing and return to the application. In this situation
* we pretend we didn't yet consume the last input row; otherwise, if
* it happened to be the last row of the image, the application would
* think we were done.
*/
if
(
!
main
->
suspended
)
{
(
*
in_row_ctr
)
--
;
main
->
suspended
=
TRUE
;
}
return
;
}
/* We did finish the row. Undo our little suspension hack if a previous
* call suspended; then mark the main buffer empty.
*/
if
(
main
->
suspended
)
{
(
*
in_row_ctr
)
++
;
main
->
suspended
=
FALSE
;
}
}
/* If get here, we are done with this iMCU row. Mark buffer empty. */
main
->
rowgroup_ctr
=
0
;
main
->
cur_iMCU_row
++
;
}
}
#endif
/* FULL_MAIN_BUFFER_SUPPORTED */
/*
* Initialize main buffer controller.
*/
GLOBAL
(
void
)
jinit_c_main_controller
(
j_compress_ptr
cinfo
,
int
need_full_buffer
)
{
my_main_ptr
main
;
int
ci
;
jpeg_component_info
*
compptr
;
main
=
(
my_main_ptr
)
(
*
cinfo
->
mem
->
alloc_small
)
((
j_common_ptr
)
cinfo
,
JPOOL_IMAGE
,
SIZEOF
(
my_main_controller
));
cinfo
->
main
=
(
struct
jpeg_c_main_controller
*
)
main
;
main
->
pub
.
start_pass
=
start_pass_main
;
/* We don't need to create a buffer in raw-data mode. */
if
(
cinfo
->
raw_data_in
)
return
;
/* Create the buffer. It holds downsampled data, so each component
* may be of a different size.
*/
if
(
need_full_buffer
)
{
#ifdef FULL_MAIN_BUFFER_SUPPORTED
/* Allocate a full-image virtual array for each component */
/* Note we pad the bottom to a multiple of the iMCU height */
for
(
ci
=
0
,
compptr
=
cinfo
->
comp_info
;
ci
<
cinfo
->
num_components
;
ci
++
,
compptr
++
)
{
main
->
whole_image
[
ci
]
=
(
*
cinfo
->
mem
->
request_virt_sarray
)
((
j_common_ptr
)
cinfo
,
JPOOL_IMAGE
,
FALSE
,
compptr
->
width_in_blocks
*
DCTSIZE
,
(
JDIMENSION
)
jround_up
((
long
)
compptr
->
height_in_blocks
,
(
long
)
compptr
->
v_samp_factor
)
*
DCTSIZE
,
(
JDIMENSION
)
(
compptr
->
v_samp_factor
*
DCTSIZE
));
}
#else
ERREXIT
(
cinfo
,
JERR_BAD_BUFFER_MODE
);
#endif
}
else
{
#ifdef FULL_MAIN_BUFFER_SUPPORTED
main
->
whole_image
[
0
]
=
NULL
;
/* flag for no virtual arrays */
#endif
/* Allocate a strip buffer for each component */
for
(
ci
=
0
,
compptr
=
cinfo
->
comp_info
;
ci
<
cinfo
->
num_components
;
ci
++
,
compptr
++
)
{
main
->
buffer
[
ci
]
=
(
*
cinfo
->
mem
->
alloc_sarray
)
((
j_common_ptr
)
cinfo
,
JPOOL_IMAGE
,
compptr
->
width_in_blocks
*
DCTSIZE
,
(
JDIMENSION
)
(
compptr
->
v_samp_factor
*
DCTSIZE
));
}
}
}
dlib/external/libjpeg/jcmarker.cpp
0 → 100644
View file @
747088ea
/*
* jcmarker.c
*
* Copyright (C) 1991-1998, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains routines to write JPEG datastream markers.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
typedef
enum
{
/* JPEG marker codes */
M_SOF0
=
0xc0
,
M_SOF1
=
0xc1
,
M_SOF2
=
0xc2
,
M_SOF3
=
0xc3
,
M_SOF5
=
0xc5
,
M_SOF6
=
0xc6
,
M_SOF7
=
0xc7
,
M_JPG
=
0xc8
,
M_SOF9
=
0xc9
,
M_SOF10
=
0xca
,
M_SOF11
=
0xcb
,
M_SOF13
=
0xcd
,
M_SOF14
=
0xce
,
M_SOF15
=
0xcf
,
M_DHT
=
0xc4
,
M_DAC
=
0xcc
,
M_RST0
=
0xd0
,
M_RST1
=
0xd1
,
M_RST2
=
0xd2
,
M_RST3
=
0xd3
,
M_RST4
=
0xd4
,
M_RST5
=
0xd5
,
M_RST6
=
0xd6
,
M_RST7
=
0xd7
,
M_SOI
=
0xd8
,
M_EOI
=
0xd9
,
M_SOS
=
0xda
,
M_DQT
=
0xdb
,
M_DNL
=
0xdc
,
M_DRI
=
0xdd
,
M_DHP
=
0xde
,
M_EXP
=
0xdf
,
M_APP0
=
0xe0
,
M_APP1
=
0xe1
,
M_APP2
=
0xe2
,
M_APP3
=
0xe3
,
M_APP4
=
0xe4
,
M_APP5
=
0xe5
,
M_APP6
=
0xe6
,
M_APP7
=
0xe7
,
M_APP8
=
0xe8
,
M_APP9
=
0xe9
,
M_APP10
=
0xea
,
M_APP11
=
0xeb
,
M_APP12
=
0xec
,
M_APP13
=
0xed
,
M_APP14
=
0xee
,
M_APP15
=
0xef
,
M_JPG0
=
0xf0
,
M_JPG13
=
0xfd
,
M_COM
=
0xfe
,
M_TEM
=
0x01
,
M_ERROR
=
0x100
}
JPEG_MARKER
;
/* Private state */
typedef
struct
{
struct
jpeg_marker_writer
pub
;
/* public fields */
unsigned
int
last_restart_interval
;
/* last DRI value emitted; 0 after SOI */
}
my_marker_writer
;
typedef
my_marker_writer
*
my_marker_ptr
;
/*
* Basic output routines.
*
* Note that we do not support suspension while writing a marker.
* Therefore, an application using suspension must ensure that there is
* enough buffer space for the initial markers (typ. 600-700 bytes) before
* calling jpeg_start_compress, and enough space to write the trailing EOI
* (a few bytes) before calling jpeg_finish_compress. Multipass compression
* modes are not supported at all with suspension, so those two are the only
* points where markers will be written.
*/
LOCAL
(
void
)
emit_byte
(
j_compress_ptr
cinfo
,
int
val
)
/* Emit a byte */
{
struct
jpeg_destination_mgr
*
dest
=
cinfo
->
dest
;
*
(
dest
->
next_output_byte
)
++
=
(
JOCTET
)
val
;
if
(
--
dest
->
free_in_buffer
==
0
)
{
if
(
!
(
*
dest
->
empty_output_buffer
)
(
cinfo
))
ERREXIT
(
cinfo
,
JERR_CANT_SUSPEND
);
}
}
LOCAL
(
void
)
emit_marker
(
j_compress_ptr
cinfo
,
JPEG_MARKER
mark
)
/* Emit a marker code */
{
emit_byte
(
cinfo
,
0xFF
);
emit_byte
(
cinfo
,
(
int
)
mark
);
}
LOCAL
(
void
)
emit_2bytes
(
j_compress_ptr
cinfo
,
int
value
)
/* Emit a 2-byte integer; these are always MSB first in JPEG files */
{
emit_byte
(
cinfo
,
(
value
>>
8
)
&
0xFF
);
emit_byte
(
cinfo
,
value
&
0xFF
);
}
/*
* Routines to write specific marker types.
*/
LOCAL
(
int
)
emit_dqt
(
j_compress_ptr
cinfo
,
int
index
)
/* Emit a DQT marker */
/* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */
{
JQUANT_TBL
*
qtbl
=
cinfo
->
quant_tbl_ptrs
[
index
];
int
prec
;
int
i
;
if
(
qtbl
==
NULL
)
ERREXIT1
(
cinfo
,
JERR_NO_QUANT_TABLE
,
index
);
prec
=
0
;
for
(
i
=
0
;
i
<
DCTSIZE2
;
i
++
)
{
if
(
qtbl
->
quantval
[
i
]
>
255
)
prec
=
1
;
}
if
(
!
qtbl
->
sent_table
)
{
emit_marker
(
cinfo
,
M_DQT
);
emit_2bytes
(
cinfo
,
prec
?
DCTSIZE2
*
2
+
1
+
2
:
DCTSIZE2
+
1
+
2
);
emit_byte
(
cinfo
,
index
+
(
prec
<<
4
));
for
(
i
=
0
;
i
<
DCTSIZE2
;
i
++
)
{
/* The table entries must be emitted in zigzag order. */
unsigned
int
qval
=
qtbl
->
quantval
[
jpeg_natural_order
[
i
]];
if
(
prec
)
emit_byte
(
cinfo
,
(
int
)
(
qval
>>
8
));
emit_byte
(
cinfo
,
(
int
)
(
qval
&
0xFF
));
}
qtbl
->
sent_table
=
TRUE
;
}
return
prec
;
}
LOCAL
(
void
)
emit_dht
(
j_compress_ptr
cinfo
,
int
index
,
int
is_ac
)
/* Emit a DHT marker */
{
JHUFF_TBL
*
htbl
;
int
length
,
i
;
if
(
is_ac
)
{
htbl
=
cinfo
->
ac_huff_tbl_ptrs
[
index
];
index
+=
0x10
;
/* output index has AC bit set */
}
else
{
htbl
=
cinfo
->
dc_huff_tbl_ptrs
[
index
];
}
if
(
htbl
==
NULL
)
ERREXIT1
(
cinfo
,
JERR_NO_HUFF_TABLE
,
index
);
if
(
!
htbl
->
sent_table
)
{
emit_marker
(
cinfo
,
M_DHT
);
length
=
0
;
for
(
i
=
1
;
i
<=
16
;
i
++
)
length
+=
htbl
->
bits
[
i
];
emit_2bytes
(
cinfo
,
length
+
2
+
1
+
16
);
emit_byte
(
cinfo
,
index
);
for
(
i
=
1
;
i
<=
16
;
i
++
)
emit_byte
(
cinfo
,
htbl
->
bits
[
i
]);
for
(
i
=
0
;
i
<
length
;
i
++
)
emit_byte
(
cinfo
,
htbl
->
huffval
[
i
]);
htbl
->
sent_table
=
TRUE
;
}
}
LOCAL
(
void
)
emit_dac
(
j_compress_ptr
cinfo
)
/* Emit a DAC marker */
/* Since the useful info is so small, we want to emit all the tables in */
/* one DAC marker. Therefore this routine does its own scan of the table. */
{
#ifdef C_ARITH_CODING_SUPPORTED
char
dc_in_use
[
NUM_ARITH_TBLS
];
char
ac_in_use
[
NUM_ARITH_TBLS
];
int
length
,
i
;
jpeg_component_info
*
compptr
;
for
(
i
=
0
;
i
<
NUM_ARITH_TBLS
;
i
++
)
dc_in_use
[
i
]
=
ac_in_use
[
i
]
=
0
;
for
(
i
=
0
;
i
<
cinfo
->
comps_in_scan
;
i
++
)
{
compptr
=
cinfo
->
cur_comp_info
[
i
];
dc_in_use
[
compptr
->
dc_tbl_no
]
=
1
;
ac_in_use
[
compptr
->
ac_tbl_no
]
=
1
;
}
length
=
0
;
for
(
i
=
0
;
i
<
NUM_ARITH_TBLS
;
i
++
)
length
+=
dc_in_use
[
i
]
+
ac_in_use
[
i
];
emit_marker
(
cinfo
,
M_DAC
);
emit_2bytes
(
cinfo
,
length
*
2
+
2
);
for
(
i
=
0
;
i
<
NUM_ARITH_TBLS
;
i
++
)
{
if
(
dc_in_use
[
i
])
{
emit_byte
(
cinfo
,
i
);
emit_byte
(
cinfo
,
cinfo
->
arith_dc_L
[
i
]
+
(
cinfo
->
arith_dc_U
[
i
]
<<
4
));
}
if
(
ac_in_use
[
i
])
{
emit_byte
(
cinfo
,
i
+
0x10
);
emit_byte
(
cinfo
,
cinfo
->
arith_ac_K
[
i
]);
}
}
#endif
/* C_ARITH_CODING_SUPPORTED */
}
LOCAL
(
void
)
emit_dri
(
j_compress_ptr
cinfo
)
/* Emit a DRI marker */
{
emit_marker
(
cinfo
,
M_DRI
);
emit_2bytes
(
cinfo
,
4
);
/* fixed length */
emit_2bytes
(
cinfo
,
(
int
)
cinfo
->
restart_interval
);
}
LOCAL
(
void
)
emit_sof
(
j_compress_ptr
cinfo
,
JPEG_MARKER
code
)
/* Emit a SOF marker */
{
int
ci
;
jpeg_component_info
*
compptr
;
emit_marker
(
cinfo
,
code
);
emit_2bytes
(
cinfo
,
3
*
cinfo
->
num_components
+
2
+
5
+
1
);
/* length */
/* Make sure image isn't bigger than SOF field can handle */
if
((
long
)
cinfo
->
image_height
>
65535L
||
(
long
)
cinfo
->
image_width
>
65535L
)
ERREXIT1
(
cinfo
,
JERR_IMAGE_TOO_BIG
,
(
unsigned
int
)
65535
);
emit_byte
(
cinfo
,
cinfo
->
data_precision
);
emit_2bytes
(
cinfo
,
(
int
)
cinfo
->
image_height
);
emit_2bytes
(
cinfo
,
(
int
)
cinfo
->
image_width
);
emit_byte
(
cinfo
,
cinfo
->
num_components
);
for
(
ci
=
0
,
compptr
=
cinfo
->
comp_info
;
ci
<
cinfo
->
num_components
;
ci
++
,
compptr
++
)
{
emit_byte
(
cinfo
,
compptr
->
component_id
);
emit_byte
(
cinfo
,
(
compptr
->
h_samp_factor
<<
4
)
+
compptr
->
v_samp_factor
);
emit_byte
(
cinfo
,
compptr
->
quant_tbl_no
);
}
}
LOCAL
(
void
)
emit_sos
(
j_compress_ptr
cinfo
)
/* Emit a SOS marker */
{
int
i
,
td
,
ta
;
jpeg_component_info
*
compptr
;
emit_marker
(
cinfo
,
M_SOS
);
emit_2bytes
(
cinfo
,
2
*
cinfo
->
comps_in_scan
+
2
+
1
+
3
);
/* length */
emit_byte
(
cinfo
,
cinfo
->
comps_in_scan
);
for
(
i
=
0
;
i
<
cinfo
->
comps_in_scan
;
i
++
)
{
compptr
=
cinfo
->
cur_comp_info
[
i
];
emit_byte
(
cinfo
,
compptr
->
component_id
);
td
=
compptr
->
dc_tbl_no
;
ta
=
compptr
->
ac_tbl_no
;
if
(
cinfo
->
progressive_mode
)
{
/* Progressive mode: only DC or only AC tables are used in one scan;
* furthermore, Huffman coding of DC refinement uses no table at all.
* We emit 0 for unused field(s); this is recommended by the P&M text
* but does not seem to be specified in the standard.
*/
if
(
cinfo
->
Ss
==
0
)
{
ta
=
0
;
/* DC scan */
if
(
cinfo
->
Ah
!=
0
&&
!
cinfo
->
arith_code
)
td
=
0
;
/* no DC table either */
}
else
{
td
=
0
;
/* AC scan */
}
}
emit_byte
(
cinfo
,
(
td
<<
4
)
+
ta
);
}
emit_byte
(
cinfo
,
cinfo
->
Ss
);
emit_byte
(
cinfo
,
cinfo
->
Se
);
emit_byte
(
cinfo
,
(
cinfo
->
Ah
<<
4
)
+
cinfo
->
Al
);
}
LOCAL
(
void
)
emit_jfif_app0
(
j_compress_ptr
cinfo
)
/* Emit a JFIF-compliant APP0 marker */
{
/*
* Length of APP0 block (2 bytes)
* Block ID (4 bytes - ASCII "JFIF")
* Zero byte (1 byte to terminate the ID string)
* Version Major, Minor (2 bytes - major first)
* Units (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm)
* Xdpu (2 bytes - dots per unit horizontal)
* Ydpu (2 bytes - dots per unit vertical)
* Thumbnail X size (1 byte)
* Thumbnail Y size (1 byte)
*/
emit_marker
(
cinfo
,
M_APP0
);
emit_2bytes
(
cinfo
,
2
+
4
+
1
+
2
+
1
+
2
+
2
+
1
+
1
);
/* length */
emit_byte
(
cinfo
,
0x4A
);
/* Identifier: ASCII "JFIF" */
emit_byte
(
cinfo
,
0x46
);
emit_byte
(
cinfo
,
0x49
);
emit_byte
(
cinfo
,
0x46
);
emit_byte
(
cinfo
,
0
);
emit_byte
(
cinfo
,
cinfo
->
JFIF_major_version
);
/* Version fields */
emit_byte
(
cinfo
,
cinfo
->
JFIF_minor_version
);
emit_byte
(
cinfo
,
cinfo
->
density_unit
);
/* Pixel size information */
emit_2bytes
(
cinfo
,
(
int
)
cinfo
->
X_density
);
emit_2bytes
(
cinfo
,
(
int
)
cinfo
->
Y_density
);
emit_byte
(
cinfo
,
0
);
/* No thumbnail image */
emit_byte
(
cinfo
,
0
);
}
LOCAL
(
void
)
emit_adobe_app14
(
j_compress_ptr
cinfo
)
/* Emit an Adobe APP14 marker */
{
/*
* Length of APP14 block (2 bytes)
* Block ID (5 bytes - ASCII "Adobe")
* Version Number (2 bytes - currently 100)
* Flags0 (2 bytes - currently 0)
* Flags1 (2 bytes - currently 0)
* Color transform (1 byte)
*
* Although Adobe TN 5116 mentions Version = 101, all the Adobe files
* now in circulation seem to use Version = 100, so that's what we write.
*
* We write the color transform byte as 1 if the JPEG color space is
* YCbCr, 2 if it's YCCK, 0 otherwise. Adobe's definition has to do with
* whether the encoder performed a transformation, which is pretty useless.
*/
emit_marker
(
cinfo
,
M_APP14
);
emit_2bytes
(
cinfo
,
2
+
5
+
2
+
2
+
2
+
1
);
/* length */
emit_byte
(
cinfo
,
0x41
);
/* Identifier: ASCII "Adobe" */
emit_byte
(
cinfo
,
0x64
);
emit_byte
(
cinfo
,
0x6F
);
emit_byte
(
cinfo
,
0x62
);
emit_byte
(
cinfo
,
0x65
);
emit_2bytes
(
cinfo
,
100
);
/* Version */
emit_2bytes
(
cinfo
,
0
);
/* Flags0 */
emit_2bytes
(
cinfo
,
0
);
/* Flags1 */
switch
(
cinfo
->
jpeg_color_space
)
{
case
JCS_YCbCr
:
emit_byte
(
cinfo
,
1
);
/* Color transform = 1 */
break
;
case
JCS_YCCK
:
emit_byte
(
cinfo
,
2
);
/* Color transform = 2 */
break
;
default
:
emit_byte
(
cinfo
,
0
);
/* Color transform = 0 */
break
;
}
}
/*
* These routines allow writing an arbitrary marker with parameters.
* The only intended use is to emit COM or APPn markers after calling
* write_file_header and before calling write_frame_header.
* Other uses are not guaranteed to produce desirable results.
* Counting the parameter bytes properly is the caller's responsibility.
*/
METHODDEF
(
void
)
write_marker_header
(
j_compress_ptr
cinfo
,
int
marker
,
unsigned
int
datalen
)
/* Emit an arbitrary marker header */
{
if
(
datalen
>
(
unsigned
int
)
65533
)
/* safety check */
ERREXIT
(
cinfo
,
JERR_BAD_LENGTH
);
emit_marker
(
cinfo
,
(
JPEG_MARKER
)
marker
);
emit_2bytes
(
cinfo
,
(
int
)
(
datalen
+
2
));
/* total length */
}
METHODDEF
(
void
)
write_marker_byte
(
j_compress_ptr
cinfo
,
int
val
)
/* Emit one byte of marker parameters following write_marker_header */
{
emit_byte
(
cinfo
,
val
);
}
/*
* Write datastream header.
* This consists of an SOI and optional APPn markers.
* We recommend use of the JFIF marker, but not the Adobe marker,
* when using YCbCr or grayscale data. The JFIF marker should NOT
* be used for any other JPEG colorspace. The Adobe marker is helpful
* to distinguish RGB, CMYK, and YCCK colorspaces.
* Note that an application can write additional header markers after
* jpeg_start_compress returns.
*/
METHODDEF
(
void
)
write_file_header
(
j_compress_ptr
cinfo
)
{
my_marker_ptr
marker
=
(
my_marker_ptr
)
cinfo
->
marker
;
emit_marker
(
cinfo
,
M_SOI
);
/* first the SOI */
/* SOI is defined to reset restart interval to 0 */
marker
->
last_restart_interval
=
0
;
if
(
cinfo
->
write_JFIF_header
)
/* next an optional JFIF APP0 */
emit_jfif_app0
(
cinfo
);
if
(
cinfo
->
write_Adobe_marker
)
/* next an optional Adobe APP14 */
emit_adobe_app14
(
cinfo
);
}
/*
* Write frame header.
* This consists of DQT and SOFn markers.
* Note that we do not emit the SOF until we have emitted the DQT(s).
* This avoids compatibility problems with incorrect implementations that
* try to error-check the quant table numbers as soon as they see the SOF.
*/
METHODDEF
(
void
)
write_frame_header
(
j_compress_ptr
cinfo
)
{
int
ci
,
prec
;
int
is_baseline
;
jpeg_component_info
*
compptr
;
/* Emit DQT for each quantization table.
* Note that emit_dqt() suppresses any duplicate tables.
*/
prec
=
0
;
for
(
ci
=
0
,
compptr
=
cinfo
->
comp_info
;
ci
<
cinfo
->
num_components
;
ci
++
,
compptr
++
)
{
prec
+=
emit_dqt
(
cinfo
,
compptr
->
quant_tbl_no
);
}
/* now prec is nonzero iff there are any 16-bit quant tables. */
/* Check for a non-baseline specification.
* Note we assume that Huffman table numbers won't be changed later.
*/
if
(
cinfo
->
arith_code
||
cinfo
->
progressive_mode
||
cinfo
->
data_precision
!=
8
)
{
is_baseline
=
FALSE
;
}
else
{
is_baseline
=
TRUE
;
for
(
ci
=
0
,
compptr
=
cinfo
->
comp_info
;
ci
<
cinfo
->
num_components
;
ci
++
,
compptr
++
)
{
if
(
compptr
->
dc_tbl_no
>
1
||
compptr
->
ac_tbl_no
>
1
)
is_baseline
=
FALSE
;
}
if
(
prec
&&
is_baseline
)
{
is_baseline
=
FALSE
;
/* If it's baseline except for quantizer size, warn the user */
TRACEMS
(
cinfo
,
0
,
JTRC_16BIT_TABLES
);
}
}
/* Emit the proper SOF marker */
if
(
cinfo
->
arith_code
)
{
emit_sof
(
cinfo
,
M_SOF9
);
/* SOF code for arithmetic coding */
}
else
{
if
(
cinfo
->
progressive_mode
)
emit_sof
(
cinfo
,
M_SOF2
);
/* SOF code for progressive Huffman */
else
if
(
is_baseline
)
emit_sof
(
cinfo
,
M_SOF0
);
/* SOF code for baseline implementation */
else
emit_sof
(
cinfo
,
M_SOF1
);
/* SOF code for non-baseline Huffman file */
}
}
/*
* Write scan header.
* This consists of DHT or DAC markers, optional DRI, and SOS.
* Compressed data will be written following the SOS.
*/
METHODDEF
(
void
)
write_scan_header
(
j_compress_ptr
cinfo
)
{
my_marker_ptr
marker
=
(
my_marker_ptr
)
cinfo
->
marker
;
int
i
;
jpeg_component_info
*
compptr
;
if
(
cinfo
->
arith_code
)
{
/* Emit arith conditioning info. We may have some duplication
* if the file has multiple scans, but it's so small it's hardly
* worth worrying about.
*/
emit_dac
(
cinfo
);
}
else
{
/* Emit Huffman tables.
* Note that emit_dht() suppresses any duplicate tables.
*/
for
(
i
=
0
;
i
<
cinfo
->
comps_in_scan
;
i
++
)
{
compptr
=
cinfo
->
cur_comp_info
[
i
];
if
(
cinfo
->
progressive_mode
)
{
/* Progressive mode: only DC or only AC tables are used in one scan */
if
(
cinfo
->
Ss
==
0
)
{
if
(
cinfo
->
Ah
==
0
)
/* DC needs no table for refinement scan */
emit_dht
(
cinfo
,
compptr
->
dc_tbl_no
,
FALSE
);
}
else
{
emit_dht
(
cinfo
,
compptr
->
ac_tbl_no
,
TRUE
);
}
}
else
{
/* Sequential mode: need both DC and AC tables */
emit_dht
(
cinfo
,
compptr
->
dc_tbl_no
,
FALSE
);
emit_dht
(
cinfo
,
compptr
->
ac_tbl_no
,
TRUE
);
}
}
}
/* Emit DRI if required --- note that DRI value could change for each scan.
* We avoid wasting space with unnecessary DRIs, however.
*/
if
(
cinfo
->
restart_interval
!=
marker
->
last_restart_interval
)
{
emit_dri
(
cinfo
);
marker
->
last_restart_interval
=
cinfo
->
restart_interval
;
}
emit_sos
(
cinfo
);
}
/*
* Write datastream trailer.
*/
METHODDEF
(
void
)
write_file_trailer
(
j_compress_ptr
cinfo
)
{
emit_marker
(
cinfo
,
M_EOI
);
}
/*
* Write an abbreviated table-specification datastream.
* This consists of SOI, DQT and DHT tables, and EOI.
* Any table that is defined and not marked sent_table = TRUE will be
* emitted. Note that all tables will be marked sent_table = TRUE at exit.
*/
METHODDEF
(
void
)
write_tables_only
(
j_compress_ptr
cinfo
)
{
int
i
;
emit_marker
(
cinfo
,
M_SOI
);
for
(
i
=
0
;
i
<
NUM_QUANT_TBLS
;
i
++
)
{
if
(
cinfo
->
quant_tbl_ptrs
[
i
]
!=
NULL
)
(
void
)
emit_dqt
(
cinfo
,
i
);
}
if
(
!
cinfo
->
arith_code
)
{
for
(
i
=
0
;
i
<
NUM_HUFF_TBLS
;
i
++
)
{
if
(
cinfo
->
dc_huff_tbl_ptrs
[
i
]
!=
NULL
)
emit_dht
(
cinfo
,
i
,
FALSE
);
if
(
cinfo
->
ac_huff_tbl_ptrs
[
i
]
!=
NULL
)
emit_dht
(
cinfo
,
i
,
TRUE
);
}
}
emit_marker
(
cinfo
,
M_EOI
);
}
/*
* Initialize the marker writer module.
*/
GLOBAL
(
void
)
jinit_marker_writer
(
j_compress_ptr
cinfo
)
{
my_marker_ptr
marker
;
/* Create the subobject */
marker
=
(
my_marker_ptr
)
(
*
cinfo
->
mem
->
alloc_small
)
((
j_common_ptr
)
cinfo
,
JPOOL_IMAGE
,
SIZEOF
(
my_marker_writer
));
cinfo
->
marker
=
(
struct
jpeg_marker_writer
*
)
marker
;
/* Initialize method pointers */
marker
->
pub
.
write_file_header
=
write_file_header
;
marker
->
pub
.
write_frame_header
=
write_frame_header
;
marker
->
pub
.
write_scan_header
=
write_scan_header
;
marker
->
pub
.
write_file_trailer
=
write_file_trailer
;
marker
->
pub
.
write_tables_only
=
write_tables_only
;
marker
->
pub
.
write_marker_header
=
write_marker_header
;
marker
->
pub
.
write_marker_byte
=
write_marker_byte
;
/* Initialize private state */
marker
->
last_restart_interval
=
0
;
}
dlib/external/libjpeg/jcmaster.cpp
0 → 100644
View file @
747088ea
/*
* jcmaster.c
*
* Copyright (C) 1991-1997, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains master control logic for the JPEG compressor.
* These routines are concerned with parameter validation, initial setup,
* and inter-pass control (determining the number of passes and the work
* to be done in each pass).
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/* Private state */
typedef
enum
{
main_pass
,
/* input data, also do first output step */
huff_opt_pass
,
/* Huffman code optimization pass */
output_pass
/* data output pass */
}
c_pass_type
;
typedef
struct
{
struct
jpeg_comp_master
pub
;
/* public fields */
c_pass_type
pass_type
;
/* the type of the current pass */
int
pass_number
;
/* # of passes completed */
int
total_passes
;
/* total # of passes needed */
int
scan_number
;
/* current index in scan_info[] */
}
my_comp_master
;
typedef
my_comp_master
*
my_master_ptr
;
/*
* Support routines that do various essential calculations.
*/
LOCAL
(
void
)
initial_setup
(
j_compress_ptr
cinfo
)
/* Do computations that are needed before master selection phase */
{
int
ci
;
jpeg_component_info
*
compptr
;
long
samplesperrow
;
JDIMENSION
jd_samplesperrow
;
/* Sanity check on image dimensions */
if
(
cinfo
->
image_height
<=
0
||
cinfo
->
image_width
<=
0
||
cinfo
->
num_components
<=
0
||
cinfo
->
input_components
<=
0
)
ERREXIT
(
cinfo
,
JERR_EMPTY_IMAGE
);
/* Make sure image isn't bigger than I can handle */
if
((
long
)
cinfo
->
image_height
>
(
long
)
JPEG_MAX_DIMENSION
||
(
long
)
cinfo
->
image_width
>
(
long
)
JPEG_MAX_DIMENSION
)
ERREXIT1
(
cinfo
,
JERR_IMAGE_TOO_BIG
,
(
unsigned
int
)
JPEG_MAX_DIMENSION
);
/* Width of an input scanline must be representable as JDIMENSION. */
samplesperrow
=
(
long
)
cinfo
->
image_width
*
(
long
)
cinfo
->
input_components
;
jd_samplesperrow
=
(
JDIMENSION
)
samplesperrow
;
if
((
long
)
jd_samplesperrow
!=
samplesperrow
)
ERREXIT
(
cinfo
,
JERR_WIDTH_OVERFLOW
);
/* For now, precision must match compiled-in value... */
if
(
cinfo
->
data_precision
!=
BITS_IN_JSAMPLE
)
ERREXIT1
(
cinfo
,
JERR_BAD_PRECISION
,
cinfo
->
data_precision
);
/* Check that number of components won't exceed internal array sizes */
if
(
cinfo
->
num_components
>
MAX_COMPONENTS
)
ERREXIT2
(
cinfo
,
JERR_COMPONENT_COUNT
,
cinfo
->
num_components
,
MAX_COMPONENTS
);
/* Compute maximum sampling factors; check factor validity */
cinfo
->
max_h_samp_factor
=
1
;
cinfo
->
max_v_samp_factor
=
1
;
for
(
ci
=
0
,
compptr
=
cinfo
->
comp_info
;
ci
<
cinfo
->
num_components
;
ci
++
,
compptr
++
)
{
if
(
compptr
->
h_samp_factor
<=
0
||
compptr
->
h_samp_factor
>
MAX_SAMP_FACTOR
||
compptr
->
v_samp_factor
<=
0
||
compptr
->
v_samp_factor
>
MAX_SAMP_FACTOR
)
ERREXIT
(
cinfo
,
JERR_BAD_SAMPLING
);
cinfo
->
max_h_samp_factor
=
MAX
(
cinfo
->
max_h_samp_factor
,
compptr
->
h_samp_factor
);
cinfo
->
max_v_samp_factor
=
MAX
(
cinfo
->
max_v_samp_factor
,
compptr
->
v_samp_factor
);
}
/* Compute dimensions of components */
for
(
ci
=
0
,
compptr
=
cinfo
->
comp_info
;
ci
<
cinfo
->
num_components
;
ci
++
,
compptr
++
)
{
/* Fill in the correct component_index value; don't rely on application */
compptr
->
component_index
=
ci
;
/* For compression, we never do DCT scaling. */
compptr
->
DCT_scaled_size
=
DCTSIZE
;
/* Size in DCT blocks */
compptr
->
width_in_blocks
=
(
JDIMENSION
)
jdiv_round_up
((
long
)
cinfo
->
image_width
*
(
long
)
compptr
->
h_samp_factor
,
(
long
)
(
cinfo
->
max_h_samp_factor
*
DCTSIZE
));
compptr
->
height_in_blocks
=
(
JDIMENSION
)
jdiv_round_up
((
long
)
cinfo
->
image_height
*
(
long
)
compptr
->
v_samp_factor
,
(
long
)
(
cinfo
->
max_v_samp_factor
*
DCTSIZE
));
/* Size in samples */
compptr
->
downsampled_width
=
(
JDIMENSION
)
jdiv_round_up
((
long
)
cinfo
->
image_width
*
(
long
)
compptr
->
h_samp_factor
,
(
long
)
cinfo
->
max_h_samp_factor
);
compptr
->
downsampled_height
=
(
JDIMENSION
)
jdiv_round_up
((
long
)
cinfo
->
image_height
*
(
long
)
compptr
->
v_samp_factor
,
(
long
)
cinfo
->
max_v_samp_factor
);
/* Mark component needed (this flag isn't actually used for compression) */
compptr
->
component_needed
=
TRUE
;
}
/* Compute number of fully interleaved MCU rows (number of times that
* main controller will call coefficient controller).
*/
cinfo
->
total_iMCU_rows
=
(
JDIMENSION
)
jdiv_round_up
((
long
)
cinfo
->
image_height
,
(
long
)
(
cinfo
->
max_v_samp_factor
*
DCTSIZE
));
}
#ifdef C_MULTISCAN_FILES_SUPPORTED
LOCAL
(
void
)
validate_script
(
j_compress_ptr
cinfo
)
/* Verify that the scan script in cinfo->scan_info[] is valid; also
* determine whether it uses progressive JPEG, and set cinfo->progressive_mode.
*/
{
const
jpeg_scan_info
*
scanptr
;
int
scanno
,
ncomps
,
ci
,
coefi
,
thisi
;
int
Ss
,
Se
,
Ah
,
Al
;
int
component_sent
[
MAX_COMPONENTS
];
#ifdef C_PROGRESSIVE_SUPPORTED
int
*
last_bitpos_ptr
;
int
last_bitpos
[
MAX_COMPONENTS
][
DCTSIZE2
];
/* -1 until that coefficient has been seen; then last Al for it */
#endif
if
(
cinfo
->
num_scans
<=
0
)
ERREXIT1
(
cinfo
,
JERR_BAD_SCAN_SCRIPT
,
0
);
/* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1;
* for progressive JPEG, no scan can have this.
*/
scanptr
=
cinfo
->
scan_info
;
if
(
scanptr
->
Ss
!=
0
||
scanptr
->
Se
!=
DCTSIZE2
-
1
)
{
#ifdef C_PROGRESSIVE_SUPPORTED
cinfo
->
progressive_mode
=
TRUE
;
last_bitpos_ptr
=
&
last_bitpos
[
0
][
0
];
for
(
ci
=
0
;
ci
<
cinfo
->
num_components
;
ci
++
)
for
(
coefi
=
0
;
coefi
<
DCTSIZE2
;
coefi
++
)
*
last_bitpos_ptr
++
=
-
1
;
#else
ERREXIT
(
cinfo
,
JERR_NOT_COMPILED
);
#endif
}
else
{
cinfo
->
progressive_mode
=
FALSE
;
for
(
ci
=
0
;
ci
<
cinfo
->
num_components
;
ci
++
)
component_sent
[
ci
]
=
FALSE
;
}
for
(
scanno
=
1
;
scanno
<=
cinfo
->
num_scans
;
scanptr
++
,
scanno
++
)
{
/* Validate component indexes */
ncomps
=
scanptr
->
comps_in_scan
;
if
(
ncomps
<=
0
||
ncomps
>
MAX_COMPS_IN_SCAN
)
ERREXIT2
(
cinfo
,
JERR_COMPONENT_COUNT
,
ncomps
,
MAX_COMPS_IN_SCAN
);
for
(
ci
=
0
;
ci
<
ncomps
;
ci
++
)
{
thisi
=
scanptr
->
component_index
[
ci
];
if
(
thisi
<
0
||
thisi
>=
cinfo
->
num_components
)
ERREXIT1
(
cinfo
,
JERR_BAD_SCAN_SCRIPT
,
scanno
);
/* Components must appear in SOF order within each scan */
if
(
ci
>
0
&&
thisi
<=
scanptr
->
component_index
[
ci
-
1
])
ERREXIT1
(
cinfo
,
JERR_BAD_SCAN_SCRIPT
,
scanno
);
}
/* Validate progression parameters */
Ss
=
scanptr
->
Ss
;
Se
=
scanptr
->
Se
;
Ah
=
scanptr
->
Ah
;
Al
=
scanptr
->
Al
;
if
(
cinfo
->
progressive_mode
)
{
#ifdef C_PROGRESSIVE_SUPPORTED
/* The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that
* seems wrong: the upper bound ought to depend on data precision.
* Perhaps they really meant 0..N+1 for N-bit precision.
* Here we allow 0..10 for 8-bit data; Al larger than 10 results in
* out-of-range reconstructed DC values during the first DC scan,
* which might cause problems for some decoders.
*/
#if BITS_IN_JSAMPLE == 8
#define MAX_AH_AL 10
#else
#define MAX_AH_AL 13
#endif
if
(
Ss
<
0
||
Ss
>=
DCTSIZE2
||
Se
<
Ss
||
Se
>=
DCTSIZE2
||
Ah
<
0
||
Ah
>
MAX_AH_AL
||
Al
<
0
||
Al
>
MAX_AH_AL
)
ERREXIT1
(
cinfo
,
JERR_BAD_PROG_SCRIPT
,
scanno
);
if
(
Ss
==
0
)
{
if
(
Se
!=
0
)
/* DC and AC together not OK */
ERREXIT1
(
cinfo
,
JERR_BAD_PROG_SCRIPT
,
scanno
);
}
else
{
if
(
ncomps
!=
1
)
/* AC scans must be for only one component */
ERREXIT1
(
cinfo
,
JERR_BAD_PROG_SCRIPT
,
scanno
);
}
for
(
ci
=
0
;
ci
<
ncomps
;
ci
++
)
{
last_bitpos_ptr
=
&
last_bitpos
[
scanptr
->
component_index
[
ci
]][
0
];
if
(
Ss
!=
0
&&
last_bitpos_ptr
[
0
]
<
0
)
/* AC without prior DC scan */
ERREXIT1
(
cinfo
,
JERR_BAD_PROG_SCRIPT
,
scanno
);
for
(
coefi
=
Ss
;
coefi
<=
Se
;
coefi
++
)
{
if
(
last_bitpos_ptr
[
coefi
]
<
0
)
{
/* first scan of this coefficient */
if
(
Ah
!=
0
)
ERREXIT1
(
cinfo
,
JERR_BAD_PROG_SCRIPT
,
scanno
);
}
else
{
/* not first scan */
if
(
Ah
!=
last_bitpos_ptr
[
coefi
]
||
Al
!=
Ah
-
1
)
ERREXIT1
(
cinfo
,
JERR_BAD_PROG_SCRIPT
,
scanno
);
}
last_bitpos_ptr
[
coefi
]
=
Al
;
}
}
#endif
}
else
{
/* For sequential JPEG, all progression parameters must be these: */
if
(
Ss
!=
0
||
Se
!=
DCTSIZE2
-
1
||
Ah
!=
0
||
Al
!=
0
)
ERREXIT1
(
cinfo
,
JERR_BAD_PROG_SCRIPT
,
scanno
);
/* Make sure components are not sent twice */
for
(
ci
=
0
;
ci
<
ncomps
;
ci
++
)
{
thisi
=
scanptr
->
component_index
[
ci
];
if
(
component_sent
[
thisi
])
ERREXIT1
(
cinfo
,
JERR_BAD_SCAN_SCRIPT
,
scanno
);
component_sent
[
thisi
]
=
TRUE
;
}
}
}
/* Now verify that everything got sent. */
if
(
cinfo
->
progressive_mode
)
{
#ifdef C_PROGRESSIVE_SUPPORTED
/* For progressive mode, we only check that at least some DC data
* got sent for each component; the spec does not require that all bits
* of all coefficients be transmitted. Would it be wiser to enforce
* transmission of all coefficient bits??
*/
for
(
ci
=
0
;
ci
<
cinfo
->
num_components
;
ci
++
)
{
if
(
last_bitpos
[
ci
][
0
]
<
0
)
ERREXIT
(
cinfo
,
JERR_MISSING_DATA
);
}
#endif
}
else
{
for
(
ci
=
0
;
ci
<
cinfo
->
num_components
;
ci
++
)
{
if
(
!
component_sent
[
ci
])
ERREXIT
(
cinfo
,
JERR_MISSING_DATA
);
}
}
}
#endif
/* C_MULTISCAN_FILES_SUPPORTED */
LOCAL
(
void
)
select_scan_parameters
(
j_compress_ptr
cinfo
)
/* Set up the scan parameters for the current scan */
{
int
ci
;
#ifdef C_MULTISCAN_FILES_SUPPORTED
if
(
cinfo
->
scan_info
!=
NULL
)
{
/* Prepare for current scan --- the script is already validated */
my_master_ptr
master
=
(
my_master_ptr
)
cinfo
->
master
;
const
jpeg_scan_info
*
scanptr
=
cinfo
->
scan_info
+
master
->
scan_number
;
cinfo
->
comps_in_scan
=
scanptr
->
comps_in_scan
;
for
(
ci
=
0
;
ci
<
scanptr
->
comps_in_scan
;
ci
++
)
{
cinfo
->
cur_comp_info
[
ci
]
=
&
cinfo
->
comp_info
[
scanptr
->
component_index
[
ci
]];
}
cinfo
->
Ss
=
scanptr
->
Ss
;
cinfo
->
Se
=
scanptr
->
Se
;
cinfo
->
Ah
=
scanptr
->
Ah
;
cinfo
->
Al
=
scanptr
->
Al
;
}
else
#endif
{
/* Prepare for single sequential-JPEG scan containing all components */
if
(
cinfo
->
num_components
>
MAX_COMPS_IN_SCAN
)
ERREXIT2
(
cinfo
,
JERR_COMPONENT_COUNT
,
cinfo
->
num_components
,
MAX_COMPS_IN_SCAN
);
cinfo
->
comps_in_scan
=
cinfo
->
num_components
;
for
(
ci
=
0
;
ci
<
cinfo
->
num_components
;
ci
++
)
{
cinfo
->
cur_comp_info
[
ci
]
=
&
cinfo
->
comp_info
[
ci
];
}
cinfo
->
Ss
=
0
;
cinfo
->
Se
=
DCTSIZE2
-
1
;
cinfo
->
Ah
=
0
;
cinfo
->
Al
=
0
;
}
}
LOCAL
(
void
)
per_scan_setup
(
j_compress_ptr
cinfo
)
/* Do computations that are needed before processing a JPEG scan */
/* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */
{
int
ci
,
mcublks
,
tmp
;
jpeg_component_info
*
compptr
;
if
(
cinfo
->
comps_in_scan
==
1
)
{
/* Noninterleaved (single-component) scan */
compptr
=
cinfo
->
cur_comp_info
[
0
];
/* Overall image size in MCUs */
cinfo
->
MCUs_per_row
=
compptr
->
width_in_blocks
;
cinfo
->
MCU_rows_in_scan
=
compptr
->
height_in_blocks
;
/* For noninterleaved scan, always one block per MCU */
compptr
->
MCU_width
=
1
;
compptr
->
MCU_height
=
1
;
compptr
->
MCU_blocks
=
1
;
compptr
->
MCU_sample_width
=
DCTSIZE
;
compptr
->
last_col_width
=
1
;
/* For noninterleaved scans, it is convenient to define last_row_height
* as the number of block rows present in the last iMCU row.
*/
tmp
=
(
int
)
(
compptr
->
height_in_blocks
%
compptr
->
v_samp_factor
);
if
(
tmp
==
0
)
tmp
=
compptr
->
v_samp_factor
;
compptr
->
last_row_height
=
tmp
;
/* Prepare array describing MCU composition */
cinfo
->
blocks_in_MCU
=
1
;
cinfo
->
MCU_membership
[
0
]
=
0
;
}
else
{
/* Interleaved (multi-component) scan */
if
(
cinfo
->
comps_in_scan
<=
0
||
cinfo
->
comps_in_scan
>
MAX_COMPS_IN_SCAN
)
ERREXIT2
(
cinfo
,
JERR_COMPONENT_COUNT
,
cinfo
->
comps_in_scan
,
MAX_COMPS_IN_SCAN
);
/* Overall image size in MCUs */
cinfo
->
MCUs_per_row
=
(
JDIMENSION
)
jdiv_round_up
((
long
)
cinfo
->
image_width
,
(
long
)
(
cinfo
->
max_h_samp_factor
*
DCTSIZE
));
cinfo
->
MCU_rows_in_scan
=
(
JDIMENSION
)
jdiv_round_up
((
long
)
cinfo
->
image_height
,
(
long
)
(
cinfo
->
max_v_samp_factor
*
DCTSIZE
));
cinfo
->
blocks_in_MCU
=
0
;
for
(
ci
=
0
;
ci
<
cinfo
->
comps_in_scan
;
ci
++
)
{
compptr
=
cinfo
->
cur_comp_info
[
ci
];
/* Sampling factors give # of blocks of component in each MCU */
compptr
->
MCU_width
=
compptr
->
h_samp_factor
;
compptr
->
MCU_height
=
compptr
->
v_samp_factor
;
compptr
->
MCU_blocks
=
compptr
->
MCU_width
*
compptr
->
MCU_height
;
compptr
->
MCU_sample_width
=
compptr
->
MCU_width
*
DCTSIZE
;
/* Figure number of non-dummy blocks in last MCU column & row */
tmp
=
(
int
)
(
compptr
->
width_in_blocks
%
compptr
->
MCU_width
);
if
(
tmp
==
0
)
tmp
=
compptr
->
MCU_width
;
compptr
->
last_col_width
=
tmp
;
tmp
=
(
int
)
(
compptr
->
height_in_blocks
%
compptr
->
MCU_height
);
if
(
tmp
==
0
)
tmp
=
compptr
->
MCU_height
;
compptr
->
last_row_height
=
tmp
;
/* Prepare array describing MCU composition */
mcublks
=
compptr
->
MCU_blocks
;
if
(
cinfo
->
blocks_in_MCU
+
mcublks
>
C_MAX_BLOCKS_IN_MCU
)
ERREXIT
(
cinfo
,
JERR_BAD_MCU_SIZE
);
while
(
mcublks
--
>
0
)
{
cinfo
->
MCU_membership
[
cinfo
->
blocks_in_MCU
++
]
=
ci
;
}
}
}
/* Convert restart specified in rows to actual MCU count. */
/* Note that count must fit in 16 bits, so we provide limiting. */
if
(
cinfo
->
restart_in_rows
>
0
)
{
long
nominal
=
(
long
)
cinfo
->
restart_in_rows
*
(
long
)
cinfo
->
MCUs_per_row
;
cinfo
->
restart_interval
=
(
unsigned
int
)
MIN
(
nominal
,
65535L
);
}
}
/*
* Per-pass setup.
* This is called at the beginning of each pass. We determine which modules
* will be active during this pass and give them appropriate start_pass calls.
* We also set is_last_pass to indicate whether any more passes will be
* required.
*/
METHODDEF
(
void
)
prepare_for_pass
(
j_compress_ptr
cinfo
)
{
my_master_ptr
master
=
(
my_master_ptr
)
cinfo
->
master
;
switch
(
master
->
pass_type
)
{
case
main_pass
:
/* Initial pass: will collect input data, and do either Huffman
* optimization or data output for the first scan.
*/
select_scan_parameters
(
cinfo
);
per_scan_setup
(
cinfo
);
if
(
!
cinfo
->
raw_data_in
)
{
(
*
cinfo
->
cconvert
->
start_pass
)
(
cinfo
);
(
*
cinfo
->
downsample
->
start_pass
)
(
cinfo
);
(
*
cinfo
->
prep
->
start_pass
)
(
cinfo
,
JBUF_PASS_THRU
);
}
(
*
cinfo
->
fdct
->
start_pass
)
(
cinfo
);
(
*
cinfo
->
entropy
->
start_pass
)
(
cinfo
,
cinfo
->
optimize_coding
);
(
*
cinfo
->
coef
->
start_pass
)
(
cinfo
,
(
master
->
total_passes
>
1
?
JBUF_SAVE_AND_PASS
:
JBUF_PASS_THRU
));
(
*
cinfo
->
main
->
start_pass
)
(
cinfo
,
JBUF_PASS_THRU
);
if
(
cinfo
->
optimize_coding
)
{
/* No immediate data output; postpone writing frame/scan headers */
master
->
pub
.
call_pass_startup
=
FALSE
;
}
else
{
/* Will write frame/scan headers at first jpeg_write_scanlines call */
master
->
pub
.
call_pass_startup
=
TRUE
;
}
break
;
#ifdef ENTROPY_OPT_SUPPORTED
case
huff_opt_pass
:
/* Do Huffman optimization for a scan after the first one. */
select_scan_parameters
(
cinfo
);
per_scan_setup
(
cinfo
);
if
(
cinfo
->
Ss
!=
0
||
cinfo
->
Ah
==
0
||
cinfo
->
arith_code
)
{
(
*
cinfo
->
entropy
->
start_pass
)
(
cinfo
,
TRUE
);
(
*
cinfo
->
coef
->
start_pass
)
(
cinfo
,
JBUF_CRANK_DEST
);
master
->
pub
.
call_pass_startup
=
FALSE
;
break
;
}
/* Special case: Huffman DC refinement scans need no Huffman table
* and therefore we can skip the optimization pass for them.
*/
master
->
pass_type
=
output_pass
;
master
->
pass_number
++
;
/*FALLTHROUGH*/
#endif
case
output_pass
:
/* Do a data-output pass. */
/* We need not repeat per-scan setup if prior optimization pass did it. */
if
(
!
cinfo
->
optimize_coding
)
{
select_scan_parameters
(
cinfo
);
per_scan_setup
(
cinfo
);
}
(
*
cinfo
->
entropy
->
start_pass
)
(
cinfo
,
FALSE
);
(
*
cinfo
->
coef
->
start_pass
)
(
cinfo
,
JBUF_CRANK_DEST
);
/* We emit frame/scan headers now */
if
(
master
->
scan_number
==
0
)
(
*
cinfo
->
marker
->
write_frame_header
)
(
cinfo
);
(
*
cinfo
->
marker
->
write_scan_header
)
(
cinfo
);
master
->
pub
.
call_pass_startup
=
FALSE
;
break
;
default
:
ERREXIT
(
cinfo
,
JERR_NOT_COMPILED
);
}
master
->
pub
.
is_last_pass
=
(
master
->
pass_number
==
master
->
total_passes
-
1
);
/* Set up progress monitor's pass info if present */
if
(
cinfo
->
progress
!=
NULL
)
{
cinfo
->
progress
->
completed_passes
=
master
->
pass_number
;
cinfo
->
progress
->
total_passes
=
master
->
total_passes
;
}
}
/*
* Special start-of-pass hook.
* This is called by jpeg_write_scanlines if call_pass_startup is TRUE.
* In single-pass processing, we need this hook because we don't want to
* write frame/scan headers during jpeg_start_compress; we want to let the
* application write COM markers etc. between jpeg_start_compress and the
* jpeg_write_scanlines loop.
* In multi-pass processing, this routine is not used.
*/
METHODDEF
(
void
)
pass_startup
(
j_compress_ptr
cinfo
)
{
cinfo
->
master
->
call_pass_startup
=
FALSE
;
/* reset flag so call only once */
(
*
cinfo
->
marker
->
write_frame_header
)
(
cinfo
);
(
*
cinfo
->
marker
->
write_scan_header
)
(
cinfo
);
}
/*
* Finish up at end of pass.
*/
METHODDEF
(
void
)
finish_pass_master
(
j_compress_ptr
cinfo
)
{
my_master_ptr
master
=
(
my_master_ptr
)
cinfo
->
master
;
/* The entropy coder always needs an end-of-pass call,
* either to analyze statistics or to flush its output buffer.
*/
(
*
cinfo
->
entropy
->
finish_pass
)
(
cinfo
);
/* Update state for next pass */
switch
(
master
->
pass_type
)
{
case
main_pass
:
/* next pass is either output of scan 0 (after optimization)
* or output of scan 1 (if no optimization).
*/
master
->
pass_type
=
output_pass
;
if
(
!
cinfo
->
optimize_coding
)
master
->
scan_number
++
;
break
;
case
huff_opt_pass
:
/* next pass is always output of current scan */
master
->
pass_type
=
output_pass
;
break
;
case
output_pass
:
/* next pass is either optimization or output of next scan */
if
(
cinfo
->
optimize_coding
)
master
->
pass_type
=
huff_opt_pass
;
master
->
scan_number
++
;
break
;
}
master
->
pass_number
++
;
}
/*
* Initialize master compression control.
*/
GLOBAL
(
void
)
jinit_c_master_control
(
j_compress_ptr
cinfo
,
int
transcode_only
)
{
my_master_ptr
master
;
master
=
(
my_master_ptr
)
(
*
cinfo
->
mem
->
alloc_small
)
((
j_common_ptr
)
cinfo
,
JPOOL_IMAGE
,
SIZEOF
(
my_comp_master
));
cinfo
->
master
=
(
struct
jpeg_comp_master
*
)
master
;
master
->
pub
.
prepare_for_pass
=
prepare_for_pass
;
master
->
pub
.
pass_startup
=
pass_startup
;
master
->
pub
.
finish_pass
=
finish_pass_master
;
master
->
pub
.
is_last_pass
=
FALSE
;
/* Validate parameters, determine derived values */
initial_setup
(
cinfo
);
if
(
cinfo
->
scan_info
!=
NULL
)
{
#ifdef C_MULTISCAN_FILES_SUPPORTED
validate_script
(
cinfo
);
#else
ERREXIT
(
cinfo
,
JERR_NOT_COMPILED
);
#endif
}
else
{
cinfo
->
progressive_mode
=
FALSE
;
cinfo
->
num_scans
=
1
;
}
if
(
cinfo
->
progressive_mode
)
/* TEMPORARY HACK ??? */
cinfo
->
optimize_coding
=
TRUE
;
/* assume default tables no good for progressive mode */
/* Initialize my private state */
if
(
transcode_only
)
{
/* no main pass in transcoding */
if
(
cinfo
->
optimize_coding
)
master
->
pass_type
=
huff_opt_pass
;
else
master
->
pass_type
=
output_pass
;
}
else
{
/* for normal compression, first pass is always this type: */
master
->
pass_type
=
main_pass
;
}
master
->
scan_number
=
0
;
master
->
pass_number
=
0
;
if
(
cinfo
->
optimize_coding
)
master
->
total_passes
=
cinfo
->
num_scans
*
2
;
else
master
->
total_passes
=
cinfo
->
num_scans
;
}
dlib/external/libjpeg/jcparam.cpp
0 → 100644
View file @
747088ea
/*
* jcparam.c
*
* Copyright (C) 1991-1998, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains optional default-setting code for the JPEG compressor.
* Applications do not have to use this file, but those that don't use it
* must know a lot more about the innards of the JPEG code.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/*
* Quantization table setup routines
*/
GLOBAL
(
void
)
jpeg_add_quant_table
(
j_compress_ptr
cinfo
,
int
which_tbl
,
const
unsigned
int
*
basic_table
,
int
scale_factor
,
int
force_baseline
)
/* Define a quantization table equal to the basic_table times
* a scale factor (given as a percentage).
* If force_baseline is TRUE, the computed quantization table entries
* are limited to 1..255 for JPEG baseline compatibility.
*/
{
JQUANT_TBL
**
qtblptr
;
int
i
;
long
temp
;
/* Safety check to ensure start_compress not called yet. */
if
(
cinfo
->
global_state
!=
CSTATE_START
)
ERREXIT1
(
cinfo
,
JERR_BAD_STATE
,
cinfo
->
global_state
);
if
(
which_tbl
<
0
||
which_tbl
>=
NUM_QUANT_TBLS
)
ERREXIT1
(
cinfo
,
JERR_DQT_INDEX
,
which_tbl
);
qtblptr
=
&
cinfo
->
quant_tbl_ptrs
[
which_tbl
];
if
(
*
qtblptr
==
NULL
)
*
qtblptr
=
jpeg_alloc_quant_table
((
j_common_ptr
)
cinfo
);
for
(
i
=
0
;
i
<
DCTSIZE2
;
i
++
)
{
temp
=
((
long
)
basic_table
[
i
]
*
scale_factor
+
50L
)
/
100L
;
/* limit the values to the valid range */
if
(
temp
<=
0L
)
temp
=
1L
;
if
(
temp
>
32767L
)
temp
=
32767L
;
/* max quantizer needed for 12 bits */
if
(
force_baseline
&&
temp
>
255L
)
temp
=
255L
;
/* limit to baseline range if requested */
(
*
qtblptr
)
->
quantval
[
i
]
=
(
unsigned
short
)
temp
;
}
/* Initialize sent_table FALSE so table will be written to JPEG file. */
(
*
qtblptr
)
->
sent_table
=
FALSE
;
}
GLOBAL
(
void
)
jpeg_set_linear_quality
(
j_compress_ptr
cinfo
,
int
scale_factor
,
int
force_baseline
)
/* Set or change the 'quality' (quantization) setting, using default tables
* and a straight percentage-scaling quality scale. In most cases it's better
* to use jpeg_set_quality (below); this entry point is provided for
* applications that insist on a linear percentage scaling.
*/
{
/* These are the sample quantization tables given in JPEG spec section K.1.
* The spec says that the values given produce "good" quality, and
* when divided by 2, "very good" quality.
*/
static
const
unsigned
int
std_luminance_quant_tbl
[
DCTSIZE2
]
=
{
16
,
11
,
10
,
16
,
24
,
40
,
51
,
61
,
12
,
12
,
14
,
19
,
26
,
58
,
60
,
55
,
14
,
13
,
16
,
24
,
40
,
57
,
69
,
56
,
14
,
17
,
22
,
29
,
51
,
87
,
80
,
62
,
18
,
22
,
37
,
56
,
68
,
109
,
103
,
77
,
24
,
35
,
55
,
64
,
81
,
104
,
113
,
92
,
49
,
64
,
78
,
87
,
103
,
121
,
120
,
101
,
72
,
92
,
95
,
98
,
112
,
100
,
103
,
99
};
static
const
unsigned
int
std_chrominance_quant_tbl
[
DCTSIZE2
]
=
{
17
,
18
,
24
,
47
,
99
,
99
,
99
,
99
,
18
,
21
,
26
,
66
,
99
,
99
,
99
,
99
,
24
,
26
,
56
,
99
,
99
,
99
,
99
,
99
,
47
,
66
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
,
99
};
/* Set up two quantization tables using the specified scaling */
jpeg_add_quant_table
(
cinfo
,
0
,
std_luminance_quant_tbl
,
scale_factor
,
force_baseline
);
jpeg_add_quant_table
(
cinfo
,
1
,
std_chrominance_quant_tbl
,
scale_factor
,
force_baseline
);
}
GLOBAL
(
int
)
jpeg_quality_scaling
(
int
quality
)
/* Convert a user-specified quality rating to a percentage scaling factor
* for an underlying quantization table, using our recommended scaling curve.
* The input 'quality' factor should be 0 (terrible) to 100 (very good).
*/
{
/* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */
if
(
quality
<=
0
)
quality
=
1
;
if
(
quality
>
100
)
quality
=
100
;
/* The basic table is used as-is (scaling 100) for a quality of 50.
* Qualities 50..100 are converted to scaling percentage 200 - 2*Q;
* note that at Q=100 the scaling is 0, which will cause jpeg_add_quant_table
* to make all the table entries 1 (hence, minimum quantization loss).
* Qualities 1..50 are converted to scaling percentage 5000/Q.
*/
if
(
quality
<
50
)
quality
=
5000
/
quality
;
else
quality
=
200
-
quality
*
2
;
return
quality
;
}
GLOBAL
(
void
)
jpeg_set_quality
(
j_compress_ptr
cinfo
,
int
quality
,
int
force_baseline
)
/* Set or change the 'quality' (quantization) setting, using default tables.
* This is the standard quality-adjusting entry point for typical user
* interfaces; only those who want detailed control over quantization tables
* would use the preceding three routines directly.
*/
{
/* Convert user 0-100 rating to percentage scaling */
quality
=
jpeg_quality_scaling
(
quality
);
/* Set up standard quality tables */
jpeg_set_linear_quality
(
cinfo
,
quality
,
force_baseline
);
}
/*
* Huffman table setup routines
*/
LOCAL
(
void
)
add_huff_table
(
j_compress_ptr
cinfo
,
JHUFF_TBL
**
htblptr
,
const
unsigned
char
*
bits
,
const
unsigned
char
*
val
)
/* Define a Huffman table */
{
int
nsymbols
,
len
;
if
(
*
htblptr
==
NULL
)
*
htblptr
=
jpeg_alloc_huff_table
((
j_common_ptr
)
cinfo
);
/* Copy the number-of-symbols-of-each-code-length counts */
MEMCOPY
((
*
htblptr
)
->
bits
,
bits
,
SIZEOF
((
*
htblptr
)
->
bits
));
/* Validate the counts. We do this here mainly so we can copy the right
* number of symbols from the val[] array, without risking marching off
* the end of memory. jchuff.c will do a more thorough test later.
*/
nsymbols
=
0
;
for
(
len
=
1
;
len
<=
16
;
len
++
)
nsymbols
+=
bits
[
len
];
if
(
nsymbols
<
1
||
nsymbols
>
256
)
ERREXIT
(
cinfo
,
JERR_BAD_HUFF_TABLE
);
MEMCOPY
((
*
htblptr
)
->
huffval
,
val
,
nsymbols
*
SIZEOF
(
unsigned
char
));
/* Initialize sent_table FALSE so table will be written to JPEG file. */
(
*
htblptr
)
->
sent_table
=
FALSE
;
}
LOCAL
(
void
)
std_huff_tables
(
j_compress_ptr
cinfo
)
/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
/* IMPORTANT: these are only valid for 8-bit data precision! */
{
static
const
unsigned
char
bits_dc_luminance
[
17
]
=
{
/* 0-base */
0
,
0
,
1
,
5
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
static
const
unsigned
char
val_dc_luminance
[]
=
{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
,
11
};
static
const
unsigned
char
bits_dc_chrominance
[
17
]
=
{
/* 0-base */
0
,
0
,
3
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
};
static
const
unsigned
char
val_dc_chrominance
[]
=
{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
,
11
};
static
const
unsigned
char
bits_ac_luminance
[
17
]
=
{
/* 0-base */
0
,
0
,
2
,
1
,
3
,
3
,
2
,
4
,
3
,
5
,
5
,
4
,
4
,
0
,
0
,
1
,
0x7d
};
static
const
unsigned
char
val_ac_luminance
[]
=
{
0x01
,
0x02
,
0x03
,
0x00
,
0x04
,
0x11
,
0x05
,
0x12
,
0x21
,
0x31
,
0x41
,
0x06
,
0x13
,
0x51
,
0x61
,
0x07
,
0x22
,
0x71
,
0x14
,
0x32
,
0x81
,
0x91
,
0xa1
,
0x08
,
0x23
,
0x42
,
0xb1
,
0xc1
,
0x15
,
0x52
,
0xd1
,
0xf0
,
0x24
,
0x33
,
0x62
,
0x72
,
0x82
,
0x09
,
0x0a
,
0x16
,
0x17
,
0x18
,
0x19
,
0x1a
,
0x25
,
0x26
,
0x27
,
0x28
,
0x29
,
0x2a
,
0x34
,
0x35
,
0x36
,
0x37
,
0x38
,
0x39
,
0x3a
,
0x43
,
0x44
,
0x45
,
0x46
,
0x47
,
0x48
,
0x49
,
0x4a
,
0x53
,
0x54
,
0x55
,
0x56
,
0x57
,
0x58
,
0x59
,
0x5a
,
0x63
,
0x64
,
0x65
,
0x66
,
0x67
,
0x68
,
0x69
,
0x6a
,
0x73
,
0x74
,
0x75
,
0x76
,
0x77
,
0x78
,
0x79
,
0x7a
,
0x83
,
0x84
,
0x85
,
0x86
,
0x87
,
0x88
,
0x89
,
0x8a
,
0x92
,
0x93
,
0x94
,
0x95
,
0x96
,
0x97
,
0x98
,
0x99
,
0x9a
,
0xa2
,
0xa3
,
0xa4
,
0xa5
,
0xa6
,
0xa7
,
0xa8
,
0xa9
,
0xaa
,
0xb2
,
0xb3
,
0xb4
,
0xb5
,
0xb6
,
0xb7
,
0xb8
,
0xb9
,
0xba
,
0xc2
,
0xc3
,
0xc4
,
0xc5
,
0xc6
,
0xc7
,
0xc8
,
0xc9
,
0xca
,
0xd2
,
0xd3
,
0xd4
,
0xd5
,
0xd6
,
0xd7
,
0xd8
,
0xd9
,
0xda
,
0xe1
,
0xe2
,
0xe3
,
0xe4
,
0xe5
,
0xe6
,
0xe7
,
0xe8
,
0xe9
,
0xea
,
0xf1
,
0xf2
,
0xf3
,
0xf4
,
0xf5
,
0xf6
,
0xf7
,
0xf8
,
0xf9
,
0xfa
};
static
const
unsigned
char
bits_ac_chrominance
[
17
]
=
{
/* 0-base */
0
,
0
,
2
,
1
,
2
,
4
,
4
,
3
,
4
,
7
,
5
,
4
,
4
,
0
,
1
,
2
,
0x77
};
static
const
unsigned
char
val_ac_chrominance
[]
=
{
0x00
,
0x01
,
0x02
,
0x03
,
0x11
,
0x04
,
0x05
,
0x21
,
0x31
,
0x06
,
0x12
,
0x41
,
0x51
,
0x07
,
0x61
,
0x71
,
0x13
,
0x22
,
0x32
,
0x81
,
0x08
,
0x14
,
0x42
,
0x91
,
0xa1
,
0xb1
,
0xc1
,
0x09
,
0x23
,
0x33
,
0x52
,
0xf0
,
0x15
,
0x62
,
0x72
,
0xd1
,
0x0a
,
0x16
,
0x24
,
0x34
,
0xe1
,
0x25
,
0xf1
,
0x17
,
0x18
,
0x19
,
0x1a
,
0x26
,
0x27
,
0x28
,
0x29
,
0x2a
,
0x35
,
0x36
,
0x37
,
0x38
,
0x39
,
0x3a
,
0x43
,
0x44
,
0x45
,
0x46
,
0x47
,
0x48
,
0x49
,
0x4a
,
0x53
,
0x54
,
0x55
,
0x56
,
0x57
,
0x58
,
0x59
,
0x5a
,
0x63
,
0x64
,
0x65
,
0x66
,
0x67
,
0x68
,
0x69
,
0x6a
,
0x73
,
0x74
,
0x75
,
0x76
,
0x77
,
0x78
,
0x79
,
0x7a
,
0x82
,
0x83
,
0x84
,
0x85
,
0x86
,
0x87
,
0x88
,
0x89
,
0x8a
,
0x92
,
0x93
,
0x94
,
0x95
,
0x96
,
0x97
,
0x98
,
0x99
,
0x9a
,
0xa2
,
0xa3
,
0xa4
,
0xa5
,
0xa6
,
0xa7
,
0xa8
,
0xa9
,
0xaa
,
0xb2
,
0xb3
,
0xb4
,
0xb5
,
0xb6
,
0xb7
,
0xb8
,
0xb9
,
0xba
,
0xc2
,
0xc3
,
0xc4
,
0xc5
,
0xc6
,
0xc7
,
0xc8
,
0xc9
,
0xca
,
0xd2
,
0xd3
,
0xd4
,
0xd5
,
0xd6
,
0xd7
,
0xd8
,
0xd9
,
0xda
,
0xe2
,
0xe3
,
0xe4
,
0xe5
,
0xe6
,
0xe7
,
0xe8
,
0xe9
,
0xea
,
0xf2
,
0xf3
,
0xf4
,
0xf5
,
0xf6
,
0xf7
,
0xf8
,
0xf9
,
0xfa
};
add_huff_table
(
cinfo
,
&
cinfo
->
dc_huff_tbl_ptrs
[
0
],
bits_dc_luminance
,
val_dc_luminance
);
add_huff_table
(
cinfo
,
&
cinfo
->
ac_huff_tbl_ptrs
[
0
],
bits_ac_luminance
,
val_ac_luminance
);
add_huff_table
(
cinfo
,
&
cinfo
->
dc_huff_tbl_ptrs
[
1
],
bits_dc_chrominance
,
val_dc_chrominance
);
add_huff_table
(
cinfo
,
&
cinfo
->
ac_huff_tbl_ptrs
[
1
],
bits_ac_chrominance
,
val_ac_chrominance
);
}
/*
* Default parameter setup for compression.
*
* Applications that don't choose to use this routine must do their
* own setup of all these parameters. Alternately, you can call this
* to establish defaults and then alter parameters selectively. This
* is the recommended approach since, if we add any new parameters,
* your code will still work (they'll be set to reasonable defaults).
*/
GLOBAL
(
void
)
jpeg_set_defaults
(
j_compress_ptr
cinfo
)
{
int
i
;
/* Safety check to ensure start_compress not called yet. */
if
(
cinfo
->
global_state
!=
CSTATE_START
)
ERREXIT1
(
cinfo
,
JERR_BAD_STATE
,
cinfo
->
global_state
);
/* Allocate comp_info array large enough for maximum component count.
* Array is made permanent in case application wants to compress
* multiple images at same param settings.
*/
if
(
cinfo
->
comp_info
==
NULL
)
cinfo
->
comp_info
=
(
jpeg_component_info
*
)
(
*
cinfo
->
mem
->
alloc_small
)
((
j_common_ptr
)
cinfo
,
JPOOL_PERMANENT
,
MAX_COMPONENTS
*
SIZEOF
(
jpeg_component_info
));
/* Initialize everything not dependent on the color space */
cinfo
->
data_precision
=
BITS_IN_JSAMPLE
;
/* Set up two quantization tables using default quality of 75 */
jpeg_set_quality
(
cinfo
,
75
,
TRUE
);
/* Set up two Huffman tables */
std_huff_tables
(
cinfo
);
/* Initialize default arithmetic coding conditioning */
for
(
i
=
0
;
i
<
NUM_ARITH_TBLS
;
i
++
)
{
cinfo
->
arith_dc_L
[
i
]
=
0
;
cinfo
->
arith_dc_U
[
i
]
=
1
;
cinfo
->
arith_ac_K
[
i
]
=
5
;
}
/* Default is no multiple-scan output */
cinfo
->
scan_info
=
NULL
;
cinfo
->
num_scans
=
0
;
/* Expect normal source image, not raw downsampled data */
cinfo
->
raw_data_in
=
FALSE
;
/* Use Huffman coding, not arithmetic coding, by default */
cinfo
->
arith_code
=
FALSE
;
/* By default, don't do extra passes to optimize entropy coding */
cinfo
->
optimize_coding
=
FALSE
;
/* The standard Huffman tables are only valid for 8-bit data precision.
* If the precision is higher, force optimization on so that usable
* tables will be computed. This test can be removed if default tables
* are supplied that are valid for the desired precision.
*/
if
(
cinfo
->
data_precision
>
8
)
cinfo
->
optimize_coding
=
TRUE
;
/* By default, use the simpler non-cosited sampling alignment */
cinfo
->
CCIR601_sampling
=
FALSE
;
/* No input smoothing */
cinfo
->
smoothing_factor
=
0
;
/* DCT algorithm preference */
cinfo
->
dct_method
=
JDCT_DEFAULT
;
/* No restart markers */
cinfo
->
restart_interval
=
0
;
cinfo
->
restart_in_rows
=
0
;
/* Fill in default JFIF marker parameters. Note that whether the marker
* will actually be written is determined by jpeg_set_colorspace.
*
* By default, the library emits JFIF version code 1.01.
* An application that wants to emit JFIF 1.02 extension markers should set
* JFIF_minor_version to 2. We could probably get away with just defaulting
* to 1.02, but there may still be some decoders in use that will complain
* about that; saying 1.01 should minimize compatibility problems.
*/
cinfo
->
JFIF_major_version
=
1
;
/* Default JFIF version = 1.01 */
cinfo
->
JFIF_minor_version
=
1
;
cinfo
->
density_unit
=
0
;
/* Pixel size is unknown by default */
cinfo
->
X_density
=
1
;
/* Pixel aspect ratio is square by default */
cinfo
->
Y_density
=
1
;
/* Choose JPEG colorspace based on input space, set defaults accordingly */
jpeg_default_colorspace
(
cinfo
);
}
/*
* Select an appropriate JPEG colorspace for in_color_space.
*/
GLOBAL
(
void
)
jpeg_default_colorspace
(
j_compress_ptr
cinfo
)
{
switch
(
cinfo
->
in_color_space
)
{
case
JCS_GRAYSCALE
:
jpeg_set_colorspace
(
cinfo
,
JCS_GRAYSCALE
);
break
;
case
JCS_RGB
:
jpeg_set_colorspace
(
cinfo
,
JCS_YCbCr
);
break
;
case
JCS_YCbCr
:
jpeg_set_colorspace
(
cinfo
,
JCS_YCbCr
);
break
;
case
JCS_CMYK
:
jpeg_set_colorspace
(
cinfo
,
JCS_CMYK
);
/* By default, no translation */
break
;
case
JCS_YCCK
:
jpeg_set_colorspace
(
cinfo
,
JCS_YCCK
);
break
;
case
JCS_UNKNOWN
:
jpeg_set_colorspace
(
cinfo
,
JCS_UNKNOWN
);
break
;
default
:
ERREXIT
(
cinfo
,
JERR_BAD_IN_COLORSPACE
);
}
}
/*
* Set the JPEG colorspace, and choose colorspace-dependent default values.
*/
GLOBAL
(
void
)
jpeg_set_colorspace
(
j_compress_ptr
cinfo
,
J_COLOR_SPACE
colorspace
)
{
jpeg_component_info
*
compptr
;
int
ci
;
#define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl) \
(compptr = &cinfo->comp_info[index], \
compptr->component_id = (id), \
compptr->h_samp_factor = (hsamp), \
compptr->v_samp_factor = (vsamp), \
compptr->quant_tbl_no = (quant), \
compptr->dc_tbl_no = (dctbl), \
compptr->ac_tbl_no = (actbl) )
/* Safety check to ensure start_compress not called yet. */
if
(
cinfo
->
global_state
!=
CSTATE_START
)
ERREXIT1
(
cinfo
,
JERR_BAD_STATE
,
cinfo
->
global_state
);
/* For all colorspaces, we use Q and Huff tables 0 for luminance components,
* tables 1 for chrominance components.
*/
cinfo
->
jpeg_color_space
=
colorspace
;
cinfo
->
write_JFIF_header
=
FALSE
;
/* No marker for non-JFIF colorspaces */
cinfo
->
write_Adobe_marker
=
FALSE
;
/* write no Adobe marker by default */
switch
(
colorspace
)
{
case
JCS_GRAYSCALE
:
cinfo
->
write_JFIF_header
=
TRUE
;
/* Write a JFIF marker */
cinfo
->
num_components
=
1
;
/* JFIF specifies component ID 1 */
SET_COMP
(
0
,
1
,
1
,
1
,
0
,
0
,
0
);
break
;
case
JCS_RGB
:
cinfo
->
write_Adobe_marker
=
TRUE
;
/* write Adobe marker to flag RGB */
cinfo
->
num_components
=
3
;
SET_COMP
(
0
,
0x52
/* 'R' */
,
1
,
1
,
0
,
0
,
0
);
SET_COMP
(
1
,
0x47
/* 'G' */
,
1
,
1
,
0
,
0
,
0
);
SET_COMP
(
2
,
0x42
/* 'B' */
,
1
,
1
,
0
,
0
,
0
);
break
;
case
JCS_YCbCr
:
cinfo
->
write_JFIF_header
=
TRUE
;
/* Write a JFIF marker */
cinfo
->
num_components
=
3
;
/* JFIF specifies component IDs 1,2,3 */
/* We default to 2x2 subsamples of chrominance */
SET_COMP
(
0
,
1
,
2
,
2
,
0
,
0
,
0
);
SET_COMP
(
1
,
2
,
1
,
1
,
1
,
1
,
1
);
SET_COMP
(
2
,
3
,
1
,
1
,
1
,
1
,
1
);
break
;
case
JCS_CMYK
:
cinfo
->
write_Adobe_marker
=
TRUE
;
/* write Adobe marker to flag CMYK */
cinfo
->
num_components
=
4
;
SET_COMP
(
0
,
0x43
/* 'C' */
,
1
,
1
,
0
,
0
,
0
);
SET_COMP
(
1
,
0x4D
/* 'M' */
,
1
,
1
,
0
,
0
,
0
);
SET_COMP
(
2
,
0x59
/* 'Y' */
,
1
,
1
,
0
,
0
,
0
);
SET_COMP
(
3
,
0x4B
/* 'K' */
,
1
,
1
,
0
,
0
,
0
);
break
;
case
JCS_YCCK
:
cinfo
->
write_Adobe_marker
=
TRUE
;
/* write Adobe marker to flag YCCK */
cinfo
->
num_components
=
4
;
SET_COMP
(
0
,
1
,
2
,
2
,
0
,
0
,
0
);
SET_COMP
(
1
,
2
,
1
,
1
,
1
,
1
,
1
);
SET_COMP
(
2
,
3
,
1
,
1
,
1
,
1
,
1
);
SET_COMP
(
3
,
4
,
2
,
2
,
0
,
0
,
0
);
break
;
case
JCS_UNKNOWN
:
cinfo
->
num_components
=
cinfo
->
input_components
;
if
(
cinfo
->
num_components
<
1
||
cinfo
->
num_components
>
MAX_COMPONENTS
)
ERREXIT2
(
cinfo
,
JERR_COMPONENT_COUNT
,
cinfo
->
num_components
,
MAX_COMPONENTS
);
for
(
ci
=
0
;
ci
<
cinfo
->
num_components
;
ci
++
)
{
SET_COMP
(
ci
,
ci
,
1
,
1
,
0
,
0
,
0
);
}
break
;
default
:
ERREXIT
(
cinfo
,
JERR_BAD_J_COLORSPACE
);
}
}
#ifdef C_PROGRESSIVE_SUPPORTED
LOCAL
(
jpeg_scan_info
*
)
fill_a_scan
(
jpeg_scan_info
*
scanptr
,
int
ci
,
int
Ss
,
int
Se
,
int
Ah
,
int
Al
)
/* Support routine: generate one scan for specified component */
{
scanptr
->
comps_in_scan
=
1
;
scanptr
->
component_index
[
0
]
=
ci
;
scanptr
->
Ss
=
Ss
;
scanptr
->
Se
=
Se
;
scanptr
->
Ah
=
Ah
;
scanptr
->
Al
=
Al
;
scanptr
++
;
return
scanptr
;
}
LOCAL
(
jpeg_scan_info
*
)
fill_scans
(
jpeg_scan_info
*
scanptr
,
int
ncomps
,
int
Ss
,
int
Se
,
int
Ah
,
int
Al
)
/* Support routine: generate one scan for each component */
{
int
ci
;
for
(
ci
=
0
;
ci
<
ncomps
;
ci
++
)
{
scanptr
->
comps_in_scan
=
1
;
scanptr
->
component_index
[
0
]
=
ci
;
scanptr
->
Ss
=
Ss
;
scanptr
->
Se
=
Se
;
scanptr
->
Ah
=
Ah
;
scanptr
->
Al
=
Al
;
scanptr
++
;
}
return
scanptr
;
}
LOCAL
(
jpeg_scan_info
*
)
fill_dc_scans
(
jpeg_scan_info
*
scanptr
,
int
ncomps
,
int
Ah
,
int
Al
)
/* Support routine: generate interleaved DC scan if possible, else N scans */
{
int
ci
;
if
(
ncomps
<=
MAX_COMPS_IN_SCAN
)
{
/* Single interleaved DC scan */
scanptr
->
comps_in_scan
=
ncomps
;
for
(
ci
=
0
;
ci
<
ncomps
;
ci
++
)
scanptr
->
component_index
[
ci
]
=
ci
;
scanptr
->
Ss
=
scanptr
->
Se
=
0
;
scanptr
->
Ah
=
Ah
;
scanptr
->
Al
=
Al
;
scanptr
++
;
}
else
{
/* Noninterleaved DC scan for each component */
scanptr
=
fill_scans
(
scanptr
,
ncomps
,
0
,
0
,
Ah
,
Al
);
}
return
scanptr
;
}
/*
* Create a recommended progressive-JPEG script.
* cinfo->num_components and cinfo->jpeg_color_space must be correct.
*/
GLOBAL
(
void
)
jpeg_simple_progression
(
j_compress_ptr
cinfo
)
{
int
ncomps
=
cinfo
->
num_components
;
int
nscans
;
jpeg_scan_info
*
scanptr
;
/* Safety check to ensure start_compress not called yet. */
if
(
cinfo
->
global_state
!=
CSTATE_START
)
ERREXIT1
(
cinfo
,
JERR_BAD_STATE
,
cinfo
->
global_state
);
/* Figure space needed for script. Calculation must match code below! */
if
(
ncomps
==
3
&&
cinfo
->
jpeg_color_space
==
JCS_YCbCr
)
{
/* Custom script for YCbCr color images. */
nscans
=
10
;
}
else
{
/* All-purpose script for other color spaces. */
if
(
ncomps
>
MAX_COMPS_IN_SCAN
)
nscans
=
6
*
ncomps
;
/* 2 DC + 4 AC scans per component */
else
nscans
=
2
+
4
*
ncomps
;
/* 2 DC scans; 4 AC scans per component */
}
/* Allocate space for script.
* We need to put it in the permanent pool in case the application performs
* multiple compressions without changing the settings. To avoid a memory
* leak if jpeg_simple_progression is called repeatedly for the same JPEG
* object, we try to re-use previously allocated space, and we allocate
* enough space to handle YCbCr even if initially asked for grayscale.
*/
if
(
cinfo
->
script_space
==
NULL
||
cinfo
->
script_space_size
<
nscans
)
{
cinfo
->
script_space_size
=
MAX
(
nscans
,
10
);
cinfo
->
script_space
=
(
jpeg_scan_info
*
)
(
*
cinfo
->
mem
->
alloc_small
)
((
j_common_ptr
)
cinfo
,
JPOOL_PERMANENT
,
cinfo
->
script_space_size
*
SIZEOF
(
jpeg_scan_info
));
}
scanptr
=
cinfo
->
script_space
;
cinfo
->
scan_info
=
scanptr
;
cinfo
->
num_scans
=
nscans
;
if
(
ncomps
==
3
&&
cinfo
->
jpeg_color_space
==
JCS_YCbCr
)
{
/* Custom script for YCbCr color images. */
/* Initial DC scan */
scanptr
=
fill_dc_scans
(
scanptr
,
ncomps
,
0
,
1
);
/* Initial AC scan: get some luma data out in a hurry */
scanptr
=
fill_a_scan
(
scanptr
,
0
,
1
,
5
,
0
,
2
);
/* Chroma data is too small to be worth expending many scans on */
scanptr
=
fill_a_scan
(
scanptr
,
2
,
1
,
63
,
0
,
1
);
scanptr
=
fill_a_scan
(
scanptr
,
1
,
1
,
63
,
0
,
1
);
/* Complete spectral selection for luma AC */
scanptr
=
fill_a_scan
(
scanptr
,
0
,
6
,
63
,
0
,
2
);
/* Refine next bit of luma AC */
scanptr
=
fill_a_scan
(
scanptr
,
0
,
1
,
63
,
2
,
1
);
/* Finish DC successive approximation */
scanptr
=
fill_dc_scans
(
scanptr
,
ncomps
,
1
,
0
);
/* Finish AC successive approximation */
scanptr
=
fill_a_scan
(
scanptr
,
2
,
1
,
63
,
1
,
0
);
scanptr
=
fill_a_scan
(
scanptr
,
1
,
1
,
63
,
1
,
0
);
/* Luma bottom bit comes last since it's usually largest scan */
scanptr
=
fill_a_scan
(
scanptr
,
0
,
1
,
63
,
1
,
0
);
}
else
{
/* All-purpose script for other color spaces. */
/* Successive approximation first pass */
scanptr
=
fill_dc_scans
(
scanptr
,
ncomps
,
0
,
1
);
scanptr
=
fill_scans
(
scanptr
,
ncomps
,
1
,
5
,
0
,
2
);
scanptr
=
fill_scans
(
scanptr
,
ncomps
,
6
,
63
,
0
,
2
);
/* Successive approximation second pass */
scanptr
=
fill_scans
(
scanptr
,
ncomps
,
1
,
63
,
2
,
1
);
/* Successive approximation final pass */
scanptr
=
fill_dc_scans
(
scanptr
,
ncomps
,
1
,
0
);
scanptr
=
fill_scans
(
scanptr
,
ncomps
,
1
,
63
,
1
,
0
);
}
}
#endif
/* C_PROGRESSIVE_SUPPORTED */
dlib/external/libjpeg/jcphuff.cpp
0 → 100644
View file @
747088ea
/*
* jcphuff.c
*
* Copyright (C) 1995-1997, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains Huffman entropy encoding routines for progressive JPEG.
*
* We do not support output suspension in this module, since the library
* currently does not allow multiple-scan files to be written with output
* suspension.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jchuff.h"
/* Declarations shared with jchuff.c */
#ifdef C_PROGRESSIVE_SUPPORTED
/* Expanded entropy encoder object for progressive Huffman encoding. */
typedef
struct
{
struct
jpeg_entropy_encoder
pub
;
/* public fields */
/* Mode flag: TRUE for optimization, FALSE for actual data output */
int
gather_statistics
;
/* Bit-level coding status.
* next_output_byte/free_in_buffer are local copies of cinfo->dest fields.
*/
JOCTET
*
next_output_byte
;
/* => next byte to write in buffer */
size_t
free_in_buffer
;
/* # of byte spaces remaining in buffer */
long
put_buffer
;
/* current bit-accumulation buffer */
int
put_bits
;
/* # of bits now in it */
j_compress_ptr
cinfo
;
/* link to cinfo (needed for dump_buffer) */
/* Coding status for DC components */
int
last_dc_val
[
MAX_COMPS_IN_SCAN
];
/* last DC coef for each component */
/* Coding status for AC components */
int
ac_tbl_no
;
/* the table number of the single component */
unsigned
int
EOBRUN
;
/* run length of EOBs */
unsigned
int
BE
;
/* # of buffered correction bits before MCU */
char
*
bit_buffer
;
/* buffer for correction bits (1 per char) */
/* packing correction bits tightly would save some space but cost time... */
unsigned
int
restarts_to_go
;
/* MCUs left in this restart interval */
int
next_restart_num
;
/* next restart number to write (0-7) */
/* Pointers to derived tables (these workspaces have image lifespan).
* Since any one scan codes only DC or only AC, we only need one set
* of tables, not one for DC and one for AC.
*/
c_derived_tbl
*
derived_tbls
[
NUM_HUFF_TBLS
];
/* Statistics tables for optimization; again, one set is enough */
long
*
count_ptrs
[
NUM_HUFF_TBLS
];
}
phuff_entropy_encoder
;
typedef
phuff_entropy_encoder
*
phuff_entropy_ptr
;
/* MAX_CORR_BITS is the number of bits the AC refinement correction-bit
* buffer can hold. Larger sizes may slightly improve compression, but
* 1000 is already well into the realm of overkill.
* The minimum safe size is 64 bits.
*/
#define MAX_CORR_BITS 1000
/* Max # of correction bits I can buffer */
/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than long.
* We assume that int right shift is unsigned if long right shift is,
* which should be safe.
*/
#ifdef RIGHT_SHIFT_IS_UNSIGNED
#define ISHIFT_TEMPS int ishift_temp;
#define IRIGHT_SHIFT(x,shft) \
((ishift_temp = (x)) < 0 ? \
(ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \
(ishift_temp >> (shft)))
#else
#define ISHIFT_TEMPS
#define IRIGHT_SHIFT(x,shft) ((x) >> (shft))
#endif
/* Forward declarations */
METHODDEF
(
int
)
encode_mcu_DC_first
JPP
((
j_compress_ptr
cinfo
,
JBLOCKROW
*
MCU_data
));
METHODDEF
(
int
)
encode_mcu_AC_first
JPP
((
j_compress_ptr
cinfo
,
JBLOCKROW
*
MCU_data
));
METHODDEF
(
int
)
encode_mcu_DC_refine
JPP
((
j_compress_ptr
cinfo
,
JBLOCKROW
*
MCU_data
));
METHODDEF
(
int
)
encode_mcu_AC_refine
JPP
((
j_compress_ptr
cinfo
,
JBLOCKROW
*
MCU_data
));
METHODDEF
(
void
)
finish_pass_phuff
JPP
((
j_compress_ptr
cinfo
));
METHODDEF
(
void
)
finish_pass_gather_phuff
JPP
((
j_compress_ptr
cinfo
));
/*
* Initialize for a Huffman-compressed scan using progressive JPEG.
*/
METHODDEF
(
void
)
start_pass_phuff
(
j_compress_ptr
cinfo
,
int
gather_statistics
)
{
phuff_entropy_ptr
entropy
=
(
phuff_entropy_ptr
)
cinfo
->
entropy
;
int
is_DC_band
;
int
ci
,
tbl
;
jpeg_component_info
*
compptr
;
entropy
->
cinfo
=
cinfo
;
entropy
->
gather_statistics
=
gather_statistics
;
is_DC_band
=
(
cinfo
->
Ss
==
0
);
/* We assume jcmaster.c already validated the scan parameters. */
/* Select execution routines */
if
(
cinfo
->
Ah
==
0
)
{
if
(
is_DC_band
)
entropy
->
pub
.
encode_mcu
=
encode_mcu_DC_first
;
else
entropy
->
pub
.
encode_mcu
=
encode_mcu_AC_first
;
}
else
{
if
(
is_DC_band
)
entropy
->
pub
.
encode_mcu
=
encode_mcu_DC_refine
;
else
{
entropy
->
pub
.
encode_mcu
=
encode_mcu_AC_refine
;
/* AC refinement needs a correction bit buffer */
if
(
entropy
->
bit_buffer
==
NULL
)
entropy
->
bit_buffer
=
(
char
*
)
(
*
cinfo
->
mem
->
alloc_small
)
((
j_common_ptr
)
cinfo
,
JPOOL_IMAGE
,
MAX_CORR_BITS
*
SIZEOF
(
char
));
}
}
if
(
gather_statistics
)
entropy
->
pub
.
finish_pass
=
finish_pass_gather_phuff
;
else
entropy
->
pub
.
finish_pass
=
finish_pass_phuff
;
/* Only DC coefficients may be interleaved, so cinfo->comps_in_scan = 1
* for AC coefficients.
*/
for
(
ci
=
0
;
ci
<
cinfo
->
comps_in_scan
;
ci
++
)
{
compptr
=
cinfo
->
cur_comp_info
[
ci
];
/* Initialize DC predictions to 0 */
entropy
->
last_dc_val
[
ci
]
=
0
;
/* Get table index */
if
(
is_DC_band
)
{
if
(
cinfo
->
Ah
!=
0
)
/* DC refinement needs no table */
continue
;
tbl
=
compptr
->
dc_tbl_no
;
}
else
{
entropy
->
ac_tbl_no
=
tbl
=
compptr
->
ac_tbl_no
;
}
if
(
gather_statistics
)
{
/* Check for invalid table index */
/* (make_c_derived_tbl does this in the other path) */
if
(
tbl
<
0
||
tbl
>=
NUM_HUFF_TBLS
)
ERREXIT1
(
cinfo
,
JERR_NO_HUFF_TABLE
,
tbl
);
/* Allocate and zero the statistics tables */
/* Note that jpeg_gen_optimal_table expects 257 entries in each table! */
if
(
entropy
->
count_ptrs
[
tbl
]
==
NULL
)
entropy
->
count_ptrs
[
tbl
]
=
(
long
*
)
(
*
cinfo
->
mem
->
alloc_small
)
((
j_common_ptr
)
cinfo
,
JPOOL_IMAGE
,
257
*
SIZEOF
(
long
));
MEMZERO
(
entropy
->
count_ptrs
[
tbl
],
257
*
SIZEOF
(
long
));
}
else
{
/* Compute derived values for Huffman table */
/* We may do this more than once for a table, but it's not expensive */
jpeg_make_c_derived_tbl
(
cinfo
,
is_DC_band
,
tbl
,
&
entropy
->
derived_tbls
[
tbl
]);
}
}
/* Initialize AC stuff */
entropy
->
EOBRUN
=
0
;
entropy
->
BE
=
0
;
/* Initialize bit buffer to empty */
entropy
->
put_buffer
=
0
;
entropy
->
put_bits
=
0
;
/* Initialize restart stuff */
entropy
->
restarts_to_go
=
cinfo
->
restart_interval
;
entropy
->
next_restart_num
=
0
;
}
/* Outputting bytes to the file.
* NB: these must be called only when actually outputting,
* that is, entropy->gather_statistics == FALSE.
*/
/* Emit a byte */
#define emit_byte(entropy,val) \
{ *(entropy)->next_output_byte++ = (JOCTET) (val); \
if (--(entropy)->free_in_buffer == 0) \
dump_buffer(entropy); }
LOCAL
(
void
)
dump_buffer
(
phuff_entropy_ptr
entropy
)
/* Empty the output buffer; we do not support suspension in this module. */
{
struct
jpeg_destination_mgr
*
dest
=
entropy
->
cinfo
->
dest
;
if
(
!
(
*
dest
->
empty_output_buffer
)
(
entropy
->
cinfo
))
ERREXIT
(
entropy
->
cinfo
,
JERR_CANT_SUSPEND
);
/* After a successful buffer dump, must reset buffer pointers */
entropy
->
next_output_byte
=
dest
->
next_output_byte
;
entropy
->
free_in_buffer
=
dest
->
free_in_buffer
;
}
/* Outputting bits to the file */
/* Only the right 24 bits of put_buffer are used; the valid bits are
* left-justified in this part. At most 16 bits can be passed to emit_bits
* in one call, and we never retain more than 7 bits in put_buffer
* between calls, so 24 bits are sufficient.
*/
INLINE
LOCAL
(
void
)
emit_bits
(
phuff_entropy_ptr
entropy
,
unsigned
int
code
,
int
size
)
/* Emit some bits, unless we are in gather mode */
{
/* This routine is heavily used, so it's worth coding tightly. */
register
long
put_buffer
=
(
long
)
code
;
register
int
put_bits
=
entropy
->
put_bits
;
/* if size is 0, caller used an invalid Huffman table entry */
if
(
size
==
0
)
ERREXIT
(
entropy
->
cinfo
,
JERR_HUFF_MISSING_CODE
);
if
(
entropy
->
gather_statistics
)
return
;
/* do nothing if we're only getting stats */
put_buffer
&=
(((
long
)
1
)
<<
size
)
-
1
;
/* mask off any extra bits in code */
put_bits
+=
size
;
/* new number of bits in buffer */
put_buffer
<<=
24
-
put_bits
;
/* align incoming bits */
put_buffer
|=
entropy
->
put_buffer
;
/* and merge with old buffer contents */
while
(
put_bits
>=
8
)
{
int
c
=
(
int
)
((
put_buffer
>>
16
)
&
0xFF
);
emit_byte
(
entropy
,
c
);
if
(
c
==
0xFF
)
{
/* need to stuff a zero byte? */
emit_byte
(
entropy
,
0
);
}
put_buffer
<<=
8
;
put_bits
-=
8
;
}
entropy
->
put_buffer
=
put_buffer
;
/* update variables */
entropy
->
put_bits
=
put_bits
;
}
LOCAL
(
void
)
flush_bits
(
phuff_entropy_ptr
entropy
)
{
emit_bits
(
entropy
,
0x7F
,
7
);
/* fill any partial byte with ones */
entropy
->
put_buffer
=
0
;
/* and reset bit-buffer to empty */
entropy
->
put_bits
=
0
;
}
/*
* Emit (or just count) a Huffman symbol.
*/
INLINE
LOCAL
(
void
)
emit_symbol
(
phuff_entropy_ptr
entropy
,
int
tbl_no
,
int
symbol
)
{
if
(
entropy
->
gather_statistics
)
entropy
->
count_ptrs
[
tbl_no
][
symbol
]
++
;
else
{
c_derived_tbl
*
tbl
=
entropy
->
derived_tbls
[
tbl_no
];
emit_bits
(
entropy
,
tbl
->
ehufco
[
symbol
],
tbl
->
ehufsi
[
symbol
]);
}
}
/*
* Emit bits from a correction bit buffer.
*/
LOCAL
(
void
)
emit_buffered_bits
(
phuff_entropy_ptr
entropy
,
char
*
bufstart
,
unsigned
int
nbits
)
{
if
(
entropy
->
gather_statistics
)
return
;
/* no real work */
while
(
nbits
>
0
)
{
emit_bits
(
entropy
,
(
unsigned
int
)
(
*
bufstart
),
1
);
bufstart
++
;
nbits
--
;
}
}
/*
* Emit any pending EOBRUN symbol.
*/
LOCAL
(
void
)
emit_eobrun
(
phuff_entropy_ptr
entropy
)
{
register
int
temp
,
nbits
;
if
(
entropy
->
EOBRUN
>
0
)
{
/* if there is any pending EOBRUN */
temp
=
entropy
->
EOBRUN
;
nbits
=
0
;
while
((
temp
>>=
1
))
nbits
++
;
/* safety check: shouldn't happen given limited correction-bit buffer */
if
(
nbits
>
14
)
ERREXIT
(
entropy
->
cinfo
,
JERR_HUFF_MISSING_CODE
);
emit_symbol
(
entropy
,
entropy
->
ac_tbl_no
,
nbits
<<
4
);
if
(
nbits
)
emit_bits
(
entropy
,
entropy
->
EOBRUN
,
nbits
);
entropy
->
EOBRUN
=
0
;
/* Emit any buffered correction bits */
emit_buffered_bits
(
entropy
,
entropy
->
bit_buffer
,
entropy
->
BE
);
entropy
->
BE
=
0
;
}
}
/*
* Emit a restart marker & resynchronize predictions.
*/
LOCAL
(
void
)
emit_restart
(
phuff_entropy_ptr
entropy
,
int
restart_num
)
{
int
ci
;
emit_eobrun
(
entropy
);
if
(
!
entropy
->
gather_statistics
)
{
flush_bits
(
entropy
);
emit_byte
(
entropy
,
0xFF
);
emit_byte
(
entropy
,
JPEG_RST0
+
restart_num
);
}
if
(
entropy
->
cinfo
->
Ss
==
0
)
{
/* Re-initialize DC predictions to 0 */
for
(
ci
=
0
;
ci
<
entropy
->
cinfo
->
comps_in_scan
;
ci
++
)
entropy
->
last_dc_val
[
ci
]
=
0
;
}
else
{
/* Re-initialize all AC-related fields to 0 */
entropy
->
EOBRUN
=
0
;
entropy
->
BE
=
0
;
}
}
/*
* MCU encoding for DC initial scan (either spectral selection,
* or first pass of successive approximation).
*/
METHODDEF
(
int
)
encode_mcu_DC_first
(
j_compress_ptr
cinfo
,
JBLOCKROW
*
MCU_data
)
{
phuff_entropy_ptr
entropy
=
(
phuff_entropy_ptr
)
cinfo
->
entropy
;
register
int
temp
,
temp2
;
register
int
nbits
;
int
blkn
,
ci
;
int
Al
=
cinfo
->
Al
;
JBLOCKROW
block
;
jpeg_component_info
*
compptr
;
ISHIFT_TEMPS
entropy
->
next_output_byte
=
cinfo
->
dest
->
next_output_byte
;
entropy
->
free_in_buffer
=
cinfo
->
dest
->
free_in_buffer
;
/* Emit restart marker if needed */
if
(
cinfo
->
restart_interval
)
if
(
entropy
->
restarts_to_go
==
0
)
emit_restart
(
entropy
,
entropy
->
next_restart_num
);
/* Encode the MCU data blocks */
for
(
blkn
=
0
;
blkn
<
cinfo
->
blocks_in_MCU
;
blkn
++
)
{
block
=
MCU_data
[
blkn
];
ci
=
cinfo
->
MCU_membership
[
blkn
];
compptr
=
cinfo
->
cur_comp_info
[
ci
];
/* Compute the DC value after the required point transform by Al.
* This is simply an arithmetic right shift.
*/
temp2
=
IRIGHT_SHIFT
((
int
)
((
*
block
)[
0
]),
Al
);
/* DC differences are figured on the point-transformed values. */
temp
=
temp2
-
entropy
->
last_dc_val
[
ci
];
entropy
->
last_dc_val
[
ci
]
=
temp2
;
/* Encode the DC coefficient difference per section G.1.2.1 */
temp2
=
temp
;
if
(
temp
<
0
)
{
temp
=
-
temp
;
/* temp is abs value of input */
/* For a negative input, want temp2 = bitwise complement of abs(input) */
/* This code assumes we are on a two's complement machine */
temp2
--
;
}
/* Find the number of bits needed for the magnitude of the coefficient */
nbits
=
0
;
while
(
temp
)
{
nbits
++
;
temp
>>=
1
;
}
/* Check for out-of-range coefficient values.
* Since we're encoding a difference, the range limit is twice as much.
*/
if
(
nbits
>
MAX_COEF_BITS
+
1
)
ERREXIT
(
cinfo
,
JERR_BAD_DCT_COEF
);
/* Count/emit the Huffman-coded symbol for the number of bits */
emit_symbol
(
entropy
,
compptr
->
dc_tbl_no
,
nbits
);
/* Emit that number of bits of the value, if positive, */
/* or the complement of its magnitude, if negative. */
if
(
nbits
)
/* emit_bits rejects calls with size 0 */
emit_bits
(
entropy
,
(
unsigned
int
)
temp2
,
nbits
);
}
cinfo
->
dest
->
next_output_byte
=
entropy
->
next_output_byte
;
cinfo
->
dest
->
free_in_buffer
=
entropy
->
free_in_buffer
;
/* Update restart-interval state too */
if
(
cinfo
->
restart_interval
)
{
if
(
entropy
->
restarts_to_go
==
0
)
{
entropy
->
restarts_to_go
=
cinfo
->
restart_interval
;
entropy
->
next_restart_num
++
;
entropy
->
next_restart_num
&=
7
;
}
entropy
->
restarts_to_go
--
;
}
return
TRUE
;
}
/*
* MCU encoding for AC initial scan (either spectral selection,
* or first pass of successive approximation).
*/
METHODDEF
(
int
)
encode_mcu_AC_first
(
j_compress_ptr
cinfo
,
JBLOCKROW
*
MCU_data
)
{
phuff_entropy_ptr
entropy
=
(
phuff_entropy_ptr
)
cinfo
->
entropy
;
register
int
temp
,
temp2
;
register
int
nbits
;
register
int
r
,
k
;
int
Se
=
cinfo
->
Se
;
int
Al
=
cinfo
->
Al
;
JBLOCKROW
block
;
entropy
->
next_output_byte
=
cinfo
->
dest
->
next_output_byte
;
entropy
->
free_in_buffer
=
cinfo
->
dest
->
free_in_buffer
;
/* Emit restart marker if needed */
if
(
cinfo
->
restart_interval
)
if
(
entropy
->
restarts_to_go
==
0
)
emit_restart
(
entropy
,
entropy
->
next_restart_num
);
/* Encode the MCU data block */
block
=
MCU_data
[
0
];
/* Encode the AC coefficients per section G.1.2.2, fig. G.3 */
r
=
0
;
/* r = run length of zeros */
for
(
k
=
cinfo
->
Ss
;
k
<=
Se
;
k
++
)
{
if
((
temp
=
(
*
block
)[
jpeg_natural_order
[
k
]])
==
0
)
{
r
++
;
continue
;
}
/* We must apply the point transform by Al. For AC coefficients this
* is an integer division with rounding towards 0. To do this portably
* in C, we shift after obtaining the absolute value; so the code is
* interwoven with finding the abs value (temp) and output bits (temp2).
*/
if
(
temp
<
0
)
{
temp
=
-
temp
;
/* temp is abs value of input */
temp
>>=
Al
;
/* apply the point transform */
/* For a negative coef, want temp2 = bitwise complement of abs(coef) */
temp2
=
~
temp
;
}
else
{
temp
>>=
Al
;
/* apply the point transform */
temp2
=
temp
;
}
/* Watch out for case that nonzero coef is zero after point transform */
if
(
temp
==
0
)
{
r
++
;
continue
;
}
/* Emit any pending EOBRUN */
if
(
entropy
->
EOBRUN
>
0
)
emit_eobrun
(
entropy
);
/* if run length > 15, must emit special run-length-16 codes (0xF0) */
while
(
r
>
15
)
{
emit_symbol
(
entropy
,
entropy
->
ac_tbl_no
,
0xF0
);
r
-=
16
;
}
/* Find the number of bits needed for the magnitude of the coefficient */
nbits
=
1
;
/* there must be at least one 1 bit */
while
((
temp
>>=
1
))
nbits
++
;
/* Check for out-of-range coefficient values */
if
(
nbits
>
MAX_COEF_BITS
)
ERREXIT
(
cinfo
,
JERR_BAD_DCT_COEF
);
/* Count/emit Huffman symbol for run length / number of bits */
emit_symbol
(
entropy
,
entropy
->
ac_tbl_no
,
(
r
<<
4
)
+
nbits
);
/* Emit that number of bits of the value, if positive, */
/* or the complement of its magnitude, if negative. */
emit_bits
(
entropy
,
(
unsigned
int
)
temp2
,
nbits
);
r
=
0
;
/* reset zero run length */
}
if
(
r
>
0
)
{
/* If there are trailing zeroes, */
entropy
->
EOBRUN
++
;
/* count an EOB */
if
(
entropy
->
EOBRUN
==
0x7FFF
)
emit_eobrun
(
entropy
);
/* force it out to avoid overflow */
}
cinfo
->
dest
->
next_output_byte
=
entropy
->
next_output_byte
;
cinfo
->
dest
->
free_in_buffer
=
entropy
->
free_in_buffer
;
/* Update restart-interval state too */
if
(
cinfo
->
restart_interval
)
{
if
(
entropy
->
restarts_to_go
==
0
)
{
entropy
->
restarts_to_go
=
cinfo
->
restart_interval
;
entropy
->
next_restart_num
++
;
entropy
->
next_restart_num
&=
7
;
}
entropy
->
restarts_to_go
--
;
}
return
TRUE
;
}
/*
* MCU encoding for DC successive approximation refinement scan.
* Note: we assume such scans can be multi-component, although the spec
* is not very clear on the point.
*/
METHODDEF
(
int
)
encode_mcu_DC_refine
(
j_compress_ptr
cinfo
,
JBLOCKROW
*
MCU_data
)
{
phuff_entropy_ptr
entropy
=
(
phuff_entropy_ptr
)
cinfo
->
entropy
;
register
int
temp
;
int
blkn
;
int
Al
=
cinfo
->
Al
;
JBLOCKROW
block
;
entropy
->
next_output_byte
=
cinfo
->
dest
->
next_output_byte
;
entropy
->
free_in_buffer
=
cinfo
->
dest
->
free_in_buffer
;
/* Emit restart marker if needed */
if
(
cinfo
->
restart_interval
)
if
(
entropy
->
restarts_to_go
==
0
)
emit_restart
(
entropy
,
entropy
->
next_restart_num
);
/* Encode the MCU data blocks */
for
(
blkn
=
0
;
blkn
<
cinfo
->
blocks_in_MCU
;
blkn
++
)
{
block
=
MCU_data
[
blkn
];
/* We simply emit the Al'th bit of the DC coefficient value. */
temp
=
(
*
block
)[
0
];
emit_bits
(
entropy
,
(
unsigned
int
)
(
temp
>>
Al
),
1
);
}
cinfo
->
dest
->
next_output_byte
=
entropy
->
next_output_byte
;
cinfo
->
dest
->
free_in_buffer
=
entropy
->
free_in_buffer
;
/* Update restart-interval state too */
if
(
cinfo
->
restart_interval
)
{
if
(
entropy
->
restarts_to_go
==
0
)
{
entropy
->
restarts_to_go
=
cinfo
->
restart_interval
;
entropy
->
next_restart_num
++
;
entropy
->
next_restart_num
&=
7
;
}
entropy
->
restarts_to_go
--
;
}
return
TRUE
;
}
/*
* MCU encoding for AC successive approximation refinement scan.
*/
METHODDEF
(
int
)
encode_mcu_AC_refine
(
j_compress_ptr
cinfo
,
JBLOCKROW
*
MCU_data
)
{
phuff_entropy_ptr
entropy
=
(
phuff_entropy_ptr
)
cinfo
->
entropy
;
register
int
temp
;
register
int
r
,
k
;
int
EOB
;
char
*
BR_buffer
;
unsigned
int
BR
;
int
Se
=
cinfo
->
Se
;
int
Al
=
cinfo
->
Al
;
JBLOCKROW
block
;
int
absvalues
[
DCTSIZE2
];
entropy
->
next_output_byte
=
cinfo
->
dest
->
next_output_byte
;
entropy
->
free_in_buffer
=
cinfo
->
dest
->
free_in_buffer
;
/* Emit restart marker if needed */
if
(
cinfo
->
restart_interval
)
if
(
entropy
->
restarts_to_go
==
0
)
emit_restart
(
entropy
,
entropy
->
next_restart_num
);
/* Encode the MCU data block */
block
=
MCU_data
[
0
];
/* It is convenient to make a pre-pass to determine the transformed
* coefficients' absolute values and the EOB position.
*/
EOB
=
0
;
for
(
k
=
cinfo
->
Ss
;
k
<=
Se
;
k
++
)
{
temp
=
(
*
block
)[
jpeg_natural_order
[
k
]];
/* We must apply the point transform by Al. For AC coefficients this
* is an integer division with rounding towards 0. To do this portably
* in C, we shift after obtaining the absolute value.
*/
if
(
temp
<
0
)
temp
=
-
temp
;
/* temp is abs value of input */
temp
>>=
Al
;
/* apply the point transform */
absvalues
[
k
]
=
temp
;
/* save abs value for main pass */
if
(
temp
==
1
)
EOB
=
k
;
/* EOB = index of last newly-nonzero coef */
}
/* Encode the AC coefficients per section G.1.2.3, fig. G.7 */
r
=
0
;
/* r = run length of zeros */
BR
=
0
;
/* BR = count of buffered bits added now */
BR_buffer
=
entropy
->
bit_buffer
+
entropy
->
BE
;
/* Append bits to buffer */
for
(
k
=
cinfo
->
Ss
;
k
<=
Se
;
k
++
)
{
if
((
temp
=
absvalues
[
k
])
==
0
)
{
r
++
;
continue
;
}
/* Emit any required ZRLs, but not if they can be folded into EOB */
while
(
r
>
15
&&
k
<=
EOB
)
{
/* emit any pending EOBRUN and the BE correction bits */
emit_eobrun
(
entropy
);
/* Emit ZRL */
emit_symbol
(
entropy
,
entropy
->
ac_tbl_no
,
0xF0
);
r
-=
16
;
/* Emit buffered correction bits that must be associated with ZRL */
emit_buffered_bits
(
entropy
,
BR_buffer
,
BR
);
BR_buffer
=
entropy
->
bit_buffer
;
/* BE bits are gone now */
BR
=
0
;
}
/* If the coef was previously nonzero, it only needs a correction bit.
* NOTE: a straight translation of the spec's figure G.7 would suggest
* that we also need to test r > 15. But if r > 15, we can only get here
* if k > EOB, which implies that this coefficient is not 1.
*/
if
(
temp
>
1
)
{
/* The correction bit is the next bit of the absolute value. */
BR_buffer
[
BR
++
]
=
(
char
)
(
temp
&
1
);
continue
;
}
/* Emit any pending EOBRUN and the BE correction bits */
emit_eobrun
(
entropy
);
/* Count/emit Huffman symbol for run length / number of bits */
emit_symbol
(
entropy
,
entropy
->
ac_tbl_no
,
(
r
<<
4
)
+
1
);
/* Emit output bit for newly-nonzero coef */
temp
=
((
*
block
)[
jpeg_natural_order
[
k
]]
<
0
)
?
0
:
1
;
emit_bits
(
entropy
,
(
unsigned
int
)
temp
,
1
);
/* Emit buffered correction bits that must be associated with this code */
emit_buffered_bits
(
entropy
,
BR_buffer
,
BR
);
BR_buffer
=
entropy
->
bit_buffer
;
/* BE bits are gone now */
BR
=
0
;
r
=
0
;
/* reset zero run length */
}
if
(
r
>
0
||
BR
>
0
)
{
/* If there are trailing zeroes, */
entropy
->
EOBRUN
++
;
/* count an EOB */
entropy
->
BE
+=
BR
;
/* concat my correction bits to older ones */
/* We force out the EOB if we risk either:
* 1. overflow of the EOB counter;
* 2. overflow of the correction bit buffer during the next MCU.
*/
if
(
entropy
->
EOBRUN
==
0x7FFF
||
entropy
->
BE
>
(
MAX_CORR_BITS
-
DCTSIZE2
+
1
))
emit_eobrun
(
entropy
);
}
cinfo
->
dest
->
next_output_byte
=
entropy
->
next_output_byte
;
cinfo
->
dest
->
free_in_buffer
=
entropy
->
free_in_buffer
;
/* Update restart-interval state too */
if
(
cinfo
->
restart_interval
)
{
if
(
entropy
->
restarts_to_go
==
0
)
{
entropy
->
restarts_to_go
=
cinfo
->
restart_interval
;
entropy
->
next_restart_num
++
;
entropy
->
next_restart_num
&=
7
;
}
entropy
->
restarts_to_go
--
;
}
return
TRUE
;
}
/*
* Finish up at the end of a Huffman-compressed progressive scan.
*/
METHODDEF
(
void
)
finish_pass_phuff
(
j_compress_ptr
cinfo
)
{
phuff_entropy_ptr
entropy
=
(
phuff_entropy_ptr
)
cinfo
->
entropy
;
entropy
->
next_output_byte
=
cinfo
->
dest
->
next_output_byte
;
entropy
->
free_in_buffer
=
cinfo
->
dest
->
free_in_buffer
;
/* Flush out any buffered data */
emit_eobrun
(
entropy
);
flush_bits
(
entropy
);
cinfo
->
dest
->
next_output_byte
=
entropy
->
next_output_byte
;
cinfo
->
dest
->
free_in_buffer
=
entropy
->
free_in_buffer
;
}
/*
* Finish up a statistics-gathering pass and create the new Huffman tables.
*/
METHODDEF
(
void
)
finish_pass_gather_phuff
(
j_compress_ptr
cinfo
)
{
phuff_entropy_ptr
entropy
=
(
phuff_entropy_ptr
)
cinfo
->
entropy
;
int
is_DC_band
;
int
ci
,
tbl
;
jpeg_component_info
*
compptr
;
JHUFF_TBL
**
htblptr
;
int
did
[
NUM_HUFF_TBLS
];
/* Flush out buffered data (all we care about is counting the EOB symbol) */
emit_eobrun
(
entropy
);
is_DC_band
=
(
cinfo
->
Ss
==
0
);
/* It's important not to apply jpeg_gen_optimal_table more than once
* per table, because it clobbers the input frequency counts!
*/
MEMZERO
(
did
,
SIZEOF
(
did
));
for
(
ci
=
0
;
ci
<
cinfo
->
comps_in_scan
;
ci
++
)
{
compptr
=
cinfo
->
cur_comp_info
[
ci
];
if
(
is_DC_band
)
{
if
(
cinfo
->
Ah
!=
0
)
/* DC refinement needs no table */
continue
;
tbl
=
compptr
->
dc_tbl_no
;
}
else
{
tbl
=
compptr
->
ac_tbl_no
;
}
if
(
!
did
[
tbl
])
{
if
(
is_DC_band
)
htblptr
=
&
cinfo
->
dc_huff_tbl_ptrs
[
tbl
];
else
htblptr
=
&
cinfo
->
ac_huff_tbl_ptrs
[
tbl
];
if
(
*
htblptr
==
NULL
)
*
htblptr
=
jpeg_alloc_huff_table
((
j_common_ptr
)
cinfo
);
jpeg_gen_optimal_table
(
cinfo
,
*
htblptr
,
entropy
->
count_ptrs
[
tbl
]);
did
[
tbl
]
=
TRUE
;
}
}
}
/*
* Module initialization routine for progressive Huffman entropy encoding.
*/
GLOBAL
(
void
)
jinit_phuff_encoder
(
j_compress_ptr
cinfo
)
{
phuff_entropy_ptr
entropy
;
int
i
;
entropy
=
(
phuff_entropy_ptr
)
(
*
cinfo
->
mem
->
alloc_small
)
((
j_common_ptr
)
cinfo
,
JPOOL_IMAGE
,
SIZEOF
(
phuff_entropy_encoder
));
cinfo
->
entropy
=
(
struct
jpeg_entropy_encoder
*
)
entropy
;
entropy
->
pub
.
start_pass
=
start_pass_phuff
;
/* Mark tables unallocated */
for
(
i
=
0
;
i
<
NUM_HUFF_TBLS
;
i
++
)
{
entropy
->
derived_tbls
[
i
]
=
NULL
;
entropy
->
count_ptrs
[
i
]
=
NULL
;
}
entropy
->
bit_buffer
=
NULL
;
/* needed only in AC refinement scan */
}
#endif
/* C_PROGRESSIVE_SUPPORTED */
dlib/external/libjpeg/jcprepct.cpp
0 → 100644
View file @
747088ea
/*
* jcprepct.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains the compression preprocessing controller.
* This controller manages the color conversion, downsampling,
* and edge expansion steps.
*
* Most of the complexity here is associated with buffering input rows
* as required by the downsampler. See the comments at the head of
* jcsample.c for the downsampler's needs.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/* At present, jcsample.c can request context rows only for smoothing.
* In the future, we might also need context rows for CCIR601 sampling
* or other more-complex downsampling procedures. The code to support
* context rows should be compiled only if needed.
*/
#ifdef INPUT_SMOOTHING_SUPPORTED
#define CONTEXT_ROWS_SUPPORTED
#endif
/*
* For the simple (no-context-row) case, we just need to buffer one
* row group's worth of pixels for the downsampling step. At the bottom of
* the image, we pad to a full row group by replicating the last pixel row.
* The downsampler's last output row is then replicated if needed to pad
* out to a full iMCU row.
*
* When providing context rows, we must buffer three row groups' worth of
* pixels. Three row groups are physically allocated, but the row pointer
* arrays are made five row groups high, with the extra pointers above and
* below "wrapping around" to point to the last and first real row groups.
* This allows the downsampler to access the proper context rows.
* At the top and bottom of the image, we create dummy context rows by
* copying the first or last real pixel row. This copying could be avoided
* by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the
* trouble on the compression side.
*/
/* Private buffer controller object */
typedef
struct
{
struct
jpeg_c_prep_controller
pub
;
/* public fields */
/* Downsampling input buffer. This buffer holds color-converted data
* until we have enough to do a downsample step.
*/
JSAMPARRAY
color_buf
[
MAX_COMPONENTS
];
JDIMENSION
rows_to_go
;
/* counts rows remaining in source image */
int
next_buf_row
;
/* index of next row to store in color_buf */
#ifdef CONTEXT_ROWS_SUPPORTED
/* only needed for context case */
int
this_row_group
;
/* starting row index of group to process */
int
next_buf_stop
;
/* downsample when we reach this index */
#endif
}
my_prep_controller
;
typedef
my_prep_controller
*
my_prep_ptr
;
/*
* Initialize for a processing pass.
*/
METHODDEF
(
void
)
start_pass_prep
(
j_compress_ptr
cinfo
,
J_BUF_MODE
pass_mode
)
{
my_prep_ptr
prep
=
(
my_prep_ptr
)
cinfo
->
prep
;
if
(
pass_mode
!=
JBUF_PASS_THRU
)
ERREXIT
(
cinfo
,
JERR_BAD_BUFFER_MODE
);
/* Initialize total-height counter for detecting bottom of image */
prep
->
rows_to_go
=
cinfo
->
image_height
;
/* Mark the conversion buffer empty */
prep
->
next_buf_row
=
0
;
#ifdef CONTEXT_ROWS_SUPPORTED
/* Preset additional state variables for context mode.
* These aren't used in non-context mode, so we needn't test which mode.
*/
prep
->
this_row_group
=
0
;
/* Set next_buf_stop to stop after two row groups have been read in. */
prep
->
next_buf_stop
=
2
*
cinfo
->
max_v_samp_factor
;
#endif
}
/*
* Expand an image vertically from height input_rows to height output_rows,
* by duplicating the bottom row.
*/
LOCAL
(
void
)
expand_bottom_edge
(
JSAMPARRAY
image_data
,
JDIMENSION
num_cols
,
int
input_rows
,
int
output_rows
)
{
register
int
row
;
for
(
row
=
input_rows
;
row
<
output_rows
;
row
++
)
{
jcopy_sample_rows
(
image_data
,
input_rows
-
1
,
image_data
,
row
,
1
,
num_cols
);
}
}
/*
* Process some data in the simple no-context case.
*
* Preprocessor output data is counted in "row groups". A row group
* is defined to be v_samp_factor sample rows of each component.
* Downsampling will produce this much data from each max_v_samp_factor
* input rows.
*/
METHODDEF
(
void
)
pre_process_data
(
j_compress_ptr
cinfo
,
JSAMPARRAY
input_buf
,
JDIMENSION
*
in_row_ctr
,
JDIMENSION
in_rows_avail
,
JSAMPIMAGE
output_buf
,
JDIMENSION
*
out_row_group_ctr
,
JDIMENSION
out_row_groups_avail
)
{
my_prep_ptr
prep
=
(
my_prep_ptr
)
cinfo
->
prep
;
int
numrows
,
ci
;
JDIMENSION
inrows
;
jpeg_component_info
*
compptr
;
while
(
*
in_row_ctr
<
in_rows_avail
&&
*
out_row_group_ctr
<
out_row_groups_avail
)
{
/* Do color conversion to fill the conversion buffer. */
inrows
=
in_rows_avail
-
*
in_row_ctr
;
numrows
=
cinfo
->
max_v_samp_factor
-
prep
->
next_buf_row
;
numrows
=
(
int
)
MIN
((
JDIMENSION
)
numrows
,
inrows
);
(
*
cinfo
->
cconvert
->
color_convert
)
(
cinfo
,
input_buf
+
*
in_row_ctr
,
prep
->
color_buf
,
(
JDIMENSION
)
prep
->
next_buf_row
,
numrows
);
*
in_row_ctr
+=
numrows
;
prep
->
next_buf_row
+=
numrows
;
prep
->
rows_to_go
-=
numrows
;
/* If at bottom of image, pad to fill the conversion buffer. */
if
(
prep
->
rows_to_go
==
0
&&
prep
->
next_buf_row
<
cinfo
->
max_v_samp_factor
)
{
for
(
ci
=
0
;
ci
<
cinfo
->
num_components
;
ci
++
)
{
expand_bottom_edge
(
prep
->
color_buf
[
ci
],
cinfo
->
image_width
,
prep
->
next_buf_row
,
cinfo
->
max_v_samp_factor
);
}
prep
->
next_buf_row
=
cinfo
->
max_v_samp_factor
;
}
/* If we've filled the conversion buffer, empty it. */
if
(
prep
->
next_buf_row
==
cinfo
->
max_v_samp_factor
)
{
(
*
cinfo
->
downsample
->
downsample
)
(
cinfo
,
prep
->
color_buf
,
(
JDIMENSION
)
0
,
output_buf
,
*
out_row_group_ctr
);
prep
->
next_buf_row
=
0
;
(
*
out_row_group_ctr
)
++
;
}
/* If at bottom of image, pad the output to a full iMCU height.
* Note we assume the caller is providing a one-iMCU-height output buffer!
*/
if
(
prep
->
rows_to_go
==
0
&&
*
out_row_group_ctr
<
out_row_groups_avail
)
{
for
(
ci
=
0
,
compptr
=
cinfo
->
comp_info
;
ci
<
cinfo
->
num_components
;
ci
++
,
compptr
++
)
{
expand_bottom_edge
(
output_buf
[
ci
],
compptr
->
width_in_blocks
*
DCTSIZE
,
(
int
)
(
*
out_row_group_ctr
*
compptr
->
v_samp_factor
),
(
int
)
(
out_row_groups_avail
*
compptr
->
v_samp_factor
));
}
*
out_row_group_ctr
=
out_row_groups_avail
;
break
;
/* can exit outer loop without test */
}
}
}
#ifdef CONTEXT_ROWS_SUPPORTED
/*
* Process some data in the context case.
*/
METHODDEF
(
void
)
pre_process_context
(
j_compress_ptr
cinfo
,
JSAMPARRAY
input_buf
,
JDIMENSION
*
in_row_ctr
,
JDIMENSION
in_rows_avail
,
JSAMPIMAGE
output_buf
,
JDIMENSION
*
out_row_group_ctr
,
JDIMENSION
out_row_groups_avail
)
{
my_prep_ptr
prep
=
(
my_prep_ptr
)
cinfo
->
prep
;
int
numrows
,
ci
;
int
buf_height
=
cinfo
->
max_v_samp_factor
*
3
;
JDIMENSION
inrows
;
while
(
*
out_row_group_ctr
<
out_row_groups_avail
)
{
if
(
*
in_row_ctr
<
in_rows_avail
)
{
/* Do color conversion to fill the conversion buffer. */
inrows
=
in_rows_avail
-
*
in_row_ctr
;
numrows
=
prep
->
next_buf_stop
-
prep
->
next_buf_row
;
numrows
=
(
int
)
MIN
((
JDIMENSION
)
numrows
,
inrows
);
(
*
cinfo
->
cconvert
->
color_convert
)
(
cinfo
,
input_buf
+
*
in_row_ctr
,
prep
->
color_buf
,
(
JDIMENSION
)
prep
->
next_buf_row
,
numrows
);
/* Pad at top of image, if first time through */
if
(
prep
->
rows_to_go
==
cinfo
->
image_height
)
{
for
(
ci
=
0
;
ci
<
cinfo
->
num_components
;
ci
++
)
{
int
row
;
for
(
row
=
1
;
row
<=
cinfo
->
max_v_samp_factor
;
row
++
)
{
jcopy_sample_rows
(
prep
->
color_buf
[
ci
],
0
,
prep
->
color_buf
[
ci
],
-
row
,
1
,
cinfo
->
image_width
);
}
}
}
*
in_row_ctr
+=
numrows
;
prep
->
next_buf_row
+=
numrows
;
prep
->
rows_to_go
-=
numrows
;
}
else
{
/* Return for more data, unless we are at the bottom of the image. */
if
(
prep
->
rows_to_go
!=
0
)
break
;
/* When at bottom of image, pad to fill the conversion buffer. */
if
(
prep
->
next_buf_row
<
prep
->
next_buf_stop
)
{
for
(
ci
=
0
;
ci
<
cinfo
->
num_components
;
ci
++
)
{
expand_bottom_edge
(
prep
->
color_buf
[
ci
],
cinfo
->
image_width
,
prep
->
next_buf_row
,
prep
->
next_buf_stop
);
}
prep
->
next_buf_row
=
prep
->
next_buf_stop
;
}
}
/* If we've gotten enough data, downsample a row group. */
if
(
prep
->
next_buf_row
==
prep
->
next_buf_stop
)
{
(
*
cinfo
->
downsample
->
downsample
)
(
cinfo
,
prep
->
color_buf
,
(
JDIMENSION
)
prep
->
this_row_group
,
output_buf
,
*
out_row_group_ctr
);
(
*
out_row_group_ctr
)
++
;
/* Advance pointers with wraparound as necessary. */
prep
->
this_row_group
+=
cinfo
->
max_v_samp_factor
;
if
(
prep
->
this_row_group
>=
buf_height
)
prep
->
this_row_group
=
0
;
if
(
prep
->
next_buf_row
>=
buf_height
)
prep
->
next_buf_row
=
0
;
prep
->
next_buf_stop
=
prep
->
next_buf_row
+
cinfo
->
max_v_samp_factor
;
}
}
}
/*
* Create the wrapped-around downsampling input buffer needed for context mode.
*/
LOCAL
(
void
)
create_context_buffer
(
j_compress_ptr
cinfo
)
{
my_prep_ptr
prep
=
(
my_prep_ptr
)
cinfo
->
prep
;
int
rgroup_height
=
cinfo
->
max_v_samp_factor
;
int
ci
,
i
;
jpeg_component_info
*
compptr
;
JSAMPARRAY
true_buffer
,
fake_buffer
;
/* Grab enough space for fake row pointers for all the components;
* we need five row groups' worth of pointers for each component.
*/
fake_buffer
=
(
JSAMPARRAY
)
(
*
cinfo
->
mem
->
alloc_small
)
((
j_common_ptr
)
cinfo
,
JPOOL_IMAGE
,
(
cinfo
->
num_components
*
5
*
rgroup_height
)
*
SIZEOF
(
JSAMPROW
));
for
(
ci
=
0
,
compptr
=
cinfo
->
comp_info
;
ci
<
cinfo
->
num_components
;
ci
++
,
compptr
++
)
{
/* Allocate the actual buffer space (3 row groups) for this component.
* We make the buffer wide enough to allow the downsampler to edge-expand
* horizontally within the buffer, if it so chooses.
*/
true_buffer
=
(
*
cinfo
->
mem
->
alloc_sarray
)
((
j_common_ptr
)
cinfo
,
JPOOL_IMAGE
,
(
JDIMENSION
)
(((
long
)
compptr
->
width_in_blocks
*
DCTSIZE
*
cinfo
->
max_h_samp_factor
)
/
compptr
->
h_samp_factor
),
(
JDIMENSION
)
(
3
*
rgroup_height
));
/* Copy true buffer row pointers into the middle of the fake row array */
MEMCOPY
(
fake_buffer
+
rgroup_height
,
true_buffer
,
3
*
rgroup_height
*
SIZEOF
(
JSAMPROW
));
/* Fill in the above and below wraparound pointers */
for
(
i
=
0
;
i
<
rgroup_height
;
i
++
)
{
fake_buffer
[
i
]
=
true_buffer
[
2
*
rgroup_height
+
i
];
fake_buffer
[
4
*
rgroup_height
+
i
]
=
true_buffer
[
i
];
}
prep
->
color_buf
[
ci
]
=
fake_buffer
+
rgroup_height
;
fake_buffer
+=
5
*
rgroup_height
;
/* point to space for next component */
}
}
#endif
/* CONTEXT_ROWS_SUPPORTED */
/*
* Initialize preprocessing controller.
*/
GLOBAL
(
void
)
jinit_c_prep_controller
(
j_compress_ptr
cinfo
,
int
need_full_buffer
)
{
my_prep_ptr
prep
;
int
ci
;
jpeg_component_info
*
compptr
;
if
(
need_full_buffer
)
/* safety check */
ERREXIT
(
cinfo
,
JERR_BAD_BUFFER_MODE
);
prep
=
(
my_prep_ptr
)
(
*
cinfo
->
mem
->
alloc_small
)
((
j_common_ptr
)
cinfo
,
JPOOL_IMAGE
,
SIZEOF
(
my_prep_controller
));
cinfo
->
prep
=
(
struct
jpeg_c_prep_controller
*
)
prep
;
prep
->
pub
.
start_pass
=
start_pass_prep
;
/* Allocate the color conversion buffer.
* We make the buffer wide enough to allow the downsampler to edge-expand
* horizontally within the buffer, if it so chooses.
*/
if
(
cinfo
->
downsample
->
need_context_rows
)
{
/* Set up to provide context rows */
#ifdef CONTEXT_ROWS_SUPPORTED
prep
->
pub
.
pre_process_data
=
pre_process_context
;
create_context_buffer
(
cinfo
);
#else
ERREXIT
(
cinfo
,
JERR_NOT_COMPILED
);
#endif
}
else
{
/* No context, just make it tall enough for one row group */
prep
->
pub
.
pre_process_data
=
pre_process_data
;
for
(
ci
=
0
,
compptr
=
cinfo
->
comp_info
;
ci
<
cinfo
->
num_components
;
ci
++
,
compptr
++
)
{
prep
->
color_buf
[
ci
]
=
(
*
cinfo
->
mem
->
alloc_sarray
)
((
j_common_ptr
)
cinfo
,
JPOOL_IMAGE
,
(
JDIMENSION
)
(((
long
)
compptr
->
width_in_blocks
*
DCTSIZE
*
cinfo
->
max_h_samp_factor
)
/
compptr
->
h_samp_factor
),
(
JDIMENSION
)
cinfo
->
max_v_samp_factor
);
}
}
}
dlib/external/libjpeg/jcsample.cpp
0 → 100644
View file @
747088ea
/*
* jcsample.c
*
* Copyright (C) 1991-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains downsampling routines.
*
* Downsampling input data is counted in "row groups". A row group
* is defined to be max_v_samp_factor pixel rows of each component,
* from which the downsampler produces v_samp_factor sample rows.
* A single row group is processed in each call to the downsampler module.
*
* The downsampler is responsible for edge-expansion of its output data
* to fill an integral number of DCT blocks horizontally. The source buffer
* may be modified if it is helpful for this purpose (the source buffer is
* allocated wide enough to correspond to the desired output width).
* The caller (the prep controller) is responsible for vertical padding.
*
* The downsampler may request "context rows" by setting need_context_rows
* during startup. In this case, the input arrays will contain at least
* one row group's worth of pixels above and below the passed-in data;
* the caller will create dummy rows at image top and bottom by replicating
* the first or last real pixel row.
*
* An excellent reference for image resampling is
* Digital Image Warping, George Wolberg, 1990.
* Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
*
* The downsampling algorithm used here is a simple average of the source
* pixels covered by the output pixel. The hi-falutin sampling literature
* refers to this as a "box filter". In general the characteristics of a box
* filter are not very good, but for the specific cases we normally use (1:1
* and 2:1 ratios) the box is equivalent to a "triangle filter" which is not
* nearly so bad. If you intend to use other sampling ratios, you'd be well
* advised to improve this code.
*
* A simple input-smoothing capability is provided. This is mainly intended
* for cleaning up color-dithered GIF input files (if you find it inadequate,
* we suggest using an external filtering program such as pnmconvol). When
* enabled, each input pixel P is replaced by a weighted sum of itself and its
* eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF,
* where SF = (smoothing_factor / 1024).
* Currently, smoothing is only supported for 2h2v sampling factors.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/* Pointer to routine to downsample a single component */
typedef
JMETHOD
(
void
,
downsample1_ptr
,
(
j_compress_ptr
cinfo
,
jpeg_component_info
*
compptr
,
JSAMPARRAY
input_data
,
JSAMPARRAY
output_data
));
/* Private subobject */
typedef
struct
{
struct
jpeg_downsampler
pub
;
/* public fields */
/* Downsampling method pointers, one per component */
downsample1_ptr
methods
[
MAX_COMPONENTS
];
}
my_downsampler
;
typedef
my_downsampler
*
my_downsample_ptr
;
/*
* Initialize for a downsampling pass.
*/
METHODDEF
(
void
)
start_pass_downsample
(
j_compress_ptr
cinfo
)
{
/* no work for now */
}
/*
* Expand a component horizontally from width input_cols to width output_cols,
* by duplicating the rightmost samples.
*/
LOCAL
(
void
)
expand_right_edge
(
JSAMPARRAY
image_data
,
int
num_rows
,
JDIMENSION
input_cols
,
JDIMENSION
output_cols
)
{
register
JSAMPROW
ptr
;
register
JSAMPLE
pixval
;
register
int
count
;
int
row
;
int
numcols
=
(
int
)
(
output_cols
-
input_cols
);
if
(
numcols
>
0
)
{
for
(
row
=
0
;
row
<
num_rows
;
row
++
)
{
ptr
=
image_data
[
row
]
+
input_cols
;
pixval
=
ptr
[
-
1
];
/* don't need GETJSAMPLE() here */
for
(
count
=
numcols
;
count
>
0
;
count
--
)
*
ptr
++
=
pixval
;
}
}
}
/*
* Do downsampling for a whole row group (all components).
*
* In this version we simply downsample each component independently.
*/
METHODDEF
(
void
)
sep_downsample
(
j_compress_ptr
cinfo
,
JSAMPIMAGE
input_buf
,
JDIMENSION
in_row_index
,
JSAMPIMAGE
output_buf
,
JDIMENSION
out_row_group_index
)
{
my_downsample_ptr
downsample
=
(
my_downsample_ptr
)
cinfo
->
downsample
;
int
ci
;
jpeg_component_info
*
compptr
;
JSAMPARRAY
in_ptr
,
out_ptr
;
for
(
ci
=
0
,
compptr
=
cinfo
->
comp_info
;
ci
<
cinfo
->
num_components
;
ci
++
,
compptr
++
)
{
in_ptr
=
input_buf
[
ci
]
+
in_row_index
;
out_ptr
=
output_buf
[
ci
]
+
(
out_row_group_index
*
compptr
->
v_samp_factor
);
(
*
downsample
->
methods
[
ci
])
(
cinfo
,
compptr
,
in_ptr
,
out_ptr
);
}
}
/*
* Downsample pixel values of a single component.
* One row group is processed per call.
* This version handles arbitrary integral sampling ratios, without smoothing.
* Note that this version is not actually used for customary sampling ratios.
*/
METHODDEF
(
void
)
int_downsample
(
j_compress_ptr
cinfo
,
jpeg_component_info
*
compptr
,
JSAMPARRAY
input_data
,
JSAMPARRAY
output_data
)
{
int
inrow
,
outrow
,
h_expand
,
v_expand
,
numpix
,
numpix2
,
h
,
v
;
JDIMENSION
outcol
,
outcol_h
;
/* outcol_h == outcol*h_expand */
JDIMENSION
output_cols
=
compptr
->
width_in_blocks
*
DCTSIZE
;
JSAMPROW
inptr
,
outptr
;
long
outvalue
;
h_expand
=
cinfo
->
max_h_samp_factor
/
compptr
->
h_samp_factor
;
v_expand
=
cinfo
->
max_v_samp_factor
/
compptr
->
v_samp_factor
;
numpix
=
h_expand
*
v_expand
;
numpix2
=
numpix
/
2
;
/* Expand input data enough to let all the output samples be generated
* by the standard loop. Special-casing padded output would be more
* efficient.
*/
expand_right_edge
(
input_data
,
cinfo
->
max_v_samp_factor
,
cinfo
->
image_width
,
output_cols
*
h_expand
);
inrow
=
0
;
for
(
outrow
=
0
;
outrow
<
compptr
->
v_samp_factor
;
outrow
++
)
{
outptr
=
output_data
[
outrow
];
for
(
outcol
=
0
,
outcol_h
=
0
;
outcol
<
output_cols
;
outcol
++
,
outcol_h
+=
h_expand
)
{
outvalue
=
0
;
for
(
v
=
0
;
v
<
v_expand
;
v
++
)
{
inptr
=
input_data
[
inrow
+
v
]
+
outcol_h
;
for
(
h
=
0
;
h
<
h_expand
;
h
++
)
{
outvalue
+=
(
long
)
GETJSAMPLE
(
*
inptr
++
);
}
}
*
outptr
++
=
(
JSAMPLE
)
((
outvalue
+
numpix2
)
/
numpix
);
}
inrow
+=
v_expand
;
}
}
/*
* Downsample pixel values of a single component.
* This version handles the special case of a full-size component,
* without smoothing.
*/
METHODDEF
(
void
)
fullsize_downsample
(
j_compress_ptr
cinfo
,
jpeg_component_info
*
compptr
,
JSAMPARRAY
input_data
,
JSAMPARRAY
output_data
)
{
/* Copy the data */
jcopy_sample_rows
(
input_data
,
0
,
output_data
,
0
,
cinfo
->
max_v_samp_factor
,
cinfo
->
image_width
);
/* Edge-expand */
expand_right_edge
(
output_data
,
cinfo
->
max_v_samp_factor
,
cinfo
->
image_width
,
compptr
->
width_in_blocks
*
DCTSIZE
);
}
/*
* Downsample pixel values of a single component.
* This version handles the common case of 2:1 horizontal and 1:1 vertical,
* without smoothing.
*
* A note about the "bias" calculations: when rounding fractional values to
* integer, we do not want to always round 0.5 up to the next integer.
* If we did that, we'd introduce a noticeable bias towards larger values.
* Instead, this code is arranged so that 0.5 will be rounded up or down at
* alternate pixel locations (a simple ordered dither pattern).
*/
METHODDEF
(
void
)
h2v1_downsample
(
j_compress_ptr
cinfo
,
jpeg_component_info
*
compptr
,
JSAMPARRAY
input_data
,
JSAMPARRAY
output_data
)
{
int
outrow
;
JDIMENSION
outcol
;
JDIMENSION
output_cols
=
compptr
->
width_in_blocks
*
DCTSIZE
;
register
JSAMPROW
inptr
,
outptr
;
register
int
bias
;
/* Expand input data enough to let all the output samples be generated
* by the standard loop. Special-casing padded output would be more
* efficient.
*/
expand_right_edge
(
input_data
,
cinfo
->
max_v_samp_factor
,
cinfo
->
image_width
,
output_cols
*
2
);
for
(
outrow
=
0
;
outrow
<
compptr
->
v_samp_factor
;
outrow
++
)
{
outptr
=
output_data
[
outrow
];
inptr
=
input_data
[
outrow
];
bias
=
0
;
/* bias = 0,1,0,1,... for successive samples */
for
(
outcol
=
0
;
outcol
<
output_cols
;
outcol
++
)
{
*
outptr
++
=
(
JSAMPLE
)
((
GETJSAMPLE
(
*
inptr
)
+
GETJSAMPLE
(
inptr
[
1
])
+
bias
)
>>
1
);
bias
^=
1
;
/* 0=>1, 1=>0 */
inptr
+=
2
;
}
}
}
/*
* Downsample pixel values of a single component.
* This version handles the standard case of 2:1 horizontal and 2:1 vertical,
* without smoothing.
*/
METHODDEF
(
void
)
h2v2_downsample
(
j_compress_ptr
cinfo
,
jpeg_component_info
*
compptr
,
JSAMPARRAY
input_data
,
JSAMPARRAY
output_data
)
{
int
inrow
,
outrow
;
JDIMENSION
outcol
;
JDIMENSION
output_cols
=
compptr
->
width_in_blocks
*
DCTSIZE
;
register
JSAMPROW
inptr0
,
inptr1
,
outptr
;
register
int
bias
;
/* Expand input data enough to let all the output samples be generated
* by the standard loop. Special-casing padded output would be more
* efficient.
*/
expand_right_edge
(
input_data
,
cinfo
->
max_v_samp_factor
,
cinfo
->
image_width
,
output_cols
*
2
);
inrow
=
0
;
for
(
outrow
=
0
;
outrow
<
compptr
->
v_samp_factor
;
outrow
++
)
{
outptr
=
output_data
[
outrow
];
inptr0
=
input_data
[
inrow
];
inptr1
=
input_data
[
inrow
+
1
];
bias
=
1
;
/* bias = 1,2,1,2,... for successive samples */
for
(
outcol
=
0
;
outcol
<
output_cols
;
outcol
++
)
{
*
outptr
++
=
(
JSAMPLE
)
((
GETJSAMPLE
(
*
inptr0
)
+
GETJSAMPLE
(
inptr0
[
1
])
+
GETJSAMPLE
(
*
inptr1
)
+
GETJSAMPLE
(
inptr1
[
1
])
+
bias
)
>>
2
);
bias
^=
3
;
/* 1=>2, 2=>1 */
inptr0
+=
2
;
inptr1
+=
2
;
}
inrow
+=
2
;
}
}
#ifdef INPUT_SMOOTHING_SUPPORTED
/*
* Downsample pixel values of a single component.
* This version handles the standard case of 2:1 horizontal and 2:1 vertical,
* with smoothing. One row of context is required.
*/
METHODDEF
(
void
)
h2v2_smooth_downsample
(
j_compress_ptr
cinfo
,
jpeg_component_info
*
compptr
,
JSAMPARRAY
input_data
,
JSAMPARRAY
output_data
)
{
int
inrow
,
outrow
;
JDIMENSION
colctr
;
JDIMENSION
output_cols
=
compptr
->
width_in_blocks
*
DCTSIZE
;
register
JSAMPROW
inptr0
,
inptr1
,
above_ptr
,
below_ptr
,
outptr
;
long
membersum
,
neighsum
,
memberscale
,
neighscale
;
/* Expand input data enough to let all the output samples be generated
* by the standard loop. Special-casing padded output would be more
* efficient.
*/
expand_right_edge
(
input_data
-
1
,
cinfo
->
max_v_samp_factor
+
2
,
cinfo
->
image_width
,
output_cols
*
2
);
/* We don't bother to form the individual "smoothed" input pixel values;
* we can directly compute the output which is the average of the four
* smoothed values. Each of the four member pixels contributes a fraction
* (1-8*SF) to its own smoothed image and a fraction SF to each of the three
* other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final
* output. The four corner-adjacent neighbor pixels contribute a fraction
* SF to just one smoothed pixel, or SF/4 to the final output; while the
* eight edge-adjacent neighbors contribute SF to each of two smoothed
* pixels, or SF/2 overall. In order to use integer arithmetic, these
* factors are scaled by 2^16 = 65536.
* Also recall that SF = smoothing_factor / 1024.
*/
memberscale
=
16384
-
cinfo
->
smoothing_factor
*
80
;
/* scaled (1-5*SF)/4 */
neighscale
=
cinfo
->
smoothing_factor
*
16
;
/* scaled SF/4 */
inrow
=
0
;
for
(
outrow
=
0
;
outrow
<
compptr
->
v_samp_factor
;
outrow
++
)
{
outptr
=
output_data
[
outrow
];
inptr0
=
input_data
[
inrow
];
inptr1
=
input_data
[
inrow
+
1
];
above_ptr
=
input_data
[
inrow
-
1
];
below_ptr
=
input_data
[
inrow
+
2
];
/* Special case for first column: pretend column -1 is same as column 0 */
membersum
=
GETJSAMPLE
(
*
inptr0
)
+
GETJSAMPLE
(
inptr0
[
1
])
+
GETJSAMPLE
(
*
inptr1
)
+
GETJSAMPLE
(
inptr1
[
1
]);
neighsum
=
GETJSAMPLE
(
*
above_ptr
)
+
GETJSAMPLE
(
above_ptr
[
1
])
+
GETJSAMPLE
(
*
below_ptr
)
+
GETJSAMPLE
(
below_ptr
[
1
])
+
GETJSAMPLE
(
*
inptr0
)
+
GETJSAMPLE
(
inptr0
[
2
])
+
GETJSAMPLE
(
*
inptr1
)
+
GETJSAMPLE
(
inptr1
[
2
]);
neighsum
+=
neighsum
;
neighsum
+=
GETJSAMPLE
(
*
above_ptr
)
+
GETJSAMPLE
(
above_ptr
[
2
])
+
GETJSAMPLE
(
*
below_ptr
)
+
GETJSAMPLE
(
below_ptr
[
2
]);
membersum
=
membersum
*
memberscale
+
neighsum
*
neighscale
;
*
outptr
++
=
(
JSAMPLE
)
((
membersum
+
32768
)
>>
16
);
inptr0
+=
2
;
inptr1
+=
2
;
above_ptr
+=
2
;
below_ptr
+=
2
;
for
(
colctr
=
output_cols
-
2
;
colctr
>
0
;
colctr
--
)
{
/* sum of pixels directly mapped to this output element */
membersum
=
GETJSAMPLE
(
*
inptr0
)
+
GETJSAMPLE
(
inptr0
[
1
])
+
GETJSAMPLE
(
*
inptr1
)
+
GETJSAMPLE
(
inptr1
[
1
]);
/* sum of edge-neighbor pixels */
neighsum
=
GETJSAMPLE
(
*
above_ptr
)
+
GETJSAMPLE
(
above_ptr
[
1
])
+
GETJSAMPLE
(
*
below_ptr
)
+
GETJSAMPLE
(
below_ptr
[
1
])
+
GETJSAMPLE
(
inptr0
[
-
1
])
+
GETJSAMPLE
(
inptr0
[
2
])
+
GETJSAMPLE
(
inptr1
[
-
1
])
+
GETJSAMPLE
(
inptr1
[
2
]);
/* The edge-neighbors count twice as much as corner-neighbors */
neighsum
+=
neighsum
;
/* Add in the corner-neighbors */
neighsum
+=
GETJSAMPLE
(
above_ptr
[
-
1
])
+
GETJSAMPLE
(
above_ptr
[
2
])
+
GETJSAMPLE
(
below_ptr
[
-
1
])
+
GETJSAMPLE
(
below_ptr
[
2
]);
/* form final output scaled up by 2^16 */
membersum
=
membersum
*
memberscale
+
neighsum
*
neighscale
;
/* round, descale and output it */
*
outptr
++
=
(
JSAMPLE
)
((
membersum
+
32768
)
>>
16
);
inptr0
+=
2
;
inptr1
+=
2
;
above_ptr
+=
2
;
below_ptr
+=
2
;
}
/* Special case for last column */
membersum
=
GETJSAMPLE
(
*
inptr0
)
+
GETJSAMPLE
(
inptr0
[
1
])
+
GETJSAMPLE
(
*
inptr1
)
+
GETJSAMPLE
(
inptr1
[
1
]);
neighsum
=
GETJSAMPLE
(
*
above_ptr
)
+
GETJSAMPLE
(
above_ptr
[
1
])
+
GETJSAMPLE
(
*
below_ptr
)
+
GETJSAMPLE
(
below_ptr
[
1
])
+
GETJSAMPLE
(
inptr0
[
-
1
])
+
GETJSAMPLE
(
inptr0
[
1
])
+
GETJSAMPLE
(
inptr1
[
-
1
])
+
GETJSAMPLE
(
inptr1
[
1
]);
neighsum
+=
neighsum
;
neighsum
+=
GETJSAMPLE
(
above_ptr
[
-
1
])
+
GETJSAMPLE
(
above_ptr
[
1
])
+
GETJSAMPLE
(
below_ptr
[
-
1
])
+
GETJSAMPLE
(
below_ptr
[
1
]);
membersum
=
membersum
*
memberscale
+
neighsum
*
neighscale
;
*
outptr
=
(
JSAMPLE
)
((
membersum
+
32768
)
>>
16
);
inrow
+=
2
;
}
}
/*
* Downsample pixel values of a single component.
* This version handles the special case of a full-size component,
* with smoothing. One row of context is required.
*/
METHODDEF
(
void
)
fullsize_smooth_downsample
(
j_compress_ptr
cinfo
,
jpeg_component_info
*
compptr
,
JSAMPARRAY
input_data
,
JSAMPARRAY
output_data
)
{
int
outrow
;
JDIMENSION
colctr
;
JDIMENSION
output_cols
=
compptr
->
width_in_blocks
*
DCTSIZE
;
register
JSAMPROW
inptr
,
above_ptr
,
below_ptr
,
outptr
;
long
membersum
,
neighsum
,
memberscale
,
neighscale
;
int
colsum
,
lastcolsum
,
nextcolsum
;
/* Expand input data enough to let all the output samples be generated
* by the standard loop. Special-casing padded output would be more
* efficient.
*/
expand_right_edge
(
input_data
-
1
,
cinfo
->
max_v_samp_factor
+
2
,
cinfo
->
image_width
,
output_cols
);
/* Each of the eight neighbor pixels contributes a fraction SF to the
* smoothed pixel, while the main pixel contributes (1-8*SF). In order
* to use integer arithmetic, these factors are multiplied by 2^16 = 65536.
* Also recall that SF = smoothing_factor / 1024.
*/
memberscale
=
65536L
-
cinfo
->
smoothing_factor
*
512L
;
/* scaled 1-8*SF */
neighscale
=
cinfo
->
smoothing_factor
*
64
;
/* scaled SF */
for
(
outrow
=
0
;
outrow
<
compptr
->
v_samp_factor
;
outrow
++
)
{
outptr
=
output_data
[
outrow
];
inptr
=
input_data
[
outrow
];
above_ptr
=
input_data
[
outrow
-
1
];
below_ptr
=
input_data
[
outrow
+
1
];
/* Special case for first column */
colsum
=
GETJSAMPLE
(
*
above_ptr
++
)
+
GETJSAMPLE
(
*
below_ptr
++
)
+
GETJSAMPLE
(
*
inptr
);
membersum
=
GETJSAMPLE
(
*
inptr
++
);
nextcolsum
=
GETJSAMPLE
(
*
above_ptr
)
+
GETJSAMPLE
(
*
below_ptr
)
+
GETJSAMPLE
(
*
inptr
);
neighsum
=
colsum
+
(
colsum
-
membersum
)
+
nextcolsum
;
membersum
=
membersum
*
memberscale
+
neighsum
*
neighscale
;
*
outptr
++
=
(
JSAMPLE
)
((
membersum
+
32768
)
>>
16
);
lastcolsum
=
colsum
;
colsum
=
nextcolsum
;
for
(
colctr
=
output_cols
-
2
;
colctr
>
0
;
colctr
--
)
{
membersum
=
GETJSAMPLE
(
*
inptr
++
);
above_ptr
++
;
below_ptr
++
;
nextcolsum
=
GETJSAMPLE
(
*
above_ptr
)
+
GETJSAMPLE
(
*
below_ptr
)
+
GETJSAMPLE
(
*
inptr
);
neighsum
=
lastcolsum
+
(
colsum
-
membersum
)
+
nextcolsum
;
membersum
=
membersum
*
memberscale
+
neighsum
*
neighscale
;
*
outptr
++
=
(
JSAMPLE
)
((
membersum
+
32768
)
>>
16
);
lastcolsum
=
colsum
;
colsum
=
nextcolsum
;
}
/* Special case for last column */
membersum
=
GETJSAMPLE
(
*
inptr
);
neighsum
=
lastcolsum
+
(
colsum
-
membersum
)
+
colsum
;
membersum
=
membersum
*
memberscale
+
neighsum
*
neighscale
;
*
outptr
=
(
JSAMPLE
)
((
membersum
+
32768
)
>>
16
);
}
}
#endif
/* INPUT_SMOOTHING_SUPPORTED */
/*
* Module initialization routine for downsampling.
* Note that we must select a routine for each component.
*/
GLOBAL
(
void
)
jinit_downsampler
(
j_compress_ptr
cinfo
)
{
my_downsample_ptr
downsample
;
int
ci
;
jpeg_component_info
*
compptr
;
int
smoothok
=
TRUE
;
downsample
=
(
my_downsample_ptr
)
(
*
cinfo
->
mem
->
alloc_small
)
((
j_common_ptr
)
cinfo
,
JPOOL_IMAGE
,
SIZEOF
(
my_downsampler
));
cinfo
->
downsample
=
(
struct
jpeg_downsampler
*
)
downsample
;
downsample
->
pub
.
start_pass
=
start_pass_downsample
;
downsample
->
pub
.
downsample
=
sep_downsample
;
downsample
->
pub
.
need_context_rows
=
FALSE
;
if
(
cinfo
->
CCIR601_sampling
)
ERREXIT
(
cinfo
,
JERR_CCIR601_NOTIMPL
);
/* Verify we can handle the sampling factors, and set up method pointers */
for
(
ci
=
0
,
compptr
=
cinfo
->
comp_info
;
ci
<
cinfo
->
num_components
;
ci
++
,
compptr
++
)
{
if
(
compptr
->
h_samp_factor
==
cinfo
->
max_h_samp_factor
&&
compptr
->
v_samp_factor
==
cinfo
->
max_v_samp_factor
)
{
#ifdef INPUT_SMOOTHING_SUPPORTED
if
(
cinfo
->
smoothing_factor
)
{
downsample
->
methods
[
ci
]
=
fullsize_smooth_downsample
;
downsample
->
pub
.
need_context_rows
=
TRUE
;
}
else
#endif
downsample
->
methods
[
ci
]
=
fullsize_downsample
;
}
else
if
(
compptr
->
h_samp_factor
*
2
==
cinfo
->
max_h_samp_factor
&&
compptr
->
v_samp_factor
==
cinfo
->
max_v_samp_factor
)
{
smoothok
=
FALSE
;
downsample
->
methods
[
ci
]
=
h2v1_downsample
;
}
else
if
(
compptr
->
h_samp_factor
*
2
==
cinfo
->
max_h_samp_factor
&&
compptr
->
v_samp_factor
*
2
==
cinfo
->
max_v_samp_factor
)
{
#ifdef INPUT_SMOOTHING_SUPPORTED
if
(
cinfo
->
smoothing_factor
)
{
downsample
->
methods
[
ci
]
=
h2v2_smooth_downsample
;
downsample
->
pub
.
need_context_rows
=
TRUE
;
}
else
#endif
downsample
->
methods
[
ci
]
=
h2v2_downsample
;
}
else
if
((
cinfo
->
max_h_samp_factor
%
compptr
->
h_samp_factor
)
==
0
&&
(
cinfo
->
max_v_samp_factor
%
compptr
->
v_samp_factor
)
==
0
)
{
smoothok
=
FALSE
;
downsample
->
methods
[
ci
]
=
int_downsample
;
}
else
ERREXIT
(
cinfo
,
JERR_FRACT_SAMPLE_NOTIMPL
);
}
#ifdef INPUT_SMOOTHING_SUPPORTED
if
(
cinfo
->
smoothing_factor
&&
!
smoothok
)
TRACEMS
(
cinfo
,
0
,
JTRC_SMOOTH_NOTIMPL
);
#endif
}
dlib/external/libjpeg/jdatadst.cpp
0 → 100644
View file @
747088ea
/*
* jdatadst.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains compression data destination routines for the case of
* emitting JPEG data to a file (or any stdio stream). While these routines
* are sufficient for most applications, some will want to use a different
* destination manager.
* IMPORTANT: we assume that fwrite() will correctly transcribe an array of
* JOCTETs into 8-bit-wide elements on external storage. If char is wider
* than 8 bits on your machine, you may need to do some tweaking.
*/
/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
#include "jinclude.h"
#include "jpeglib.h"
#include "jerror.h"
/* Expanded data destination object for stdio output */
typedef
struct
{
struct
jpeg_destination_mgr
pub
;
/* public fields */
FILE
*
outfile
;
/* target stream */
JOCTET
*
buffer
;
/* start of buffer */
}
my_destination_mgr
;
typedef
my_destination_mgr
*
my_dest_ptr
;
#define OUTPUT_BUF_SIZE 4096
/* choose an efficiently fwrite'able size */
/*
* Initialize destination --- called by jpeg_start_compress
* before any data is actually written.
*/
METHODDEF
(
void
)
init_destination
(
j_compress_ptr
cinfo
)
{
my_dest_ptr
dest
=
(
my_dest_ptr
)
cinfo
->
dest
;
/* Allocate the output buffer --- it will be released when done with image */
dest
->
buffer
=
(
JOCTET
*
)
(
*
cinfo
->
mem
->
alloc_small
)
((
j_common_ptr
)
cinfo
,
JPOOL_IMAGE
,
OUTPUT_BUF_SIZE
*
SIZEOF
(
JOCTET
));
dest
->
pub
.
next_output_byte
=
dest
->
buffer
;
dest
->
pub
.
free_in_buffer
=
OUTPUT_BUF_SIZE
;
}
/*
* Empty the output buffer --- called whenever buffer fills up.
*
* In typical applications, this should write the entire output buffer
* (ignoring the current state of next_output_byte & free_in_buffer),
* reset the pointer & count to the start of the buffer, and return TRUE
* indicating that the buffer has been dumped.
*
* In applications that need to be able to suspend compression due to output
* overrun, a FALSE return indicates that the buffer cannot be emptied now.
* In this situation, the compressor will return to its caller (possibly with
* an indication that it has not accepted all the supplied scanlines). The
* application should resume compression after it has made more room in the
* output buffer. Note that there are substantial restrictions on the use of
* suspension --- see the documentation.
*
* When suspending, the compressor will back up to a convenient restart point
* (typically the start of the current MCU). next_output_byte & free_in_buffer
* indicate where the restart point will be if the current call returns FALSE.
* Data beyond this point will be regenerated after resumption, so do not
* write it out when emptying the buffer externally.
*/
METHODDEF
(
int
)
empty_output_buffer
(
j_compress_ptr
cinfo
)
{
my_dest_ptr
dest
=
(
my_dest_ptr
)
cinfo
->
dest
;
if
(
JFWRITE
(
dest
->
outfile
,
dest
->
buffer
,
OUTPUT_BUF_SIZE
)
!=
(
size_t
)
OUTPUT_BUF_SIZE
)
ERREXIT
(
cinfo
,
JERR_FILE_WRITE
);
dest
->
pub
.
next_output_byte
=
dest
->
buffer
;
dest
->
pub
.
free_in_buffer
=
OUTPUT_BUF_SIZE
;
return
TRUE
;
}
/*
* Terminate destination --- called by jpeg_finish_compress
* after all data has been written. Usually needs to flush buffer.
*
* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
* application must deal with any cleanup that should happen even
* for error exit.
*/
METHODDEF
(
void
)
term_destination
(
j_compress_ptr
cinfo
)
{
my_dest_ptr
dest
=
(
my_dest_ptr
)
cinfo
->
dest
;
size_t
datacount
=
OUTPUT_BUF_SIZE
-
dest
->
pub
.
free_in_buffer
;
/* Write any data remaining in the buffer */
if
(
datacount
>
0
)
{
if
(
JFWRITE
(
dest
->
outfile
,
dest
->
buffer
,
datacount
)
!=
datacount
)
ERREXIT
(
cinfo
,
JERR_FILE_WRITE
);
}
fflush
(
dest
->
outfile
);
/* Make sure we wrote the output file OK */
if
(
ferror
(
dest
->
outfile
))
ERREXIT
(
cinfo
,
JERR_FILE_WRITE
);
}
/*
* Prepare for output to a stdio stream.
* The caller must have already opened the stream, and is responsible
* for closing it after finishing compression.
*/
GLOBAL
(
void
)
jpeg_stdio_dest
(
j_compress_ptr
cinfo
,
FILE
*
outfile
)
{
my_dest_ptr
dest
;
/* The destination object is made permanent so that multiple JPEG images
* can be written to the same file without re-executing jpeg_stdio_dest.
* This makes it dangerous to use this manager and a different destination
* manager serially with the same JPEG object, because their private object
* sizes may be different. Caveat programmer.
*/
if
(
cinfo
->
dest
==
NULL
)
{
/* first time for this JPEG object? */
cinfo
->
dest
=
(
struct
jpeg_destination_mgr
*
)
(
*
cinfo
->
mem
->
alloc_small
)
((
j_common_ptr
)
cinfo
,
JPOOL_PERMANENT
,
SIZEOF
(
my_destination_mgr
));
}
dest
=
(
my_dest_ptr
)
cinfo
->
dest
;
dest
->
pub
.
init_destination
=
init_destination
;
dest
->
pub
.
empty_output_buffer
=
empty_output_buffer
;
dest
->
pub
.
term_destination
=
term_destination
;
dest
->
outfile
=
outfile
;
}
dlib/external/libjpeg/jfdctflt.cpp
0 → 100644
View file @
747088ea
/*
* jfdctflt.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains a floating-point implementation of the
* forward DCT (Discrete Cosine Transform).
*
* This implementation should be more accurate than either of the integer
* DCT implementations. However, it may not give the same results on all
* machines because of differences in roundoff behavior. Speed will depend
* on the hardware's floating point capacity.
*
* A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT
* on each column. Direct algorithms are also available, but they are
* much more complex and seem not to be any faster when reduced to code.
*
* This implementation is based on Arai, Agui, and Nakajima's algorithm for
* scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in
* Japanese, but the algorithm is described in the Pennebaker & Mitchell
* JPEG textbook (see REFERENCES section in file README). The following code
* is based directly on figure 4-8 in P&M.
* While an 8-point DCT cannot be done in less than 11 multiplies, it is
* possible to arrange the computation so that many of the multiplies are
* simple scalings of the final outputs. These multiplies can then be
* folded into the multiplications or divisions by the JPEG quantization
* table entries. The AA&N method leaves only 5 multiplies and 29 adds
* to be done in the DCT itself.
* The primary disadvantage of this method is that with a fixed-point
* implementation, accuracy is lost due to imprecise representation of the
* scaled quantization values. However, that problem does not arise if
* we use floating point arithmetic.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jdct.h"
/* Private declarations for DCT subsystem */
#ifdef DCT_FLOAT_SUPPORTED
/*
* This module is specialized to the case DCTSIZE = 8.
*/
#if DCTSIZE != 8
Sorry
,
this
code
only
copes
with
8
x8
DCTs
.
/* deliberate syntax err */
#endif
/*
* Perform the forward DCT on one block of samples.
*/
GLOBAL
(
void
)
jpeg_fdct_float
(
FAST_FLOAT
*
data
)
{
FAST_FLOAT
tmp0
,
tmp1
,
tmp2
,
tmp3
,
tmp4
,
tmp5
,
tmp6
,
tmp7
;
FAST_FLOAT
tmp10
,
tmp11
,
tmp12
,
tmp13
;
FAST_FLOAT
z1
,
z2
,
z3
,
z4
,
z5
,
z11
,
z13
;
FAST_FLOAT
*
dataptr
;
int
ctr
;
/* Pass 1: process rows. */
dataptr
=
data
;
for
(
ctr
=
DCTSIZE
-
1
;
ctr
>=
0
;
ctr
--
)
{
tmp0
=
dataptr
[
0
]
+
dataptr
[
7
];
tmp7
=
dataptr
[
0
]
-
dataptr
[
7
];
tmp1
=
dataptr
[
1
]
+
dataptr
[
6
];
tmp6
=
dataptr
[
1
]
-
dataptr
[
6
];
tmp2
=
dataptr
[
2
]
+
dataptr
[
5
];
tmp5
=
dataptr
[
2
]
-
dataptr
[
5
];
tmp3
=
dataptr
[
3
]
+
dataptr
[
4
];
tmp4
=
dataptr
[
3
]
-
dataptr
[
4
];
/* Even part */
tmp10
=
tmp0
+
tmp3
;
/* phase 2 */
tmp13
=
tmp0
-
tmp3
;
tmp11
=
tmp1
+
tmp2
;
tmp12
=
tmp1
-
tmp2
;
dataptr
[
0
]
=
tmp10
+
tmp11
;
/* phase 3 */
dataptr
[
4
]
=
tmp10
-
tmp11
;
z1
=
(
tmp12
+
tmp13
)
*
((
FAST_FLOAT
)
0.707106781
);
/* c4 */
dataptr
[
2
]
=
tmp13
+
z1
;
/* phase 5 */
dataptr
[
6
]
=
tmp13
-
z1
;
/* Odd part */
tmp10
=
tmp4
+
tmp5
;
/* phase 2 */
tmp11
=
tmp5
+
tmp6
;
tmp12
=
tmp6
+
tmp7
;
/* The rotator is modified from fig 4-8 to avoid extra negations. */
z5
=
(
tmp10
-
tmp12
)
*
((
FAST_FLOAT
)
0.382683433
);
/* c6 */
z2
=
((
FAST_FLOAT
)
0.541196100
)
*
tmp10
+
z5
;
/* c2-c6 */
z4
=
((
FAST_FLOAT
)
1.306562965
)
*
tmp12
+
z5
;
/* c2+c6 */
z3
=
tmp11
*
((
FAST_FLOAT
)
0.707106781
);
/* c4 */
z11
=
tmp7
+
z3
;
/* phase 5 */
z13
=
tmp7
-
z3
;
dataptr
[
5
]
=
z13
+
z2
;
/* phase 6 */
dataptr
[
3
]
=
z13
-
z2
;
dataptr
[
1
]
=
z11
+
z4
;
dataptr
[
7
]
=
z11
-
z4
;
dataptr
+=
DCTSIZE
;
/* advance pointer to next row */
}
/* Pass 2: process columns. */
dataptr
=
data
;
for
(
ctr
=
DCTSIZE
-
1
;
ctr
>=
0
;
ctr
--
)
{
tmp0
=
dataptr
[
DCTSIZE
*
0
]
+
dataptr
[
DCTSIZE
*
7
];
tmp7
=
dataptr
[
DCTSIZE
*
0
]
-
dataptr
[
DCTSIZE
*
7
];
tmp1
=
dataptr
[
DCTSIZE
*
1
]
+
dataptr
[
DCTSIZE
*
6
];
tmp6
=
dataptr
[
DCTSIZE
*
1
]
-
dataptr
[
DCTSIZE
*
6
];
tmp2
=
dataptr
[
DCTSIZE
*
2
]
+
dataptr
[
DCTSIZE
*
5
];
tmp5
=
dataptr
[
DCTSIZE
*
2
]
-
dataptr
[
DCTSIZE
*
5
];
tmp3
=
dataptr
[
DCTSIZE
*
3
]
+
dataptr
[
DCTSIZE
*
4
];
tmp4
=
dataptr
[
DCTSIZE
*
3
]
-
dataptr
[
DCTSIZE
*
4
];
/* Even part */
tmp10
=
tmp0
+
tmp3
;
/* phase 2 */
tmp13
=
tmp0
-
tmp3
;
tmp11
=
tmp1
+
tmp2
;
tmp12
=
tmp1
-
tmp2
;
dataptr
[
DCTSIZE
*
0
]
=
tmp10
+
tmp11
;
/* phase 3 */
dataptr
[
DCTSIZE
*
4
]
=
tmp10
-
tmp11
;
z1
=
(
tmp12
+
tmp13
)
*
((
FAST_FLOAT
)
0.707106781
);
/* c4 */
dataptr
[
DCTSIZE
*
2
]
=
tmp13
+
z1
;
/* phase 5 */
dataptr
[
DCTSIZE
*
6
]
=
tmp13
-
z1
;
/* Odd part */
tmp10
=
tmp4
+
tmp5
;
/* phase 2 */
tmp11
=
tmp5
+
tmp6
;
tmp12
=
tmp6
+
tmp7
;
/* The rotator is modified from fig 4-8 to avoid extra negations. */
z5
=
(
tmp10
-
tmp12
)
*
((
FAST_FLOAT
)
0.382683433
);
/* c6 */
z2
=
((
FAST_FLOAT
)
0.541196100
)
*
tmp10
+
z5
;
/* c2-c6 */
z4
=
((
FAST_FLOAT
)
1.306562965
)
*
tmp12
+
z5
;
/* c2+c6 */
z3
=
tmp11
*
((
FAST_FLOAT
)
0.707106781
);
/* c4 */
z11
=
tmp7
+
z3
;
/* phase 5 */
z13
=
tmp7
-
z3
;
dataptr
[
DCTSIZE
*
5
]
=
z13
+
z2
;
/* phase 6 */
dataptr
[
DCTSIZE
*
3
]
=
z13
-
z2
;
dataptr
[
DCTSIZE
*
1
]
=
z11
+
z4
;
dataptr
[
DCTSIZE
*
7
]
=
z11
-
z4
;
dataptr
++
;
/* advance pointer to next column */
}
}
#endif
/* DCT_FLOAT_SUPPORTED */
dlib/external/libjpeg/jfdctfst.cpp
0 → 100644
View file @
747088ea
/*
* jfdctfst.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains a fast, not so accurate integer implementation of the
* forward DCT (Discrete Cosine Transform).
*
* A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT
* on each column. Direct algorithms are also available, but they are
* much more complex and seem not to be any faster when reduced to code.
*
* This implementation is based on Arai, Agui, and Nakajima's algorithm for
* scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in
* Japanese, but the algorithm is described in the Pennebaker & Mitchell
* JPEG textbook (see REFERENCES section in file README). The following code
* is based directly on figure 4-8 in P&M.
* While an 8-point DCT cannot be done in less than 11 multiplies, it is
* possible to arrange the computation so that many of the multiplies are
* simple scalings of the final outputs. These multiplies can then be
* folded into the multiplications or divisions by the JPEG quantization
* table entries. The AA&N method leaves only 5 multiplies and 29 adds
* to be done in the DCT itself.
* The primary disadvantage of this method is that with fixed-point math,
* accuracy is lost due to imprecise representation of the scaled
* quantization values. The smaller the quantization table entry, the less
* precise the scaled value, so this implementation does worse with high-
* quality-setting files than with low-quality ones.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jdct.h"
/* Private declarations for DCT subsystem */
#ifdef DCT_IFAST_SUPPORTED
/*
* This module is specialized to the case DCTSIZE = 8.
*/
#if DCTSIZE != 8
Sorry
,
this
code
only
copes
with
8
x8
DCTs
.
/* deliberate syntax err */
#endif
/* Scaling decisions are generally the same as in the LL&M algorithm;
* see jfdctint.c for more details. However, we choose to descale
* (right shift) multiplication products as soon as they are formed,
* rather than carrying additional fractional bits into subsequent additions.
* This compromises accuracy slightly, but it lets us save a few shifts.
* More importantly, 16-bit arithmetic is then adequate (for 8-bit samples)
* everywhere except in the multiplications proper; this saves a good deal
* of work on 16-bit-int machines.
*
* Again to save a few shifts, the intermediate results between pass 1 and
* pass 2 are not upscaled, but are represented only to integral precision.
*
* A final compromise is to represent the multiplicative constants to only
* 8 fractional bits, rather than 13. This saves some shifting work on some
* machines, and may also reduce the cost of multiplication (since there
* are fewer one-bits in the constants).
*/
#define CONST_BITS 8
/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
* causing a lot of useless floating-point operations at run time.
* To get around this we use the following pre-calculated constants.
* If you change CONST_BITS you may want to add appropriate values.
* (With a reasonable C compiler, you can just rely on the FIX() macro...)
*/
#if CONST_BITS == 8
#define FIX_0_382683433 ((long) 98)
/* FIX(0.382683433) */
#define FIX_0_541196100 ((long) 139)
/* FIX(0.541196100) */
#define FIX_0_707106781 ((long) 181)
/* FIX(0.707106781) */
#define FIX_1_306562965 ((long) 334)
/* FIX(1.306562965) */
#else
#define FIX_0_382683433 FIX(0.382683433)
#define FIX_0_541196100 FIX(0.541196100)
#define FIX_0_707106781 FIX(0.707106781)
#define FIX_1_306562965 FIX(1.306562965)
#endif
/* We can gain a little more speed, with a further compromise in accuracy,
* by omitting the addition in a descaling shift. This yields an incorrectly
* rounded result half the time...
*/
#ifndef USE_ACCURATE_ROUNDING
#undef DESCALE
#define DESCALE(x,n) RIGHT_SHIFT(x, n)
#endif
/* Multiply a DCTELEM variable by an long constant, and immediately
* descale to yield a DCTELEM result.
*/
#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS))
/*
* Perform the forward DCT on one block of samples.
*/
GLOBAL
(
void
)
jpeg_fdct_ifast
(
DCTELEM
*
data
)
{
DCTELEM
tmp0
,
tmp1
,
tmp2
,
tmp3
,
tmp4
,
tmp5
,
tmp6
,
tmp7
;
DCTELEM
tmp10
,
tmp11
,
tmp12
,
tmp13
;
DCTELEM
z1
,
z2
,
z3
,
z4
,
z5
,
z11
,
z13
;
DCTELEM
*
dataptr
;
int
ctr
;
SHIFT_TEMPS
/* Pass 1: process rows. */
dataptr
=
data
;
for
(
ctr
=
DCTSIZE
-
1
;
ctr
>=
0
;
ctr
--
)
{
tmp0
=
dataptr
[
0
]
+
dataptr
[
7
];
tmp7
=
dataptr
[
0
]
-
dataptr
[
7
];
tmp1
=
dataptr
[
1
]
+
dataptr
[
6
];
tmp6
=
dataptr
[
1
]
-
dataptr
[
6
];
tmp2
=
dataptr
[
2
]
+
dataptr
[
5
];
tmp5
=
dataptr
[
2
]
-
dataptr
[
5
];
tmp3
=
dataptr
[
3
]
+
dataptr
[
4
];
tmp4
=
dataptr
[
3
]
-
dataptr
[
4
];
/* Even part */
tmp10
=
tmp0
+
tmp3
;
/* phase 2 */
tmp13
=
tmp0
-
tmp3
;
tmp11
=
tmp1
+
tmp2
;
tmp12
=
tmp1
-
tmp2
;
dataptr
[
0
]
=
tmp10
+
tmp11
;
/* phase 3 */
dataptr
[
4
]
=
tmp10
-
tmp11
;
z1
=
MULTIPLY
(
tmp12
+
tmp13
,
FIX_0_707106781
);
/* c4 */
dataptr
[
2
]
=
tmp13
+
z1
;
/* phase 5 */
dataptr
[
6
]
=
tmp13
-
z1
;
/* Odd part */
tmp10
=
tmp4
+
tmp5
;
/* phase 2 */
tmp11
=
tmp5
+
tmp6
;
tmp12
=
tmp6
+
tmp7
;
/* The rotator is modified from fig 4-8 to avoid extra negations. */
z5
=
MULTIPLY
(
tmp10
-
tmp12
,
FIX_0_382683433
);
/* c6 */
z2
=
MULTIPLY
(
tmp10
,
FIX_0_541196100
)
+
z5
;
/* c2-c6 */
z4
=
MULTIPLY
(
tmp12
,
FIX_1_306562965
)
+
z5
;
/* c2+c6 */
z3
=
MULTIPLY
(
tmp11
,
FIX_0_707106781
);
/* c4 */
z11
=
tmp7
+
z3
;
/* phase 5 */
z13
=
tmp7
-
z3
;
dataptr
[
5
]
=
z13
+
z2
;
/* phase 6 */
dataptr
[
3
]
=
z13
-
z2
;
dataptr
[
1
]
=
z11
+
z4
;
dataptr
[
7
]
=
z11
-
z4
;
dataptr
+=
DCTSIZE
;
/* advance pointer to next row */
}
/* Pass 2: process columns. */
dataptr
=
data
;
for
(
ctr
=
DCTSIZE
-
1
;
ctr
>=
0
;
ctr
--
)
{
tmp0
=
dataptr
[
DCTSIZE
*
0
]
+
dataptr
[
DCTSIZE
*
7
];
tmp7
=
dataptr
[
DCTSIZE
*
0
]
-
dataptr
[
DCTSIZE
*
7
];
tmp1
=
dataptr
[
DCTSIZE
*
1
]
+
dataptr
[
DCTSIZE
*
6
];
tmp6
=
dataptr
[
DCTSIZE
*
1
]
-
dataptr
[
DCTSIZE
*
6
];
tmp2
=
dataptr
[
DCTSIZE
*
2
]
+
dataptr
[
DCTSIZE
*
5
];
tmp5
=
dataptr
[
DCTSIZE
*
2
]
-
dataptr
[
DCTSIZE
*
5
];
tmp3
=
dataptr
[
DCTSIZE
*
3
]
+
dataptr
[
DCTSIZE
*
4
];
tmp4
=
dataptr
[
DCTSIZE
*
3
]
-
dataptr
[
DCTSIZE
*
4
];
/* Even part */
tmp10
=
tmp0
+
tmp3
;
/* phase 2 */
tmp13
=
tmp0
-
tmp3
;
tmp11
=
tmp1
+
tmp2
;
tmp12
=
tmp1
-
tmp2
;
dataptr
[
DCTSIZE
*
0
]
=
tmp10
+
tmp11
;
/* phase 3 */
dataptr
[
DCTSIZE
*
4
]
=
tmp10
-
tmp11
;
z1
=
MULTIPLY
(
tmp12
+
tmp13
,
FIX_0_707106781
);
/* c4 */
dataptr
[
DCTSIZE
*
2
]
=
tmp13
+
z1
;
/* phase 5 */
dataptr
[
DCTSIZE
*
6
]
=
tmp13
-
z1
;
/* Odd part */
tmp10
=
tmp4
+
tmp5
;
/* phase 2 */
tmp11
=
tmp5
+
tmp6
;
tmp12
=
tmp6
+
tmp7
;
/* The rotator is modified from fig 4-8 to avoid extra negations. */
z5
=
MULTIPLY
(
tmp10
-
tmp12
,
FIX_0_382683433
);
/* c6 */
z2
=
MULTIPLY
(
tmp10
,
FIX_0_541196100
)
+
z5
;
/* c2-c6 */
z4
=
MULTIPLY
(
tmp12
,
FIX_1_306562965
)
+
z5
;
/* c2+c6 */
z3
=
MULTIPLY
(
tmp11
,
FIX_0_707106781
);
/* c4 */
z11
=
tmp7
+
z3
;
/* phase 5 */
z13
=
tmp7
-
z3
;
dataptr
[
DCTSIZE
*
5
]
=
z13
+
z2
;
/* phase 6 */
dataptr
[
DCTSIZE
*
3
]
=
z13
-
z2
;
dataptr
[
DCTSIZE
*
1
]
=
z11
+
z4
;
dataptr
[
DCTSIZE
*
7
]
=
z11
-
z4
;
dataptr
++
;
/* advance pointer to next column */
}
}
#endif
/* DCT_IFAST_SUPPORTED */
dlib/external/libjpeg/jfdctint.cpp
0 → 100644
View file @
747088ea
/*
* jfdctint.c
*
* Copyright (C) 1991-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains a slow-but-accurate integer implementation of the
* forward DCT (Discrete Cosine Transform).
*
* A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT
* on each column. Direct algorithms are also available, but they are
* much more complex and seem not to be any faster when reduced to code.
*
* This implementation is based on an algorithm described in
* C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT
* Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics,
* Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991.
* The primary algorithm described there uses 11 multiplies and 29 adds.
* We use their alternate method with 12 multiplies and 32 adds.
* The advantage of this method is that no data path contains more than one
* multiplication; this allows a very simple and accurate implementation in
* scaled fixed-point arithmetic, with a minimal number of shifts.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jdct.h"
/* Private declarations for DCT subsystem */
#ifdef DCT_ISLOW_SUPPORTED
/*
* This module is specialized to the case DCTSIZE = 8.
*/
#if DCTSIZE != 8
Sorry
,
this
code
only
copes
with
8
x8
DCTs
.
/* deliberate syntax err */
#endif
/*
* The poop on this scaling stuff is as follows:
*
* Each 1-D DCT step produces outputs which are a factor of sqrt(N)
* larger than the true DCT outputs. The final outputs are therefore
* a factor of N larger than desired; since N=8 this can be cured by
* a simple right shift at the end of the algorithm. The advantage of
* this arrangement is that we save two multiplications per 1-D DCT,
* because the y0 and y4 outputs need not be divided by sqrt(N).
* In the IJG code, this factor of 8 is removed by the quantization step
* (in jcdctmgr.c), NOT in this module.
*
* We have to do addition and subtraction of the integer inputs, which
* is no problem, and multiplication by fractional constants, which is
* a problem to do in integer arithmetic. We multiply all the constants
* by CONST_SCALE and convert them to integer constants (thus retaining
* CONST_BITS bits of precision in the constants). After doing a
* multiplication we have to divide the product by CONST_SCALE, with proper
* rounding, to produce the correct output. This division can be done
* cheaply as a right shift of CONST_BITS bits. We postpone shifting
* as long as possible so that partial sums can be added together with
* full fractional precision.
*
* The outputs of the first pass are scaled up by PASS1_BITS bits so that
* they are represented to better-than-integral precision. These outputs
* require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word
* with the recommended scaling. (For 12-bit sample data, the intermediate
* array is long anyway.)
*
* To avoid overflow of the 32-bit intermediate results in pass 2, we must
* have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis
* shows that the values given below are the most effective.
*/
#if BITS_IN_JSAMPLE == 8
#define CONST_BITS 13
#define PASS1_BITS 2
#else
#define CONST_BITS 13
#define PASS1_BITS 1
/* lose a little precision to avoid overflow */
#endif
/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
* causing a lot of useless floating-point operations at run time.
* To get around this we use the following pre-calculated constants.
* If you change CONST_BITS you may want to add appropriate values.
* (With a reasonable C compiler, you can just rely on the FIX() macro...)
*/
#if CONST_BITS == 13
#define FIX_0_298631336 ((long) 2446)
/* FIX(0.298631336) */
#define FIX_0_390180644 ((long) 3196)
/* FIX(0.390180644) */
#define FIX_0_541196100 ((long) 4433)
/* FIX(0.541196100) */
#define FIX_0_765366865 ((long) 6270)
/* FIX(0.765366865) */
#define FIX_0_899976223 ((long) 7373)
/* FIX(0.899976223) */
#define FIX_1_175875602 ((long) 9633)
/* FIX(1.175875602) */
#define FIX_1_501321110 ((long) 12299)
/* FIX(1.501321110) */
#define FIX_1_847759065 ((long) 15137)
/* FIX(1.847759065) */
#define FIX_1_961570560 ((long) 16069)
/* FIX(1.961570560) */
#define FIX_2_053119869 ((long) 16819)
/* FIX(2.053119869) */
#define FIX_2_562915447 ((long) 20995)
/* FIX(2.562915447) */
#define FIX_3_072711026 ((long) 25172)
/* FIX(3.072711026) */
#else
#define FIX_0_298631336 FIX(0.298631336)
#define FIX_0_390180644 FIX(0.390180644)
#define FIX_0_541196100 FIX(0.541196100)
#define FIX_0_765366865 FIX(0.765366865)
#define FIX_0_899976223 FIX(0.899976223)
#define FIX_1_175875602 FIX(1.175875602)
#define FIX_1_501321110 FIX(1.501321110)
#define FIX_1_847759065 FIX(1.847759065)
#define FIX_1_961570560 FIX(1.961570560)
#define FIX_2_053119869 FIX(2.053119869)
#define FIX_2_562915447 FIX(2.562915447)
#define FIX_3_072711026 FIX(3.072711026)
#endif
/* Multiply an long variable by an long constant to yield an long result.
* For 8-bit samples with the recommended scaling, all the variable
* and constant values involved are no more than 16 bits wide, so a
* 16x16->32 bit multiply can be used instead of a full 32x32 multiply.
* For 12-bit samples, a full 32-bit multiplication will be needed.
*/
#if BITS_IN_JSAMPLE == 8
#define MULTIPLY(var,const) MULTIPLY16C16(var,const)
#else
#define MULTIPLY(var,const) ((var) * (const))
#endif
/*
* Perform the forward DCT on one block of samples.
*/
GLOBAL
(
void
)
jpeg_fdct_islow
(
DCTELEM
*
data
)
{
long
tmp0
,
tmp1
,
tmp2
,
tmp3
,
tmp4
,
tmp5
,
tmp6
,
tmp7
;
long
tmp10
,
tmp11
,
tmp12
,
tmp13
;
long
z1
,
z2
,
z3
,
z4
,
z5
;
DCTELEM
*
dataptr
;
int
ctr
;
SHIFT_TEMPS
/* Pass 1: process rows. */
/* Note results are scaled up by sqrt(8) compared to a true DCT; */
/* furthermore, we scale the results by 2**PASS1_BITS. */
dataptr
=
data
;
for
(
ctr
=
DCTSIZE
-
1
;
ctr
>=
0
;
ctr
--
)
{
tmp0
=
dataptr
[
0
]
+
dataptr
[
7
];
tmp7
=
dataptr
[
0
]
-
dataptr
[
7
];
tmp1
=
dataptr
[
1
]
+
dataptr
[
6
];
tmp6
=
dataptr
[
1
]
-
dataptr
[
6
];
tmp2
=
dataptr
[
2
]
+
dataptr
[
5
];
tmp5
=
dataptr
[
2
]
-
dataptr
[
5
];
tmp3
=
dataptr
[
3
]
+
dataptr
[
4
];
tmp4
=
dataptr
[
3
]
-
dataptr
[
4
];
/* Even part per LL&M figure 1 --- note that published figure is faulty;
* rotator "sqrt(2)*c1" should be "sqrt(2)*c6".
*/
tmp10
=
tmp0
+
tmp3
;
tmp13
=
tmp0
-
tmp3
;
tmp11
=
tmp1
+
tmp2
;
tmp12
=
tmp1
-
tmp2
;
dataptr
[
0
]
=
(
DCTELEM
)
((
tmp10
+
tmp11
)
<<
PASS1_BITS
);
dataptr
[
4
]
=
(
DCTELEM
)
((
tmp10
-
tmp11
)
<<
PASS1_BITS
);
z1
=
MULTIPLY
(
tmp12
+
tmp13
,
FIX_0_541196100
);
dataptr
[
2
]
=
(
DCTELEM
)
DESCALE
(
z1
+
MULTIPLY
(
tmp13
,
FIX_0_765366865
),
CONST_BITS
-
PASS1_BITS
);
dataptr
[
6
]
=
(
DCTELEM
)
DESCALE
(
z1
+
MULTIPLY
(
tmp12
,
-
FIX_1_847759065
),
CONST_BITS
-
PASS1_BITS
);
/* Odd part per figure 8 --- note paper omits factor of sqrt(2).
* cK represents cos(K*pi/16).
* i0..i3 in the paper are tmp4..tmp7 here.
*/
z1
=
tmp4
+
tmp7
;
z2
=
tmp5
+
tmp6
;
z3
=
tmp4
+
tmp6
;
z4
=
tmp5
+
tmp7
;
z5
=
MULTIPLY
(
z3
+
z4
,
FIX_1_175875602
);
/* sqrt(2) * c3 */
tmp4
=
MULTIPLY
(
tmp4
,
FIX_0_298631336
);
/* sqrt(2) * (-c1+c3+c5-c7) */
tmp5
=
MULTIPLY
(
tmp5
,
FIX_2_053119869
);
/* sqrt(2) * ( c1+c3-c5+c7) */
tmp6
=
MULTIPLY
(
tmp6
,
FIX_3_072711026
);
/* sqrt(2) * ( c1+c3+c5-c7) */
tmp7
=
MULTIPLY
(
tmp7
,
FIX_1_501321110
);
/* sqrt(2) * ( c1+c3-c5-c7) */
z1
=
MULTIPLY
(
z1
,
-
FIX_0_899976223
);
/* sqrt(2) * (c7-c3) */
z2
=
MULTIPLY
(
z2
,
-
FIX_2_562915447
);
/* sqrt(2) * (-c1-c3) */
z3
=
MULTIPLY
(
z3
,
-
FIX_1_961570560
);
/* sqrt(2) * (-c3-c5) */
z4
=
MULTIPLY
(
z4
,
-
FIX_0_390180644
);
/* sqrt(2) * (c5-c3) */
z3
+=
z5
;
z4
+=
z5
;
dataptr
[
7
]
=
(
DCTELEM
)
DESCALE
(
tmp4
+
z1
+
z3
,
CONST_BITS
-
PASS1_BITS
);
dataptr
[
5
]
=
(
DCTELEM
)
DESCALE
(
tmp5
+
z2
+
z4
,
CONST_BITS
-
PASS1_BITS
);
dataptr
[
3
]
=
(
DCTELEM
)
DESCALE
(
tmp6
+
z2
+
z3
,
CONST_BITS
-
PASS1_BITS
);
dataptr
[
1
]
=
(
DCTELEM
)
DESCALE
(
tmp7
+
z1
+
z4
,
CONST_BITS
-
PASS1_BITS
);
dataptr
+=
DCTSIZE
;
/* advance pointer to next row */
}
/* Pass 2: process columns.
* We remove the PASS1_BITS scaling, but leave the results scaled up
* by an overall factor of 8.
*/
dataptr
=
data
;
for
(
ctr
=
DCTSIZE
-
1
;
ctr
>=
0
;
ctr
--
)
{
tmp0
=
dataptr
[
DCTSIZE
*
0
]
+
dataptr
[
DCTSIZE
*
7
];
tmp7
=
dataptr
[
DCTSIZE
*
0
]
-
dataptr
[
DCTSIZE
*
7
];
tmp1
=
dataptr
[
DCTSIZE
*
1
]
+
dataptr
[
DCTSIZE
*
6
];
tmp6
=
dataptr
[
DCTSIZE
*
1
]
-
dataptr
[
DCTSIZE
*
6
];
tmp2
=
dataptr
[
DCTSIZE
*
2
]
+
dataptr
[
DCTSIZE
*
5
];
tmp5
=
dataptr
[
DCTSIZE
*
2
]
-
dataptr
[
DCTSIZE
*
5
];
tmp3
=
dataptr
[
DCTSIZE
*
3
]
+
dataptr
[
DCTSIZE
*
4
];
tmp4
=
dataptr
[
DCTSIZE
*
3
]
-
dataptr
[
DCTSIZE
*
4
];
/* Even part per LL&M figure 1 --- note that published figure is faulty;
* rotator "sqrt(2)*c1" should be "sqrt(2)*c6".
*/
tmp10
=
tmp0
+
tmp3
;
tmp13
=
tmp0
-
tmp3
;
tmp11
=
tmp1
+
tmp2
;
tmp12
=
tmp1
-
tmp2
;
dataptr
[
DCTSIZE
*
0
]
=
(
DCTELEM
)
DESCALE
(
tmp10
+
tmp11
,
PASS1_BITS
);
dataptr
[
DCTSIZE
*
4
]
=
(
DCTELEM
)
DESCALE
(
tmp10
-
tmp11
,
PASS1_BITS
);
z1
=
MULTIPLY
(
tmp12
+
tmp13
,
FIX_0_541196100
);
dataptr
[
DCTSIZE
*
2
]
=
(
DCTELEM
)
DESCALE
(
z1
+
MULTIPLY
(
tmp13
,
FIX_0_765366865
),
CONST_BITS
+
PASS1_BITS
);
dataptr
[
DCTSIZE
*
6
]
=
(
DCTELEM
)
DESCALE
(
z1
+
MULTIPLY
(
tmp12
,
-
FIX_1_847759065
),
CONST_BITS
+
PASS1_BITS
);
/* Odd part per figure 8 --- note paper omits factor of sqrt(2).
* cK represents cos(K*pi/16).
* i0..i3 in the paper are tmp4..tmp7 here.
*/
z1
=
tmp4
+
tmp7
;
z2
=
tmp5
+
tmp6
;
z3
=
tmp4
+
tmp6
;
z4
=
tmp5
+
tmp7
;
z5
=
MULTIPLY
(
z3
+
z4
,
FIX_1_175875602
);
/* sqrt(2) * c3 */
tmp4
=
MULTIPLY
(
tmp4
,
FIX_0_298631336
);
/* sqrt(2) * (-c1+c3+c5-c7) */
tmp5
=
MULTIPLY
(
tmp5
,
FIX_2_053119869
);
/* sqrt(2) * ( c1+c3-c5+c7) */
tmp6
=
MULTIPLY
(
tmp6
,
FIX_3_072711026
);
/* sqrt(2) * ( c1+c3+c5-c7) */
tmp7
=
MULTIPLY
(
tmp7
,
FIX_1_501321110
);
/* sqrt(2) * ( c1+c3-c5-c7) */
z1
=
MULTIPLY
(
z1
,
-
FIX_0_899976223
);
/* sqrt(2) * (c7-c3) */
z2
=
MULTIPLY
(
z2
,
-
FIX_2_562915447
);
/* sqrt(2) * (-c1-c3) */
z3
=
MULTIPLY
(
z3
,
-
FIX_1_961570560
);
/* sqrt(2) * (-c3-c5) */
z4
=
MULTIPLY
(
z4
,
-
FIX_0_390180644
);
/* sqrt(2) * (c5-c3) */
z3
+=
z5
;
z4
+=
z5
;
dataptr
[
DCTSIZE
*
7
]
=
(
DCTELEM
)
DESCALE
(
tmp4
+
z1
+
z3
,
CONST_BITS
+
PASS1_BITS
);
dataptr
[
DCTSIZE
*
5
]
=
(
DCTELEM
)
DESCALE
(
tmp5
+
z2
+
z4
,
CONST_BITS
+
PASS1_BITS
);
dataptr
[
DCTSIZE
*
3
]
=
(
DCTELEM
)
DESCALE
(
tmp6
+
z2
+
z3
,
CONST_BITS
+
PASS1_BITS
);
dataptr
[
DCTSIZE
*
1
]
=
(
DCTELEM
)
DESCALE
(
tmp7
+
z1
+
z4
,
CONST_BITS
+
PASS1_BITS
);
dataptr
++
;
/* advance pointer to next column */
}
}
#endif
/* DCT_ISLOW_SUPPORTED */
dlib/image_io.h
View file @
747088ea
...
@@ -9,6 +9,7 @@
...
@@ -9,6 +9,7 @@
#include "image_loader/load_image.h"
#include "image_loader/load_image.h"
#include "image_saver/image_saver.h"
#include "image_saver/image_saver.h"
#include "image_saver/save_png.h"
#include "image_saver/save_png.h"
#include "image_saver/save_jpeg.h"
#endif // DLIB_IMAGe_IO_
#endif // DLIB_IMAGe_IO_
dlib/image_saver/save_jpeg.cpp
0 → 100644
View file @
747088ea
// Copyright (C) 2014 Davis E. King (davis@dlib.net), Nils Labugt
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_JPEG_SAVER_CPp_
#define DLIB_JPEG_SAVER_CPp_
// only do anything with this file if DLIB_JPEG_SUPPORT is defined
#ifdef DLIB_JPEG_SUPPORT
#include "../array2d.h"
#include "../pixel.h"
#include "save_jpeg.h"
#include <stdio.h>
#include <jpeglib.h>
#include <sstream>
#include <setjmp.h>
#include "image_saver.h"
namespace
dlib
{
// ----------------------------------------------------------------------------------------
struct
jpeg_saver_error_mgr
{
jpeg_error_mgr
pub
;
/* "public" fields */
jmp_buf
setjmp_buffer
;
/* for return to caller */
};
void
jpeg_saver_error_exit
(
j_common_ptr
cinfo
)
{
/* cinfo->err really points to a jpeg_saver_error_mgr struct, so coerce pointer */
jpeg_saver_error_mgr
*
myerr
=
(
jpeg_saver_error_mgr
*
)
cinfo
->
err
;
/* Return control to the setjmp point */
longjmp
(
myerr
->
setjmp_buffer
,
1
);
}
// ----------------------------------------------------------------------------------------
void
save_jpeg
(
const
array2d
<
rgb_pixel
>&
img
,
const
std
::
string
&
filename
,
int
quality
)
{
FILE
*
outfile
=
fopen
(
filename
.
c_str
(),
"wb"
);
if
(
!
outfile
)
throw
image_save_error
(
"Can't open file "
+
filename
+
" for writing."
);
jpeg_compress_struct
cinfo
;
jpeg_saver_error_mgr
jerr
;
cinfo
.
err
=
jpeg_std_error
(
&
jerr
.
pub
);
jerr
.
pub
.
error_exit
=
jpeg_saver_error_exit
;
/* Establish the setjmp return context for my_error_exit to use. */
if
(
setjmp
(
jerr
.
setjmp_buffer
))
{
/* If we get here, the JPEG code has signaled an error.
* We need to clean up the JPEG object, close the input file, and return.
*/
jpeg_destroy_compress
(
&
cinfo
);
fclose
(
outfile
);
throw
image_save_error
(
"save_jpeg: error while writing "
+
filename
);
}
jpeg_create_compress
(
&
cinfo
);
jpeg_stdio_dest
(
&
cinfo
,
outfile
);
cinfo
.
image_width
=
img
.
nc
();
cinfo
.
image_height
=
img
.
nr
();
cinfo
.
input_components
=
3
;
cinfo
.
in_color_space
=
JCS_RGB
;
jpeg_set_defaults
(
&
cinfo
);
jpeg_set_quality
(
&
cinfo
,
quality
,
true
);
jpeg_start_compress
(
&
cinfo
,
true
);
// now write out the rows one at a time
while
(
cinfo
.
next_scanline
<
cinfo
.
image_height
)
{
JSAMPROW
row_pointer
=
(
JSAMPROW
)
&
img
[
cinfo
.
next_scanline
][
0
];
jpeg_write_scanlines
(
&
cinfo
,
&
row_pointer
,
1
);
}
jpeg_finish_compress
(
&
cinfo
);
jpeg_destroy_compress
(
&
cinfo
);
fclose
(
outfile
);
}
// ----------------------------------------------------------------------------------------
void
save_jpeg
(
const
array2d
<
unsigned
char
>&
img
,
const
std
::
string
&
filename
,
int
quality
)
{
FILE
*
outfile
=
fopen
(
filename
.
c_str
(),
"wb"
);
if
(
!
outfile
)
throw
image_save_error
(
"Can't open file "
+
filename
+
" for writing."
);
jpeg_compress_struct
cinfo
;
jpeg_saver_error_mgr
jerr
;
cinfo
.
err
=
jpeg_std_error
(
&
jerr
.
pub
);
jerr
.
pub
.
error_exit
=
jpeg_saver_error_exit
;
/* Establish the setjmp return context for my_error_exit to use. */
if
(
setjmp
(
jerr
.
setjmp_buffer
))
{
/* If we get here, the JPEG code has signaled an error.
* We need to clean up the JPEG object, close the input file, and return.
*/
jpeg_destroy_compress
(
&
cinfo
);
fclose
(
outfile
);
throw
image_save_error
(
"save_jpeg: error while writing "
+
filename
);
}
jpeg_create_compress
(
&
cinfo
);
jpeg_stdio_dest
(
&
cinfo
,
outfile
);
cinfo
.
image_width
=
img
.
nc
();
cinfo
.
image_height
=
img
.
nr
();
cinfo
.
input_components
=
1
;
cinfo
.
in_color_space
=
JCS_GRAYSCALE
;
jpeg_set_defaults
(
&
cinfo
);
jpeg_set_quality
(
&
cinfo
,
quality
,
true
);
jpeg_start_compress
(
&
cinfo
,
true
);
// now write out the rows one at a time
while
(
cinfo
.
next_scanline
<
cinfo
.
image_height
)
{
JSAMPROW
row_pointer
=
(
JSAMPROW
)
&
img
[
cinfo
.
next_scanline
][
0
];
jpeg_write_scanlines
(
&
cinfo
,
&
row_pointer
,
1
);
}
jpeg_finish_compress
(
&
cinfo
);
jpeg_destroy_compress
(
&
cinfo
);
fclose
(
outfile
);
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_JPEG_SUPPORT
#endif // DLIB_JPEG_SAVER_CPp_
dlib/image_saver/save_jpeg.h
0 → 100644
View file @
747088ea
// Copyright (C) 2014 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_SAVE_JPEG_Hh_
#define DLIB_SAVE_JPEG_Hh_
#include "save_jpeg_abstract.h"
#include "../enable_if.h"
#include "../matrix.h"
#include "../array2d.h"
#include "../pixel.h"
#include "../image_processing/generic_image.h"
#include <string>
namespace
dlib
{
// ----------------------------------------------------------------------------------------
void
save_jpeg
(
const
array2d
<
rgb_pixel
>&
img
,
const
std
::
string
&
filename
,
int
quality
=
75
);
// ----------------------------------------------------------------------------------------
void
save_jpeg
(
const
array2d
<
unsigned
char
>&
img
,
const
std
::
string
&
filename
,
int
quality
=
75
);
// ----------------------------------------------------------------------------------------
template
<
typename
image_type
>
typename
disable_if
<
is_matrix
<
image_type
>
>::
type
save_jpeg
(
const
image_type
&
img
,
const
std
::
string
&
filename
,
int
quality
=
75
)
{
// Convert any kind of grayscale image to an unsigned char image
if
(
pixel_traits
<
typename
image_traits
<
image_type
>::
pixel_type
>::
grayscale
)
{
array2d
<
unsigned
char
>
temp
;
assign_image
(
temp
,
img
);
save_jpeg
(
temp
,
filename
,
quality
);
}
else
{
// This is some other kind of color image so just save it as an RGB image.
array2d
<
rgb_pixel
>
temp
;
assign_image
(
temp
,
img
);
save_jpeg
(
temp
,
filename
,
quality
);
}
}
// ----------------------------------------------------------------------------------------
template
<
typename
EXP
>
void
save_jpeg
(
const
matrix_exp
<
EXP
>&
img
,
const
std
::
string
&
file_name
,
int
quality
=
75
)
{
array2d
<
typename
EXP
::
type
>
temp
;
assign_image
(
temp
,
img
);
save_jpeg
(
temp
,
file_name
,
quality
);
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_SAVE_JPEG_Hh_
dlib/image_saver/save_jpeg_abstract.h
0 → 100644
View file @
747088ea
// Copyright (C) 2014 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_SAVE_JPEG_ABSTRACT_Hh_
#ifdef DLIB_SAVE_JPEG_ABSTRACT_Hh_
#include "../image_processing/generic_image.h"
#include "../pixel.h"
#include <string>
namespace
dlib
{
// ----------------------------------------------------------------------------------------
template
<
typename
image_type
>
void
save_jpeg
(
const
image_type
&
img
,
const
std
::
string
&
filename
,
int
quality
=
75
);
/*!
requires
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or a matrix expression
- image.size() != 0
ensures
- writes the image to the file indicated by file_name in the JPEG format.
- image[0][0] will be in the upper left corner of the image.
- image[image.nr()-1][image.nc()-1] will be in the lower right corner of the
image.
- This routine can save images containing any type of pixel. However,
save_jpeg() can only natively store rgb_pixel and uint8 pixel types. All
other pixel types will be converted into one of these types as appropriate
before being saved to disk.
throws
- image_save_error
This exception is thrown if there is an error that prevents us from saving
the image.
- std::bad_alloc
!*/
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_SAVE_JPEG_ABSTRACT_Hh_
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment