| synopsis || arguments || prev || next |

kdu_codestream::flush

Java: Kdu_codestream::Flush

void flush( kdu_long * layer_bytes, int num_layer_specs, kdu_uint16 * layer_thresholds=NULL, bool trim_to_rate=true, bool record_in_comseg=true, double tolerance=0.0)

Java: void Flush( long[] layer_bytes, int num_layer_specs, int[] layer_thresholds, boolean trim_to_rate, boolean record_in_comseg, double tolerance)

[Declared in "../coresys/common/kdu_compressed.h"]

Go to class description.


Synopsis

In most cases, this is the function you use to actually write out code-stream data once the subband data has been generated and encoded. Starting from version 3.3, this function may be invoked multiple times, in order to generate the code-stream incrementally. This allows you to interleave image data transformation and encoding steps with code-stream flushing, avoiding the need to buffer all compressed data in memory.

The function may be used in two quite different ways:

Normally, num_layer_specs should be identical to the actual number of quality layers to be generated. In this case, every non-zero entry in a layer_bytes array identifies the target maximum number of bytes for the corresponding quality layer and every non-zero entry in a layer_thresholds array identifies a distortion-length slope threshold for the corresponding layer.

It can happen that individual tiles have fewer quality layers. In this case, these tiles participate only in the rate allocation associated with the initial quality layers and they make no contribution to the later (higher rate) layers. If no tiles have num_layer_specs quality layers, the code-stream size will be limited to that specified in the highest layer_bytes entry for which at least one tile has a quality layer.

It can happen that individual tiles have more quality layers than the number of layer specs provided here. Packets associated with all such layers will be written with the "empty header bit" set to 0 — they will thus have the minimum 1 byte representation. These useless packet bytes are taken into account in the rate allocation process, so as to guarantee that the complete code-stream does not exceed the size specified in a final layer spec.

When a layer_bytes array is used to size the quality layers, zero valued entries in this array mean that the rate allocator should attempt to assign roughly logarithmically spaced sizes (or bit-rates) to those quality layers. The logarithmic spacing rule is applied after first subtracting a minimal header offset consisting of the main and tile header bytes, plus 1 byte per packet (3 bytes if EPH markers are being used, 7 bytes if SOP marker segments are being used, and 9 bytes if both SOP and EPH marker segments are being used). Any or all of the entries may be 0. If the last entry is 0, all generated bits will be output by the time the last quality layer is encountered.

If the first entry in the layer_bytes array is 0 and there are multiple layers, the function employs the following reasonable policy to determine suitable rate allocation targets.

If one or more initial layers are assigned non-zero target sizes, but these are followed by further non-final layers which have no explicitly specified target size (0 valued entries in the layer_bytes array), the function adds the appropriate minimum header size to the size specified for all initial non-zero layers. This behaviour allows the user or application to safely specify arbitrarily small bounds for the lowest quality layers and usually mimics most closely the effect an application or user would like to see.

If both the layer_bytes and the layer_thresholds arguments are NULL, the function behaves as though layer_bytes pointed to an array having all zero entries, so that the layer size allocation policy described above will be employed.

As noted at the beginning of this description, the function now supports incremental flushing of the code-stream. What this means is that you can generate some of the compressed data, pushing the code-block bit-streams into the code-stream management machinery using the kdu_subband::open_block and kdu_subband::close_block interfaces, and then call flush to flush as much of the generated data to the attached kdu_compressed_target object as possible. You can then continue generating coded block bit-streams, calling the flush function every so often. This behaviour allows you to minimize the amount of coded data which must be stored internally. While the idea is quite straightforward, there are quite a number of important factors which you should take into account if incremental flushing is to be beneficial to your application:

We conclude this introductory discussion by noting the way in which values are taken in from and returned via any non-NULL layer_bytes and layer_thresholds arrays when the function is invoked one or more times. When the function is first invoked, the mode of operation is determined to be either size driven, or slope driven, depending upon whether or not a layer_thresholds array is supplied having a non-zero first entry. If the layer sized mode of operation is in force, the target layer sizes are copied to an internal array and the same overall layer size targets are used for this and all subsequent calls to the flush function until the code-stream has been entirely flushed; it makes no difference what values are supplied in the layer_bytes array for subsequent flush calls in an incremental flushing sequence. If the explicit slope thresholds mode is in force, the supplied slope thresholds are also copied to an internal array and the same mode is employed for all future calls to this function until the code-stream has been completely flushed. If subsequent calls provide a non-NULL layer_thresholds array, however, the supplied thresholds will replace those stored in the internal array. This allows the application to implement its own rate control loop, adapting the slope thresholds between incremental flush calls so as to achieve some objective.

Regardless of the mode of operation, whenever this function returns it copies into any non-NULL layer_bytes array, the total number of bytes which have actually been written out to the code-stream so far for each specified layer. Similarly, whenever the function returns, it copies into any non-NULL layer_thresholds array, the actual slope threshold used when generating code-stream data for each layer during this call.


Arguments

layer_bytes [kdu_long *]

Array containing num_layer_specs elements to be used either for returning or for explicitly setting the cumulative number of bytes associated with the first k quality layers, for each k from 1 to num_layer_specs. This argument may be NULL, in which case it will be treated as though a layer_bytes array were supplied with all zero entries. See above for a detailed discussion of how the function synthesizes layer size targets where zero valued entries are encountered in a layer_bytes array.

num_layer_specs [int]

Number of elements in any layer_bytes or layer_thresholds arrays. If the function is invoked multiple times to incrementally flush the code-stream, each call must provide exactly the same number of layer specifications.

layer_thresholds [kdu_uint16 *]

If non-NULL, must point to an array with num_layer_specs entries, to be used either for returning or for explicitly setting distortion-length slope thresholds for the quality layers. Determination as to whether or not the layer_thresholds array should be used to explicitly set thresholds for the quality layers is based upon whether or not the first element in the array holds 0 upon entry, when the function is first called, as described more thoroughly above.

trim_to_rate [bool]

This argument is ignored if slope thresholds are being used to control layer formation, instead of target layer sizes, or if this is not the final call to the flush function (as already noted, the function may be called multiple times before the code-stream is completely flushed out). By default, the rate allocation logic performs an additional trimming step when constructing the final (highest rate) quality layer. In this trimming step, the distortion-length slope threshold is selected so as to just exceed the maximum target size and the allocator then works back through the code-blocks, starting from the highest resolution ones, trimming the extra code-bytes which would be included by this excessively small slope threshold, until the rate target is satisfied. If trim_to_rate is set to false, the last layer will be treated in exactly the same way as all the other layers. This can be useful for several reasons: 1) it can improve the execution speed slightly; 2) it ensures that the final distortion-length slopes which are returned via a non-NULL layer_thresholds array can be used in a subsequent compression step (e.g., compressing the same image or a similar image again) without any unexpected surprises.

record_in_comseg [bool]

If true, the rate-distortion slope and the target number of bytes associated with each quality layer will be recorded in a COM (comment) marker segment in the main code-stream header. This can be very useful for applications which wish to process the code-stream later in a manner which depends upon the interpretation of the quality layers. For this reason, you should generally set this argument to true, unless you want to get the smallest possible file size when compressing small images. If the function is called multiple times to effect incremental code-stream flushing, the parameters recorded in the COM marker segment will be extrapolated from the information available when the flush function is first called. The information in this comment is thus generally to be taken more as indicative than absolutely accurate.

tolerance [double]

This argument is ignored unless quality layer generation is being driven by layer sizes, supplied via the layer_bytes array. In this case, it may be used to trade accuracy for speed when determining the distortion-length slopes which achieve the target layer sizes as closely as possible. In particular, the algorithm will finish once it has found a distortion-length slope which yields a size in the range target*(1-tolerance) <= size <= target, where target is the target size for the relevant layer. If no such slope can be found, the layer is assigned a slope such that the size is as close as possible to target, without exceeding it.


| top || synopsis || arguments || prev || next |