jxl
This commit is contained in:
108
main.cpp
108
main.cpp
@@ -1,102 +1,38 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "util/grid2.hpp"
|
||||
#include "util/bmpwriter.hpp"
|
||||
|
||||
// Function to convert hex color string to Vec4
|
||||
Vec4 hexToVec4(const std::string& hex) {
|
||||
if (hex.length() != 6) {
|
||||
return Vec4(0, 0, 0, 1); // Default to black if invalid
|
||||
}
|
||||
|
||||
int r, g, b;
|
||||
sscanf(hex.c_str(), "%02x%02x%02x", &r, &g, &b);
|
||||
|
||||
return Vec4(r / 255.0f, g / 255.0f, b / 255.0f, 1.0f);
|
||||
}
|
||||
#include "util/simple_httpserver.hpp"
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
// Check for gradient flag
|
||||
bool createGradient = false;
|
||||
// Check command line arguments
|
||||
int port = 8080;
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
std::string arg = argv[i];
|
||||
if (arg == "--gradient" || arg == "-g") {
|
||||
createGradient = true;
|
||||
break;
|
||||
if (arg == "--port" || arg == "-p") {
|
||||
if (i + 1 < argc) {
|
||||
port = std::stoi(argv[++i]);
|
||||
}
|
||||
} else if (arg == "--help" || arg == "-h") {
|
||||
std::cout << "Usage: " << argv[0] << " [options]" << std::endl;
|
||||
std::cout << "Options:" << std::endl;
|
||||
std::cout << " -p, --port PORT Set server port (default: 8080)" << std::endl;
|
||||
std::cout << " -h, --help Show this help message" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!createGradient) {
|
||||
std::cout << "Usage: " << argv[0] << " --gradient (-g)" << std::endl;
|
||||
std::cout << "Creates a gradient image with red, green, and blue corners" << std::endl;
|
||||
SimpleHTTPServer server(port);
|
||||
|
||||
if (!server.start()) {
|
||||
std::cerr << "Failed to start server on port " << port << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Create a grid with points arranged in a gradient pattern
|
||||
const int WIDTH = 512;
|
||||
const int HEIGHT = 512;
|
||||
const int POINTS_PER_DIM = 256; // Resolution of the gradient
|
||||
std::cout << "Server running on http://localhost:" << port << std::endl;
|
||||
std::cout << "Open this URL in your web browser to view the dynamic gradient" << std::endl;
|
||||
std::cout << "Press Ctrl+C to stop the server" << std::endl;
|
||||
|
||||
Grid2 grid;
|
||||
|
||||
// Define our target colors at specific positions
|
||||
Vec4 white = hexToVec4("ffffff"); // Top-left corner (1,1)
|
||||
Vec4 red = hexToVec4("ff0000"); // Top-right corner (1,-1)
|
||||
Vec4 green = hexToVec4("00ff00"); // Center (0,0)
|
||||
Vec4 blue = hexToVec4("0000ff"); // Bottom-left corner (-1,-1)
|
||||
Vec4 black = hexToVec4("000000"); // Bottom-right corner (-1,1)
|
||||
|
||||
// Create gradient points
|
||||
for (int y = 0; y < POINTS_PER_DIM; ++y) {
|
||||
for (int x = 0; x < POINTS_PER_DIM; ++x) {
|
||||
// Normalize coordinates to [-1, 1]
|
||||
float nx = (static_cast<float>(x) / (POINTS_PER_DIM - 1)) * 2.0f - 1.0f;
|
||||
float ny = (static_cast<float>(y) / (POINTS_PER_DIM - 1)) * 2.0f - 1.0f;
|
||||
|
||||
// Create position
|
||||
Vec2 pos(nx, ny);
|
||||
|
||||
// Calculate weights for each corner based on distance
|
||||
// We'll use bilinear interpolation
|
||||
|
||||
// Convert to [0,1] range for interpolation
|
||||
float u = (nx + 1.0f) / 2.0f; // maps -1..1 to 0..1
|
||||
float v = (ny + 1.0f) / 2.0f; // maps -1..1 to 0..1
|
||||
|
||||
// For a more natural gradient, we'll interpolate between the four corners
|
||||
// and blend with the center color based on distance from center
|
||||
|
||||
// Bilinear interpolation between corners
|
||||
Vec4 top = white * (1.0f - u) + red * u;
|
||||
Vec4 bottom = blue * (1.0f - u) + black * u;
|
||||
Vec4 cornerColor = top * (1.0f - v) + bottom * v;
|
||||
|
||||
// Calculate distance from center (0,0)
|
||||
float distFromCenter = std::sqrt(nx * nx + ny * ny) / std::sqrt(2.0f); // normalize to [0,1]
|
||||
|
||||
Vec4 color = green * (1.0f - distFromCenter) + cornerColor * distFromCenter;
|
||||
|
||||
grid.addPoint(pos, color);
|
||||
}
|
||||
}
|
||||
|
||||
// Render to RGB image
|
||||
std::vector<uint8_t> imageData = grid.renderToRGB(WIDTH, HEIGHT);
|
||||
|
||||
// Save as BMP
|
||||
if (BMPWriter::saveBMP("output/gradient.bmp", imageData, WIDTH, HEIGHT)) {
|
||||
std::cout << "Gradient image saved as 'gradient.bmp'" << std::endl;
|
||||
std::cout << "Color positions: " << std::endl;
|
||||
std::cout << " Top-left: ffffff (white)" << std::endl;
|
||||
std::cout << " Top-right: ff0000 (red)" << std::endl;
|
||||
std::cout << " Center: 00ff00 (green)" << std::endl;
|
||||
std::cout << " Bottom-left: 0000ff (blue)" << std::endl;
|
||||
std::cout << " Bottom-right: 000000 (black)" << std::endl;
|
||||
} else {
|
||||
std::cerr << "Failed to save gradient image" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
server.handleRequests();
|
||||
|
||||
return 0;
|
||||
}
|
||||
24
util/jxl/cms.h
Normal file
24
util/jxl/cms.h
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) the JPEG XL Project Authors. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef JXL_CMS_H_
|
||||
#define JXL_CMS_H_
|
||||
|
||||
// ICC profiles and color space conversions.
|
||||
|
||||
#include <jxl/cms_interface.h>
|
||||
#include <jxl/jxl_cms_export.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
JXL_CMS_EXPORT const JxlCmsInterface* JxlGetDefaultCms();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // JXL_CMS_H_
|
||||
255
util/jxl/cms_interface.h
Normal file
255
util/jxl/cms_interface.h
Normal file
@@ -0,0 +1,255 @@
|
||||
/* Copyright (c) the JPEG XL Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/** @addtogroup libjxl_color
|
||||
* @{
|
||||
* @file cms_interface.h
|
||||
* @brief Interface to allow the injection of different color management systems
|
||||
* (CMSes, also called color management modules, or CMMs) in JPEG XL.
|
||||
*
|
||||
* A CMS is needed by the JPEG XL encoder and decoder to perform colorspace
|
||||
* conversions. This defines an interface that can be implemented for different
|
||||
* CMSes and then passed to the library.
|
||||
*/
|
||||
|
||||
#ifndef JXL_CMS_INTERFACE_H_
|
||||
#define JXL_CMS_INTERFACE_H_
|
||||
|
||||
#include <jxl/color_encoding.h>
|
||||
#include <jxl/types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Parses an ICC profile and populates @p c and @p cmyk with the data.
|
||||
*
|
||||
* @param user_data @ref JxlCmsInterface::set_fields_data passed as-is.
|
||||
* @param icc_data the ICC data to parse.
|
||||
* @param icc_size how many bytes of icc_data are valid.
|
||||
* @param c a @ref JxlColorEncoding to populate if applicable.
|
||||
* @param cmyk a boolean to set to whether the colorspace is a CMYK colorspace.
|
||||
* @return Whether the relevant fields in @p c were successfully populated.
|
||||
*/
|
||||
typedef JXL_BOOL (*jpegxl_cms_set_fields_from_icc_func)(void* user_data,
|
||||
const uint8_t* icc_data,
|
||||
size_t icc_size,
|
||||
JxlColorEncoding* c,
|
||||
JXL_BOOL* cmyk);
|
||||
|
||||
/** Represents an input or output colorspace to a color transform, as a
|
||||
* serialized ICC profile. */
|
||||
typedef struct {
|
||||
/** The serialized ICC profile. This is guaranteed to be present and valid. */
|
||||
struct {
|
||||
const uint8_t* data;
|
||||
size_t size;
|
||||
} icc;
|
||||
|
||||
/** Structured representation of the colorspace, if applicable. If all fields
|
||||
* are different from their "unknown" value, then this is equivalent to the
|
||||
* ICC representation of the colorspace. If some are "unknown", those that are
|
||||
* not are still valid and can still be used on their own if they are useful.
|
||||
*/
|
||||
JxlColorEncoding color_encoding;
|
||||
|
||||
/** Number of components per pixel. This can be deduced from the other
|
||||
* representations of the colorspace but is provided for convenience and
|
||||
* validation. */
|
||||
size_t num_channels;
|
||||
} JxlColorProfile;
|
||||
|
||||
/** Allocates and returns the data needed for @p num_threads parallel transforms
|
||||
* from the @p input colorspace to @p output, with up to @p pixels_per_thread
|
||||
* pixels to transform per call to @ref JxlCmsInterface::run. @p init_data comes
|
||||
* directly from the @ref JxlCmsInterface instance. Since @c run only receives
|
||||
* the data returned by @c init, a reference to @p init_data should be kept
|
||||
* there if access to it is desired in @c run. Likewise for @ref
|
||||
* JxlCmsInterface::destroy.
|
||||
*
|
||||
* The ICC data in @p input and @p output is guaranteed to outlive the @c init /
|
||||
* @c run / @c destroy cycle.
|
||||
*
|
||||
* @param init_data @ref JxlCmsInterface::init_data passed as-is.
|
||||
* @param num_threads the maximum number of threads from which
|
||||
* @ref JxlCmsInterface::run will be called.
|
||||
* @param pixels_per_thread the maximum number of pixels that each call to
|
||||
* @ref JxlCmsInterface::run will have to transform.
|
||||
* @param input_profile the input colorspace for the transform.
|
||||
* @param output_profile the colorspace to which @ref JxlCmsInterface::run
|
||||
* should convert the input data.
|
||||
* @param intensity_target for colorspaces where luminance is relative
|
||||
* (essentially: not PQ), indicates the luminance at which (1, 1, 1) will
|
||||
* be displayed. This is useful for conversions between PQ and a relative
|
||||
* luminance colorspace, in either direction: @p intensity_target cd/m²
|
||||
* in PQ should map to and from (1, 1, 1) in the relative one.\n
|
||||
* It is also used for conversions to and from HLG, as it is
|
||||
* scene-referred while other colorspaces are assumed to be
|
||||
* display-referred. That is, conversions from HLG should apply the OOTF
|
||||
* for a peak display luminance of @p intensity_target, and conversions
|
||||
* to HLG should undo it. The OOTF is a gamma function applied to the
|
||||
* luminance channel (https://www.itu.int/rec/R-REC-BT.2100-2-201807-I
|
||||
* page 7), with the gamma value computed as
|
||||
* <tt>1.2 * 1.111^log2(intensity_target / 1000)</tt> (footnote 2 page 8
|
||||
* of the same document).
|
||||
* @return The data needed for the transform, or @c NULL in case of failure.
|
||||
* This will be passed to the other functions as @c user_data.
|
||||
*/
|
||||
typedef void* (*jpegxl_cms_init_func)(void* init_data, size_t num_threads,
|
||||
size_t pixels_per_thread,
|
||||
const JxlColorProfile* input_profile,
|
||||
const JxlColorProfile* output_profile,
|
||||
float intensity_target);
|
||||
|
||||
/** Returns a buffer that can be used by callers of the interface to store the
|
||||
* input of the conversion or read its result, if they pass it as the input or
|
||||
* output of the @c run function.
|
||||
* @param user_data the data returned by @c init.
|
||||
* @param thread the index of the thread for which to return a buffer.
|
||||
* @return A buffer that can be used by the caller for passing to @c run.
|
||||
*/
|
||||
typedef float* (*jpegxl_cms_get_buffer_func)(void* user_data, size_t thread);
|
||||
|
||||
/** Executes one transform and returns true on success or false on error. It
|
||||
* must be possible to call this from different threads with different values
|
||||
* for @p thread, all between 0 (inclusive) and the value of @p num_threads
|
||||
* passed to @c init (exclusive). It is allowed to implement this by locking
|
||||
* such that the transforms are essentially performed sequentially, if such a
|
||||
* performance profile is acceptable. @p user_data is the data returned by
|
||||
* @c init.
|
||||
* The buffers each contain @p num_pixels × @c num_channels interleaved floating
|
||||
* point (0..1) samples where @c num_channels is the number of color channels of
|
||||
* their respective color profiles. It is guaranteed that the only case in which
|
||||
* they might overlap is if the output has fewer channels than the input, in
|
||||
* which case the pointers may be identical.
|
||||
* For CMYK data, 0 represents the maximum amount of ink while 1 represents no
|
||||
* ink.
|
||||
* @param user_data the data returned by @c init.
|
||||
* @param thread the index of the thread from which the function is being
|
||||
* called.
|
||||
* @param input_buffer the buffer containing the pixel data to be transformed.
|
||||
* @param output_buffer the buffer receiving the transformed pixel data.
|
||||
* @param num_pixels the number of pixels to transform from @p input to
|
||||
* @p output.
|
||||
* @return ::JXL_TRUE on success, ::JXL_FALSE on failure.
|
||||
*/
|
||||
typedef JXL_BOOL (*jpegxl_cms_run_func)(void* user_data, size_t thread,
|
||||
const float* input_buffer,
|
||||
float* output_buffer,
|
||||
size_t num_pixels);
|
||||
|
||||
/** Performs the necessary clean-up and frees the memory allocated for user
|
||||
* data.
|
||||
*/
|
||||
typedef void (*jpegxl_cms_destroy_func)(void*);
|
||||
|
||||
/**
|
||||
* Interface for performing colorspace transforms. The @c init function can be
|
||||
* called several times to instantiate several transforms, including before
|
||||
* other transforms have been destroyed.
|
||||
*
|
||||
* The call sequence for a given colorspace transform could look like the
|
||||
* following:
|
||||
* @dot
|
||||
* digraph calls {
|
||||
* newrank = true
|
||||
* node [shape = box, fontname = monospace]
|
||||
* init [label = "user_data <- init(\l\
|
||||
* init_data = data,\l\
|
||||
* num_threads = 3,\l\
|
||||
* pixels_per_thread = 20,\l\
|
||||
* input = (sRGB, 3 channels),\l\
|
||||
* output = (Display-P3, 3 channels),\l\
|
||||
* intensity_target = 255\l\
|
||||
* )\l"]
|
||||
* subgraph cluster_0 {
|
||||
* color = lightgrey
|
||||
* label = "thread 1"
|
||||
* labeljust = "c"
|
||||
* run_1_1 [label = "run(\l\
|
||||
* user_data,\l\
|
||||
* thread = 1,\l\
|
||||
* input = in[0],\l\
|
||||
* output = out[0],\l\
|
||||
* num_pixels = 20\l\
|
||||
* )\l"]
|
||||
* run_1_2 [label = "run(\l\
|
||||
* user_data,\l\
|
||||
* thread = 1,\l\
|
||||
* input = in[3],\l\
|
||||
* output = out[3],\l\
|
||||
* num_pixels = 20\l\
|
||||
* )\l"]
|
||||
* }
|
||||
* subgraph cluster_1 {
|
||||
* color = lightgrey
|
||||
* label = "thread 2"
|
||||
* labeljust = "l"
|
||||
* run_2_1 [label = "run(\l\
|
||||
* user_data,\l\
|
||||
* thread = 2,\l\
|
||||
* input = in[1],\l\
|
||||
* output = out[1],\l\
|
||||
* num_pixels = 20\l\
|
||||
* )\l"]
|
||||
* run_2_2 [label = "run(\l\
|
||||
* user_data,\l\
|
||||
* thread = 2,\l\
|
||||
* input = in[4],\l\
|
||||
* output = out[4],\l\
|
||||
* num_pixels = 13\l\
|
||||
* )\l"]
|
||||
* }
|
||||
* subgraph cluster_3 {
|
||||
* color = lightgrey
|
||||
* label = "thread 3"
|
||||
* labeljust = "c"
|
||||
* run_3_1 [label = "run(\l\
|
||||
* user_data,\l\
|
||||
* thread = 3,\l\
|
||||
* input = in[2],\l\
|
||||
* output = out[2],\l\
|
||||
* num_pixels = 20\l\
|
||||
* )\l"]
|
||||
* }
|
||||
* init -> {run_1_1; run_2_1; run_3_1; rank = same}
|
||||
* run_1_1 -> run_1_2
|
||||
* run_2_1 -> run_2_2
|
||||
* {run_1_2; run_2_2, run_3_1} -> "destroy(user_data)"
|
||||
* }
|
||||
* @enddot
|
||||
*/
|
||||
typedef struct {
|
||||
/** CMS-specific data that will be passed to @ref set_fields_from_icc. */
|
||||
void* set_fields_data;
|
||||
/** Populates a @ref JxlColorEncoding from an ICC profile. */
|
||||
jpegxl_cms_set_fields_from_icc_func set_fields_from_icc;
|
||||
|
||||
/** CMS-specific data that will be passed to @ref init. */
|
||||
void* init_data;
|
||||
/** Prepares a colorspace transform as described in the documentation of @ref
|
||||
* jpegxl_cms_init_func. */
|
||||
jpegxl_cms_init_func init;
|
||||
/** Returns a buffer that can be used as input to @c run. */
|
||||
jpegxl_cms_get_buffer_func get_src_buf;
|
||||
/** Returns a buffer that can be used as output from @c run. */
|
||||
jpegxl_cms_get_buffer_func get_dst_buf;
|
||||
/** Executes the transform on a batch of pixels, per @ref jpegxl_cms_run_func.
|
||||
*/
|
||||
jpegxl_cms_run_func run;
|
||||
/** Cleans up the transform. */
|
||||
jpegxl_cms_destroy_func destroy;
|
||||
} JxlCmsInterface;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* JXL_CMS_INTERFACE_H_ */
|
||||
|
||||
/** @} */
|
||||
433
util/jxl/codestream_header.h
Normal file
433
util/jxl/codestream_header.h
Normal file
@@ -0,0 +1,433 @@
|
||||
/* Copyright (c) the JPEG XL Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/** @addtogroup libjxl_metadata
|
||||
* @{
|
||||
* @file codestream_header.h
|
||||
* @brief Definitions of structs and enums for the metadata from the JPEG XL
|
||||
* codestream headers (signature, metadata, preview dimensions, ...), excluding
|
||||
* color encoding which is in color_encoding.h.
|
||||
*/
|
||||
|
||||
#ifndef JXL_CODESTREAM_HEADER_H_
|
||||
#define JXL_CODESTREAM_HEADER_H_
|
||||
|
||||
#include <jxl/types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Image orientation metadata.
|
||||
* Values 1..8 match the EXIF definitions.
|
||||
* The name indicates the operation to perform to transform from the encoded
|
||||
* image to the display image.
|
||||
*/
|
||||
typedef enum {
|
||||
JXL_ORIENT_IDENTITY = 1,
|
||||
JXL_ORIENT_FLIP_HORIZONTAL = 2,
|
||||
JXL_ORIENT_ROTATE_180 = 3,
|
||||
JXL_ORIENT_FLIP_VERTICAL = 4,
|
||||
JXL_ORIENT_TRANSPOSE = 5,
|
||||
JXL_ORIENT_ROTATE_90_CW = 6,
|
||||
JXL_ORIENT_ANTI_TRANSPOSE = 7,
|
||||
JXL_ORIENT_ROTATE_90_CCW = 8,
|
||||
} JxlOrientation;
|
||||
|
||||
/** Given type of an extra channel.
|
||||
*/
|
||||
typedef enum {
|
||||
JXL_CHANNEL_ALPHA,
|
||||
JXL_CHANNEL_DEPTH,
|
||||
JXL_CHANNEL_SPOT_COLOR,
|
||||
JXL_CHANNEL_SELECTION_MASK,
|
||||
JXL_CHANNEL_BLACK,
|
||||
JXL_CHANNEL_CFA,
|
||||
JXL_CHANNEL_THERMAL,
|
||||
JXL_CHANNEL_RESERVED0,
|
||||
JXL_CHANNEL_RESERVED1,
|
||||
JXL_CHANNEL_RESERVED2,
|
||||
JXL_CHANNEL_RESERVED3,
|
||||
JXL_CHANNEL_RESERVED4,
|
||||
JXL_CHANNEL_RESERVED5,
|
||||
JXL_CHANNEL_RESERVED6,
|
||||
JXL_CHANNEL_RESERVED7,
|
||||
JXL_CHANNEL_UNKNOWN,
|
||||
JXL_CHANNEL_OPTIONAL
|
||||
} JxlExtraChannelType;
|
||||
|
||||
/** The codestream preview header */
|
||||
typedef struct {
|
||||
/** Preview width in pixels */
|
||||
uint32_t xsize;
|
||||
|
||||
/** Preview height in pixels */
|
||||
uint32_t ysize;
|
||||
} JxlPreviewHeader;
|
||||
|
||||
/** The codestream animation header, optionally present in the beginning of
|
||||
* the codestream, and if it is it applies to all animation frames, unlike @ref
|
||||
* JxlFrameHeader which applies to an individual frame.
|
||||
*/
|
||||
typedef struct {
|
||||
/** Numerator of ticks per second of a single animation frame time unit */
|
||||
uint32_t tps_numerator;
|
||||
|
||||
/** Denominator of ticks per second of a single animation frame time unit */
|
||||
uint32_t tps_denominator;
|
||||
|
||||
/** Amount of animation loops, or 0 to repeat infinitely */
|
||||
uint32_t num_loops;
|
||||
|
||||
/** Whether animation time codes are present at animation frames in the
|
||||
* codestream */
|
||||
JXL_BOOL have_timecodes;
|
||||
} JxlAnimationHeader;
|
||||
|
||||
/** Basic image information. This information is available from the file
|
||||
* signature and first part of the codestream header.
|
||||
*/
|
||||
typedef struct {
|
||||
/* TODO(lode): need additional fields for (transcoded) JPEG? For reusable
|
||||
* fields orientation must be read from Exif APP1. For has_icc_profile: must
|
||||
* look up where ICC profile is guaranteed to be in a JPEG file to be able to
|
||||
* indicate this. */
|
||||
|
||||
/* TODO(lode): make struct packed, and/or make this opaque struct with getter
|
||||
* functions (still separate struct from opaque decoder) */
|
||||
|
||||
/** Whether the codestream is embedded in the container format. If true,
|
||||
* metadata information and extensions may be available in addition to the
|
||||
* codestream.
|
||||
*/
|
||||
JXL_BOOL have_container;
|
||||
|
||||
/** Width of the image in pixels, before applying orientation.
|
||||
*/
|
||||
uint32_t xsize;
|
||||
|
||||
/** Height of the image in pixels, before applying orientation.
|
||||
*/
|
||||
uint32_t ysize;
|
||||
|
||||
/** Original image color channel bit depth.
|
||||
*/
|
||||
uint32_t bits_per_sample;
|
||||
|
||||
/** Original image color channel floating point exponent bits, or 0 if they
|
||||
* are unsigned integer. For example, if the original data is half-precision
|
||||
* (binary16) floating point, bits_per_sample is 16 and
|
||||
* exponent_bits_per_sample is 5, and so on for other floating point
|
||||
* precisions.
|
||||
*/
|
||||
uint32_t exponent_bits_per_sample;
|
||||
|
||||
/** Upper bound on the intensity level present in the image in nits. For
|
||||
* unsigned integer pixel encodings, this is the brightness of the largest
|
||||
* representable value. The image does not necessarily contain a pixel
|
||||
* actually this bright. An encoder is allowed to set 255 for SDR images
|
||||
* without computing a histogram.
|
||||
* Leaving this set to its default of 0 lets libjxl choose a sensible default
|
||||
* value based on the color encoding.
|
||||
*/
|
||||
float intensity_target;
|
||||
|
||||
/** Lower bound on the intensity level present in the image. This may be
|
||||
* loose, i.e. lower than the actual darkest pixel. When tone mapping, a
|
||||
* decoder will map [min_nits, intensity_target] to the display range.
|
||||
*/
|
||||
float min_nits;
|
||||
|
||||
/** See the description of @see linear_below.
|
||||
*/
|
||||
JXL_BOOL relative_to_max_display;
|
||||
|
||||
/** The tone mapping will leave unchanged (linear mapping) any pixels whose
|
||||
* brightness is strictly below this. The interpretation depends on
|
||||
* relative_to_max_display. If true, this is a ratio [0, 1] of the maximum
|
||||
* display brightness [nits], otherwise an absolute brightness [nits].
|
||||
*/
|
||||
float linear_below;
|
||||
|
||||
/** Whether the data in the codestream is encoded in the original color
|
||||
* profile that is attached to the codestream metadata header, or is
|
||||
* encoded in an internally supported absolute color space (which the decoder
|
||||
* can always convert to linear or non-linear sRGB or to XYB). If the original
|
||||
* profile is used, the decoder outputs pixel data in the color space matching
|
||||
* that profile, but doesn't convert it to any other color space. If the
|
||||
* original profile is not used, the decoder only outputs the data as sRGB
|
||||
* (linear if outputting to floating point, nonlinear with standard sRGB
|
||||
* transfer function if outputting to unsigned integers) but will not convert
|
||||
* it to to the original color profile. The decoder also does not convert to
|
||||
* the target display color profile. To convert the pixel data produced by
|
||||
* the decoder to the original color profile, one of the JxlDecoderGetColor*
|
||||
* functions needs to be called with
|
||||
* ::JXL_COLOR_PROFILE_TARGET_DATA to get the color profile of the decoder
|
||||
* output, and then an external CMS can be used for conversion. Note that for
|
||||
* lossy compression, this should be set to false for most use cases, and if
|
||||
* needed, the image should be converted to the original color profile after
|
||||
* decoding, as described above.
|
||||
*/
|
||||
JXL_BOOL uses_original_profile;
|
||||
|
||||
/** Indicates a preview image exists near the beginning of the codestream.
|
||||
* The preview itself or its dimensions are not included in the basic info.
|
||||
*/
|
||||
JXL_BOOL have_preview;
|
||||
|
||||
/** Indicates animation frames exist in the codestream. The animation
|
||||
* information is not included in the basic info.
|
||||
*/
|
||||
JXL_BOOL have_animation;
|
||||
|
||||
/** Image orientation, value 1-8 matching the values used by JEITA CP-3451C
|
||||
* (Exif version 2.3).
|
||||
*/
|
||||
JxlOrientation orientation;
|
||||
|
||||
/** Number of color channels encoded in the image, this is either 1 for
|
||||
* grayscale data, or 3 for colored data. This count does not include
|
||||
* the alpha channel or other extra channels. To check presence of an alpha
|
||||
* channel, such as in the case of RGBA color, check alpha_bits != 0.
|
||||
* If and only if this is 1, the @ref JxlColorSpace in the @ref
|
||||
* JxlColorEncoding is
|
||||
* ::JXL_COLOR_SPACE_GRAY.
|
||||
*/
|
||||
uint32_t num_color_channels;
|
||||
|
||||
/** Number of additional image channels. This includes the main alpha channel,
|
||||
* but can also include additional channels such as depth, additional alpha
|
||||
* channels, spot colors, and so on. Information about the extra channels
|
||||
* can be queried with @ref JxlDecoderGetExtraChannelInfo. The main alpha
|
||||
* channel, if it exists, also has its information available in the
|
||||
* alpha_bits, alpha_exponent_bits and alpha_premultiplied fields in this @ref
|
||||
* JxlBasicInfo.
|
||||
*/
|
||||
uint32_t num_extra_channels;
|
||||
|
||||
/** Bit depth of the encoded alpha channel, or 0 if there is no alpha channel.
|
||||
* If present, matches the alpha_bits value of the JxlExtraChannelInfo
|
||||
* associated with this alpha channel.
|
||||
*/
|
||||
uint32_t alpha_bits;
|
||||
|
||||
/** Alpha channel floating point exponent bits, or 0 if they are unsigned. If
|
||||
* present, matches the alpha_bits value of the JxlExtraChannelInfo associated
|
||||
* with this alpha channel. integer.
|
||||
*/
|
||||
uint32_t alpha_exponent_bits;
|
||||
|
||||
/** Whether the alpha channel is premultiplied. Only used if there is a main
|
||||
* alpha channel. Matches the alpha_premultiplied value of the
|
||||
* JxlExtraChannelInfo associated with this alpha channel.
|
||||
*/
|
||||
JXL_BOOL alpha_premultiplied;
|
||||
|
||||
/** Dimensions of encoded preview image, only used if have_preview is
|
||||
* JXL_TRUE.
|
||||
*/
|
||||
JxlPreviewHeader preview;
|
||||
|
||||
/** Animation header with global animation properties for all frames, only
|
||||
* used if have_animation is JXL_TRUE.
|
||||
*/
|
||||
JxlAnimationHeader animation;
|
||||
|
||||
/** Intrinsic width of the image.
|
||||
* The intrinsic size can be different from the actual size in pixels
|
||||
* (as given by xsize and ysize) and it denotes the recommended dimensions
|
||||
* for displaying the image, i.e. applications are advised to resample the
|
||||
* decoded image to the intrinsic dimensions.
|
||||
*/
|
||||
uint32_t intrinsic_xsize;
|
||||
|
||||
/** Intrinsic height of the image.
|
||||
* The intrinsic size can be different from the actual size in pixels
|
||||
* (as given by xsize and ysize) and it denotes the recommended dimensions
|
||||
* for displaying the image, i.e. applications are advised to resample the
|
||||
* decoded image to the intrinsic dimensions.
|
||||
*/
|
||||
uint32_t intrinsic_ysize;
|
||||
|
||||
/** Padding for forwards-compatibility, in case more fields are exposed
|
||||
* in a future version of the library.
|
||||
*/
|
||||
uint8_t padding[100];
|
||||
} JxlBasicInfo;
|
||||
|
||||
/** Information for a single extra channel.
|
||||
*/
|
||||
typedef struct {
|
||||
/** Given type of an extra channel.
|
||||
*/
|
||||
JxlExtraChannelType type;
|
||||
|
||||
/** Total bits per sample for this channel.
|
||||
*/
|
||||
uint32_t bits_per_sample;
|
||||
|
||||
/** Floating point exponent bits per channel, or 0 if they are unsigned
|
||||
* integer.
|
||||
*/
|
||||
uint32_t exponent_bits_per_sample;
|
||||
|
||||
/** The exponent the channel is downsampled by on each axis.
|
||||
* TODO(lode): expand this comment to match the JPEG XL specification,
|
||||
* specify how to upscale, how to round the size computation, and to which
|
||||
* extra channels this field applies.
|
||||
*/
|
||||
uint32_t dim_shift;
|
||||
|
||||
/** Length of the extra channel name in bytes, or 0 if no name.
|
||||
* Excludes null termination character.
|
||||
*/
|
||||
uint32_t name_length;
|
||||
|
||||
/** Whether alpha channel uses premultiplied alpha. Only applicable if
|
||||
* type is JXL_CHANNEL_ALPHA.
|
||||
*/
|
||||
JXL_BOOL alpha_premultiplied;
|
||||
|
||||
/** Spot color of the current spot channel in linear RGBA. Only applicable if
|
||||
* type is JXL_CHANNEL_SPOT_COLOR.
|
||||
*/
|
||||
float spot_color[4];
|
||||
|
||||
/** Only applicable if type is JXL_CHANNEL_CFA.
|
||||
* TODO(lode): add comment about the meaning of this field.
|
||||
*/
|
||||
uint32_t cfa_channel;
|
||||
} JxlExtraChannelInfo;
|
||||
|
||||
/* TODO(lode): add API to get the codestream header extensions. */
|
||||
/** Extensions in the codestream header. */
|
||||
typedef struct {
|
||||
/** Extension bits. */
|
||||
uint64_t extensions;
|
||||
} JxlHeaderExtensions;
|
||||
|
||||
/** Frame blend modes.
|
||||
* When decoding, if coalescing is enabled (default), this can be ignored.
|
||||
*/
|
||||
typedef enum {
|
||||
JXL_BLEND_REPLACE = 0,
|
||||
JXL_BLEND_ADD = 1,
|
||||
JXL_BLEND_BLEND = 2,
|
||||
JXL_BLEND_MULADD = 3,
|
||||
JXL_BLEND_MUL = 4,
|
||||
} JxlBlendMode;
|
||||
|
||||
/** The information about blending the color channels or a single extra channel.
|
||||
* When decoding, if coalescing is enabled (default), this can be ignored and
|
||||
* the blend mode is considered to be JXL_BLEND_REPLACE.
|
||||
* When encoding, these settings apply to the pixel data given to the encoder.
|
||||
*/
|
||||
typedef struct {
|
||||
/** Blend mode.
|
||||
*/
|
||||
JxlBlendMode blendmode;
|
||||
/** Reference frame ID to use as the 'bottom' layer (0-3).
|
||||
*/
|
||||
uint32_t source;
|
||||
/** Which extra channel to use as the 'alpha' channel for blend modes
|
||||
* JXL_BLEND_BLEND and JXL_BLEND_MULADD.
|
||||
*/
|
||||
uint32_t alpha;
|
||||
/** Clamp values to [0,1] for the purpose of blending.
|
||||
*/
|
||||
JXL_BOOL clamp;
|
||||
} JxlBlendInfo;
|
||||
|
||||
/** The information about layers.
|
||||
* When decoding, if coalescing is enabled (default), this can be ignored.
|
||||
* When encoding, these settings apply to the pixel data given to the encoder,
|
||||
* the encoder could choose an internal representation that differs.
|
||||
*/
|
||||
typedef struct {
|
||||
/** Whether cropping is applied for this frame. When decoding, if false,
|
||||
* crop_x0 and crop_y0 are set to zero, and xsize and ysize to the main
|
||||
* image dimensions. When encoding and this is false, those fields are
|
||||
* ignored. When decoding, if coalescing is enabled (default), this is always
|
||||
* false, regardless of the internal encoding in the JPEG XL codestream.
|
||||
*/
|
||||
JXL_BOOL have_crop;
|
||||
|
||||
/** Horizontal offset of the frame (can be negative).
|
||||
*/
|
||||
int32_t crop_x0;
|
||||
|
||||
/** Vertical offset of the frame (can be negative).
|
||||
*/
|
||||
int32_t crop_y0;
|
||||
|
||||
/** Width of the frame (number of columns).
|
||||
*/
|
||||
uint32_t xsize;
|
||||
|
||||
/** Height of the frame (number of rows).
|
||||
*/
|
||||
uint32_t ysize;
|
||||
|
||||
/** The blending info for the color channels. Blending info for extra channels
|
||||
* has to be retrieved separately using JxlDecoderGetExtraChannelBlendInfo.
|
||||
*/
|
||||
JxlBlendInfo blend_info;
|
||||
|
||||
/** After blending, save the frame as reference frame with this ID (0-3).
|
||||
* Special case: if the frame duration is nonzero, ID 0 means "will not be
|
||||
* referenced in the future". This value is not used for the last frame.
|
||||
* When encoding, ID 3 is reserved to frames that are generated internally by
|
||||
* the encoder, and should not be used by applications.
|
||||
*/
|
||||
uint32_t save_as_reference;
|
||||
} JxlLayerInfo;
|
||||
|
||||
/** The header of one displayed frame or non-coalesced layer. */
|
||||
typedef struct {
|
||||
/** How long to wait after rendering in ticks. The duration in seconds of a
|
||||
* tick is given by tps_numerator and tps_denominator in @ref
|
||||
* JxlAnimationHeader.
|
||||
*/
|
||||
uint32_t duration;
|
||||
|
||||
/** SMPTE timecode of the current frame in form 0xHHMMSSFF, or 0. The bits are
|
||||
* interpreted from most-significant to least-significant as hour, minute,
|
||||
* second, and frame. If timecode is nonzero, it is strictly larger than that
|
||||
* of a previous frame with nonzero duration. These values are only available
|
||||
* if have_timecodes in @ref JxlAnimationHeader is ::JXL_TRUE.
|
||||
* This value is only used if have_timecodes in @ref JxlAnimationHeader is
|
||||
* ::JXL_TRUE.
|
||||
*/
|
||||
uint32_t timecode;
|
||||
|
||||
/** Length of the frame name in bytes, or 0 if no name.
|
||||
* Excludes null termination character. This value is set by the decoder.
|
||||
* For the encoder, this value is ignored and @ref JxlEncoderSetFrameName is
|
||||
* used instead to set the name and the length.
|
||||
*/
|
||||
uint32_t name_length;
|
||||
|
||||
/** Indicates this is the last animation frame. This value is set by the
|
||||
* decoder to indicate no further frames follow. For the encoder, it is not
|
||||
* required to set this value and it is ignored, @ref JxlEncoderCloseFrames is
|
||||
* used to indicate the last frame to the encoder instead.
|
||||
*/
|
||||
JXL_BOOL is_last;
|
||||
|
||||
/** Information about the layer in case of no coalescing.
|
||||
*/
|
||||
JxlLayerInfo layer_info;
|
||||
} JxlFrameHeader;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* JXL_CODESTREAM_HEADER_H_ */
|
||||
|
||||
/** @}*/
|
||||
161
util/jxl/color_encoding.h
Normal file
161
util/jxl/color_encoding.h
Normal file
@@ -0,0 +1,161 @@
|
||||
/* Copyright (c) the JPEG XL Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/** @addtogroup libjxl_color
|
||||
* @{
|
||||
* @file color_encoding.h
|
||||
* @brief Color Encoding definitions used by JPEG XL.
|
||||
* All CIE units are for the standard 1931 2 degree observer.
|
||||
*/
|
||||
|
||||
#ifndef JXL_COLOR_ENCODING_H_
|
||||
#define JXL_COLOR_ENCODING_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Color space of the image data. */
|
||||
typedef enum {
|
||||
/** Tristimulus RGB */
|
||||
JXL_COLOR_SPACE_RGB,
|
||||
/** Luminance based, the primaries in @ref JxlColorEncoding must be ignored.
|
||||
* This value implies that num_color_channels in @ref JxlBasicInfo is 1, any
|
||||
* other value implies num_color_channels is 3. */
|
||||
JXL_COLOR_SPACE_GRAY,
|
||||
/** XYB (opsin) color space */
|
||||
JXL_COLOR_SPACE_XYB,
|
||||
/** None of the other table entries describe the color space appropriately */
|
||||
JXL_COLOR_SPACE_UNKNOWN,
|
||||
} JxlColorSpace;
|
||||
|
||||
/** Built-in white points for color encoding. When decoding, the numerical xy
|
||||
* white point value can be read from the @ref JxlColorEncoding white_point
|
||||
* field regardless of the enum value. When encoding, enum values except
|
||||
* ::JXL_WHITE_POINT_CUSTOM override the numerical fields. Some enum values
|
||||
* match a subset of CICP (Rec. ITU-T H.273 | ISO/IEC 23091-2:2019(E)), however
|
||||
* the white point and RGB primaries are separate enums here.
|
||||
*/
|
||||
typedef enum {
|
||||
/** CIE Standard Illuminant D65: 0.3127, 0.3290 */
|
||||
JXL_WHITE_POINT_D65 = 1,
|
||||
/** White point must be read from the @ref JxlColorEncoding white_point field,
|
||||
* or as ICC profile. This enum value is not an exact match of the
|
||||
* corresponding CICP value. */
|
||||
JXL_WHITE_POINT_CUSTOM = 2,
|
||||
/** CIE Standard Illuminant E (equal-energy): 1/3, 1/3 */
|
||||
JXL_WHITE_POINT_E = 10,
|
||||
/** DCI-P3 from SMPTE RP 431-2: 0.314, 0.351 */
|
||||
JXL_WHITE_POINT_DCI = 11,
|
||||
} JxlWhitePoint;
|
||||
|
||||
/** Built-in primaries for color encoding. When decoding, the primaries can be
|
||||
* read from the @ref JxlColorEncoding primaries_red_xy, primaries_green_xy and
|
||||
* primaries_blue_xy fields regardless of the enum value. When encoding, the
|
||||
* enum values except ::JXL_PRIMARIES_CUSTOM override the numerical fields.
|
||||
* Some enum values match a subset of CICP (Rec. ITU-T H.273 | ISO/IEC
|
||||
* 23091-2:2019(E)), however the white point and RGB primaries are separate
|
||||
* enums here.
|
||||
*/
|
||||
typedef enum {
|
||||
/** The CIE xy values of the red, green and blue primaries are: 0.639998686,
|
||||
0.330010138; 0.300003784, 0.600003357; 0.150002046, 0.059997204 */
|
||||
JXL_PRIMARIES_SRGB = 1,
|
||||
/** Primaries must be read from the @ref JxlColorEncoding primaries_red_xy,
|
||||
* primaries_green_xy and primaries_blue_xy fields, or as ICC profile. This
|
||||
* enum value is not an exact match of the corresponding CICP value. */
|
||||
JXL_PRIMARIES_CUSTOM = 2,
|
||||
/** As specified in Rec. ITU-R BT.2100-1 */
|
||||
JXL_PRIMARIES_2100 = 9,
|
||||
/** As specified in SMPTE RP 431-2 */
|
||||
JXL_PRIMARIES_P3 = 11,
|
||||
} JxlPrimaries;
|
||||
|
||||
/** Built-in transfer functions for color encoding. Enum values match a subset
|
||||
* of CICP (Rec. ITU-T H.273 | ISO/IEC 23091-2:2019(E)) unless specified
|
||||
* otherwise. */
|
||||
typedef enum {
|
||||
/** As specified in ITU-R BT.709-6 */
|
||||
JXL_TRANSFER_FUNCTION_709 = 1,
|
||||
/** None of the other table entries describe the transfer function. */
|
||||
JXL_TRANSFER_FUNCTION_UNKNOWN = 2,
|
||||
/** The gamma exponent is 1 */
|
||||
JXL_TRANSFER_FUNCTION_LINEAR = 8,
|
||||
/** As specified in IEC 61966-2-1 sRGB */
|
||||
JXL_TRANSFER_FUNCTION_SRGB = 13,
|
||||
/** As specified in SMPTE ST 2084 */
|
||||
JXL_TRANSFER_FUNCTION_PQ = 16,
|
||||
/** As specified in SMPTE ST 428-1 */
|
||||
JXL_TRANSFER_FUNCTION_DCI = 17,
|
||||
/** As specified in Rec. ITU-R BT.2100-1 (HLG) */
|
||||
JXL_TRANSFER_FUNCTION_HLG = 18,
|
||||
/** Transfer function follows power law given by the gamma value in @ref
|
||||
JxlColorEncoding. Not a CICP value. */
|
||||
JXL_TRANSFER_FUNCTION_GAMMA = 65535,
|
||||
} JxlTransferFunction;
|
||||
|
||||
/** Rendering intent for color encoding, as specified in ISO 15076-1:2010 */
|
||||
typedef enum {
|
||||
/** vendor-specific */
|
||||
JXL_RENDERING_INTENT_PERCEPTUAL = 0,
|
||||
/** media-relative */
|
||||
JXL_RENDERING_INTENT_RELATIVE,
|
||||
/** vendor-specific */
|
||||
JXL_RENDERING_INTENT_SATURATION,
|
||||
/** ICC-absolute */
|
||||
JXL_RENDERING_INTENT_ABSOLUTE,
|
||||
} JxlRenderingIntent;
|
||||
|
||||
/** Color encoding of the image as structured information.
|
||||
*/
|
||||
typedef struct {
|
||||
/** Color space of the image data.
|
||||
*/
|
||||
JxlColorSpace color_space;
|
||||
|
||||
/** Built-in white point. If this value is ::JXL_WHITE_POINT_CUSTOM, must
|
||||
* use the numerical white point values from white_point_xy.
|
||||
*/
|
||||
JxlWhitePoint white_point;
|
||||
|
||||
/** Numerical whitepoint values in CIE xy space. */
|
||||
double white_point_xy[2];
|
||||
|
||||
/** Built-in RGB primaries. If this value is ::JXL_PRIMARIES_CUSTOM, must
|
||||
* use the numerical primaries values below. This field and the custom values
|
||||
* below are unused and must be ignored if the color space is
|
||||
* ::JXL_COLOR_SPACE_GRAY or ::JXL_COLOR_SPACE_XYB.
|
||||
*/
|
||||
JxlPrimaries primaries;
|
||||
|
||||
/** Numerical red primary values in CIE xy space. */
|
||||
double primaries_red_xy[2];
|
||||
|
||||
/** Numerical green primary values in CIE xy space. */
|
||||
double primaries_green_xy[2];
|
||||
|
||||
/** Numerical blue primary values in CIE xy space. */
|
||||
double primaries_blue_xy[2];
|
||||
|
||||
/** Transfer function if have_gamma is 0 */
|
||||
JxlTransferFunction transfer_function;
|
||||
|
||||
/** Gamma value used when transfer_function is @ref
|
||||
* JXL_TRANSFER_FUNCTION_GAMMA
|
||||
*/
|
||||
double gamma;
|
||||
|
||||
/** Rendering intent defined for the color profile. */
|
||||
JxlRenderingIntent rendering_intent;
|
||||
} JxlColorEncoding;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* JXL_COLOR_ENCODING_H_ */
|
||||
|
||||
/** @}*/
|
||||
75
util/jxl/compressed_icc.h
Normal file
75
util/jxl/compressed_icc.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/* Copyright (c) the JPEG XL Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/** @addtogroup libjxl_metadata
|
||||
* @{
|
||||
* @file compressed_icc.h
|
||||
* @brief Utility functions to compress and decompress ICC streams.
|
||||
*/
|
||||
|
||||
#ifndef JXL_COMPRESSED_ICC_H_
|
||||
#define JXL_COMPRESSED_ICC_H_
|
||||
|
||||
#include <jxl/jxl_export.h>
|
||||
#include <jxl/memory_manager.h>
|
||||
#include <jxl/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Allocates a buffer using the memory manager, fills it with a compressed
|
||||
* representation of an ICC profile, returns the result through @c output_buffer
|
||||
* and indicates its size through @c output_size.
|
||||
*
|
||||
* The result must be freed using the memory manager once it is not of any more
|
||||
* use.
|
||||
*
|
||||
* @param[in] memory_manager Pointer to a JxlMemoryManager.
|
||||
* @param[in] icc Pointer to a buffer containing the uncompressed ICC profile.
|
||||
* @param[in] icc_size Size of the buffer containing the ICC profile.
|
||||
* @param[out] compressed_icc Will be set to a pointer to the buffer containing
|
||||
* the result.
|
||||
* @param[out] compressed_icc_size Will be set to the size of the buffer
|
||||
* containing the result.
|
||||
* @return Whether compressing the profile was successful.
|
||||
*/
|
||||
JXL_EXPORT JXL_BOOL JxlICCProfileEncode(const JxlMemoryManager* memory_manager,
|
||||
const uint8_t* icc, size_t icc_size,
|
||||
uint8_t** compressed_icc,
|
||||
size_t* compressed_icc_size);
|
||||
|
||||
/**
|
||||
* Allocates a buffer using the memory manager, fills it with the decompressed
|
||||
* version of the ICC profile in @c compressed_icc, returns the result through
|
||||
* @c output_buffer and indicates its size through @c output_size.
|
||||
*
|
||||
* The result must be freed using the memory manager once it is not of any more
|
||||
* use.
|
||||
*
|
||||
* @param[in] memory_manager Pointer to a JxlMemoryManager.
|
||||
* @param[in] compressed_icc Pointer to a buffer containing the compressed ICC
|
||||
* profile.
|
||||
* @param[in] compressed_icc_size Size of the buffer containing the compressed
|
||||
* ICC profile.
|
||||
* @param[out] icc Will be set to a pointer to the buffer containing the result.
|
||||
* @param[out] icc_size Will be set to the size of the buffer containing the
|
||||
* result.
|
||||
* @return Whether decompressing the profile was successful.
|
||||
*/
|
||||
JXL_EXPORT JXL_BOOL JxlICCProfileDecode(const JxlMemoryManager* memory_manager,
|
||||
const uint8_t* compressed_icc,
|
||||
size_t compressed_icc_size,
|
||||
uint8_t** icc, size_t* icc_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* JXL_COMPRESSED_ICC_H_ */
|
||||
|
||||
/** @} */
|
||||
1472
util/jxl/decode.h
Normal file
1472
util/jxl/decode.h
Normal file
File diff suppressed because it is too large
Load Diff
58
util/jxl/decode_cxx.h
Normal file
58
util/jxl/decode_cxx.h
Normal file
@@ -0,0 +1,58 @@
|
||||
// Copyright (c) the JPEG XL Project Authors. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/// @addtogroup libjxl_cpp
|
||||
/// @{
|
||||
///
|
||||
/// @file decode_cxx.h
|
||||
/// @brief C++ header-only helper for @ref decode.h.
|
||||
///
|
||||
/// There's no binary library associated with the header since this is a header
|
||||
/// only library.
|
||||
|
||||
#ifndef JXL_DECODE_CXX_H_
|
||||
#define JXL_DECODE_CXX_H_
|
||||
|
||||
#include <jxl/decode.h>
|
||||
#include <jxl/memory_manager.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#ifndef __cplusplus
|
||||
#error "This a C++ only header. Use jxl/decode.h from C sources."
|
||||
#endif
|
||||
|
||||
/// Struct to call JxlDecoderDestroy from the JxlDecoderPtr unique_ptr.
|
||||
struct JxlDecoderDestroyStruct {
|
||||
/// Calls @ref JxlDecoderDestroy() on the passed decoder.
|
||||
void operator()(JxlDecoder* decoder) { JxlDecoderDestroy(decoder); }
|
||||
};
|
||||
|
||||
/// std::unique_ptr<> type that calls JxlDecoderDestroy() when releasing the
|
||||
/// decoder.
|
||||
///
|
||||
/// Use this helper type from C++ sources to ensure the decoder is destroyed and
|
||||
/// their internal resources released.
|
||||
typedef std::unique_ptr<JxlDecoder, JxlDecoderDestroyStruct> JxlDecoderPtr;
|
||||
|
||||
/// Creates an instance of JxlDecoder into a JxlDecoderPtr and initializes it.
|
||||
///
|
||||
/// This function returns a unique_ptr that will call JxlDecoderDestroy() when
|
||||
/// releasing the pointer. See @ref JxlDecoderCreate for details on the
|
||||
/// instance creation.
|
||||
///
|
||||
/// @param memory_manager custom allocator function. It may be NULL. The memory
|
||||
/// manager will be copied internally.
|
||||
/// @return a @c NULL JxlDecoderPtr if the instance can not be allocated or
|
||||
/// initialized
|
||||
/// @return initialized JxlDecoderPtr instance otherwise.
|
||||
static inline JxlDecoderPtr JxlDecoderMake(
|
||||
const JxlMemoryManager* memory_manager) {
|
||||
return JxlDecoderPtr(JxlDecoderCreate(memory_manager));
|
||||
}
|
||||
|
||||
#endif // JXL_DECODE_CXX_H_
|
||||
|
||||
/// @}
|
||||
1602
util/jxl/encode.h
Normal file
1602
util/jxl/encode.h
Normal file
File diff suppressed because it is too large
Load Diff
58
util/jxl/encode_cxx.h
Normal file
58
util/jxl/encode_cxx.h
Normal file
@@ -0,0 +1,58 @@
|
||||
// Copyright (c) the JPEG XL Project Authors. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/// @addtogroup libjxl_cpp
|
||||
///@{
|
||||
///
|
||||
/// @file encode_cxx.h
|
||||
/// @brief C++ header-only helper for @ref encode.h.
|
||||
///
|
||||
/// There's no binary library associated with the header since this is a header
|
||||
/// only library.
|
||||
|
||||
#ifndef JXL_ENCODE_CXX_H_
|
||||
#define JXL_ENCODE_CXX_H_
|
||||
|
||||
#include <jxl/encode.h>
|
||||
#include <jxl/memory_manager.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#ifndef __cplusplus
|
||||
#error "This a C++ only header. Use jxl/encode.h from C sources."
|
||||
#endif
|
||||
|
||||
/// Struct to call JxlEncoderDestroy from the JxlEncoderPtr unique_ptr.
|
||||
struct JxlEncoderDestroyStruct {
|
||||
/// Calls @ref JxlEncoderDestroy() on the passed encoder.
|
||||
void operator()(JxlEncoder* encoder) { JxlEncoderDestroy(encoder); }
|
||||
};
|
||||
|
||||
/// std::unique_ptr<> type that calls JxlEncoderDestroy() when releasing the
|
||||
/// encoder.
|
||||
///
|
||||
/// Use this helper type from C++ sources to ensure the encoder is destroyed and
|
||||
/// their internal resources released.
|
||||
typedef std::unique_ptr<JxlEncoder, JxlEncoderDestroyStruct> JxlEncoderPtr;
|
||||
|
||||
/// Creates an instance of JxlEncoder into a JxlEncoderPtr and initializes it.
|
||||
///
|
||||
/// This function returns a unique_ptr that will call JxlEncoderDestroy() when
|
||||
/// releasing the pointer. See @ref JxlEncoderCreate for details on the
|
||||
/// instance creation.
|
||||
///
|
||||
/// @param memory_manager custom allocator function. It may be NULL. The memory
|
||||
/// manager will be copied internally.
|
||||
/// @return a @c NULL JxlEncoderPtr if the instance can not be allocated or
|
||||
/// initialized
|
||||
/// @return initialized JxlEncoderPtr instance otherwise.
|
||||
static inline JxlEncoderPtr JxlEncoderMake(
|
||||
const JxlMemoryManager* memory_manager) {
|
||||
return JxlEncoderPtr(JxlEncoderCreate(memory_manager));
|
||||
}
|
||||
|
||||
#endif // JXL_ENCODE_CXX_H_
|
||||
|
||||
/// @}
|
||||
129
util/jxl/gain_map.h
Normal file
129
util/jxl/gain_map.h
Normal file
@@ -0,0 +1,129 @@
|
||||
/* Copyright (c) the JPEG XL Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/** @addtogroup libjxl_metadata
|
||||
* @{
|
||||
* @file gain_map.h
|
||||
* @brief Utility functions to manipulate jhgm (gain map) boxes.
|
||||
*/
|
||||
|
||||
#ifndef JXL_GAIN_MAP_H_
|
||||
#define JXL_GAIN_MAP_H_
|
||||
|
||||
#include <jxl/color_encoding.h>
|
||||
#include <jxl/jxl_export.h>
|
||||
#include <jxl/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Gain map bundle
|
||||
*
|
||||
* This structure is used to serialize gain map data to and from an input
|
||||
* buffer. It holds pointers to sections within the buffer, and different parts
|
||||
* of the gain map data such as metadata, ICC profile data, and the gain map
|
||||
* itself.
|
||||
*
|
||||
* The pointers in this structure do not take ownership of the memory they point
|
||||
* to. Instead, they reference specific locations within the provided buffer. It
|
||||
* is the caller's responsibility to ensure that the buffer remains valid and is
|
||||
* not deallocated as long as these pointers are in use. The structure should be
|
||||
* considered as providing a view into the buffer, not as an owner of the data.
|
||||
*/
|
||||
typedef struct {
|
||||
/** Version number of the gain map bundle. */
|
||||
uint8_t jhgm_version;
|
||||
/** Size of the gain map metadata in bytes. */
|
||||
uint16_t gain_map_metadata_size;
|
||||
/** Pointer to the gain map metadata, which is a binary
|
||||
* blob following ISO 21496-1. This pointer references data within the input
|
||||
* buffer. */
|
||||
const uint8_t* gain_map_metadata;
|
||||
/** Indicates whether a color encoding is present. */
|
||||
JXL_BOOL has_color_encoding;
|
||||
/** If has_color_encoding is true, this field contains the
|
||||
* uncompressed color encoding data. */
|
||||
JxlColorEncoding color_encoding;
|
||||
/** Size of the alternative ICC profile in bytes (compressed
|
||||
* size). */
|
||||
uint32_t alt_icc_size;
|
||||
/** Pointer to the compressed ICC profile. This pointer references
|
||||
* data within the input buffer. */
|
||||
const uint8_t* alt_icc;
|
||||
/** Size of the gain map in bytes. */
|
||||
uint32_t gain_map_size;
|
||||
/** Pointer to the gain map data, which is a JPEG XL naked
|
||||
* codestream. This pointer references data within the input buffer.*/
|
||||
const uint8_t* gain_map;
|
||||
} JxlGainMapBundle;
|
||||
|
||||
/**
|
||||
* Calculates the total size required to serialize the gain map bundle into a
|
||||
* binary buffer. This function accounts for all the necessary space to
|
||||
* serialize fields such as gain map metadata, color encoding, compressed ICC
|
||||
* profile data, and the gain map itself.
|
||||
*
|
||||
* @param[in] map_bundle Pointer to the JxlGainMapBundle containing all
|
||||
* necessary data to compute the size.
|
||||
* @param[out] bundle_size The size in bytes required to serialize the bundle.
|
||||
* @return Whether setting the size was successful.
|
||||
*/
|
||||
JXL_EXPORT JXL_BOOL JxlGainMapGetBundleSize(const JxlGainMapBundle* map_bundle,
|
||||
size_t* bundle_size);
|
||||
|
||||
/**
|
||||
* Serializes the gain map bundle into a preallocated buffer. The function
|
||||
* ensures that all parts of the bundle such as metadata, color encoding,
|
||||
* compressed ICC profile, and the gain map are correctly encoded into the
|
||||
* buffer. First call `JxlGainMapGetBundleSize` to get the size needed for
|
||||
* the buffer.
|
||||
*
|
||||
* @param[in] map_bundle Pointer to the `JxlGainMapBundle` to serialize.
|
||||
* @param[out] output_buffer Pointer to the buffer where the serialized data
|
||||
* will be written.
|
||||
* @param[in] output_buffer_size The size of the output buffer in bytes. Must be
|
||||
* large enough to hold the entire serialized data.
|
||||
* @param[out] bytes_written The number of bytes written to the output buffer.
|
||||
* @return Whether writing the bundle was successful.
|
||||
*/
|
||||
JXL_EXPORT JXL_BOOL JxlGainMapWriteBundle(const JxlGainMapBundle* map_bundle,
|
||||
uint8_t* output_buffer,
|
||||
size_t output_buffer_size,
|
||||
size_t* bytes_written);
|
||||
|
||||
/**
|
||||
* Deserializes a gain map bundle from a provided buffer and populates a
|
||||
* `JxlGainMapBundle` structure with the data extracted. This function assumes
|
||||
* the buffer contains a valid serialized gain map bundle. After successful
|
||||
* execution, the `JxlGainMapBundle` structure will reference three different
|
||||
* sections within the buffer:
|
||||
* - gain_map_metadata
|
||||
* - alt_icc
|
||||
* - gain_map
|
||||
* These sections will be accompanied by their respective sizes. Users must
|
||||
* ensure that the buffer remains valid as long as these pointers are in use.
|
||||
* @param[in,out] map_bundle Pointer to a preallocated `JxlGainMapBundle` where
|
||||
* the deserialized data will be stored.
|
||||
* @param[in] input_buffer Pointer to the buffer containing the serialized gain
|
||||
* map bundle data.
|
||||
* @param[in] input_buffer_size The size of the input buffer in bytes.
|
||||
* @param[out] bytes_read The number of bytes read from the input buffer.
|
||||
* @return Whether reading the bundle was successful.
|
||||
*/
|
||||
JXL_EXPORT JXL_BOOL JxlGainMapReadBundle(JxlGainMapBundle* map_bundle,
|
||||
const uint8_t* input_buffer,
|
||||
size_t input_buffer_size,
|
||||
size_t* bytes_read);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* JXL_GAIN_MAP_H_ */
|
||||
|
||||
/** @} */
|
||||
8
util/jxl/jxl_export.h
Normal file
8
util/jxl/jxl_export.h
Normal file
@@ -0,0 +1,8 @@
|
||||
// Copyright 2021 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
#ifndef THIRD_PARTY_LIBJXL_JXL_JXL_EXPORT_H_
|
||||
#define THIRD_PARTY_LIBJXL_JXL_JXL_EXPORT_H_
|
||||
#define JXL_EXPORT
|
||||
#define JXL_DEPRECATED
|
||||
#endif // THIRD_PARTY_LIBJXL_JXL_JXL_EXPORT_H_
|
||||
73
util/jxl/memory_manager.h
Normal file
73
util/jxl/memory_manager.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* Copyright (c) the JPEG XL Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/** @addtogroup libjxl_common
|
||||
* @{
|
||||
* @file memory_manager.h
|
||||
* @brief Abstraction functions used by JPEG XL to allocate memory.
|
||||
*/
|
||||
|
||||
#ifndef JXL_MEMORY_MANAGER_H_
|
||||
#define JXL_MEMORY_MANAGER_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Allocating function for a memory region of a given size.
|
||||
*
|
||||
* Allocates a contiguous memory region of size @p size bytes. The returned
|
||||
* memory may not be aligned to a specific size or initialized at all.
|
||||
*
|
||||
* @param opaque custom memory manager handle provided by the caller.
|
||||
* @param size in bytes of the requested memory region.
|
||||
* @return @c NULL if the memory can not be allocated,
|
||||
* @return pointer to the memory otherwise.
|
||||
*/
|
||||
typedef void* (*jpegxl_alloc_func)(void* opaque, size_t size);
|
||||
|
||||
/**
|
||||
* Deallocating function pointer type.
|
||||
*
|
||||
* This function @b MUST do nothing if @p address is @c NULL.
|
||||
*
|
||||
* @param opaque custom memory manager handle provided by the caller.
|
||||
* @param address memory region pointer returned by ::jpegxl_alloc_func, or @c
|
||||
* NULL.
|
||||
*/
|
||||
typedef void (*jpegxl_free_func)(void* opaque, void* address);
|
||||
|
||||
/**
|
||||
* Memory Manager struct.
|
||||
* These functions, when provided by the caller, will be used to handle memory
|
||||
* allocations.
|
||||
*/
|
||||
typedef struct JxlMemoryManagerStruct {
|
||||
/** The opaque pointer that will be passed as the first parameter to all the
|
||||
* functions in this struct. */
|
||||
void* opaque;
|
||||
|
||||
/** Memory allocation function. This can be NULL if and only if also the
|
||||
* free() member in this class is NULL. All dynamic memory will be allocated
|
||||
* and freed with these functions if they are not NULL, otherwise with the
|
||||
* standard malloc/free. */
|
||||
jpegxl_alloc_func alloc;
|
||||
/** Free function matching the alloc() member. */
|
||||
jpegxl_free_func free;
|
||||
|
||||
/* TODO(deymo): Add cache-aligned alloc/free functions here. */
|
||||
} JxlMemoryManager;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* JXL_MEMORY_MANAGER_H_ */
|
||||
|
||||
/** @}*/
|
||||
164
util/jxl/parallel_runner.h
Normal file
164
util/jxl/parallel_runner.h
Normal file
@@ -0,0 +1,164 @@
|
||||
/* Copyright (c) the JPEG XL Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/** @addtogroup libjxl_threads
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @file parallel_runner.h
|
||||
*/
|
||||
|
||||
/** API for running data operations in parallel in a multi-threaded environment.
|
||||
* This module allows the JPEG XL caller to define their own way of creating and
|
||||
* assigning threads.
|
||||
*
|
||||
* The JxlParallelRunner function type defines a parallel data processing
|
||||
* runner that may be implemented by the caller to allow the library to process
|
||||
* in multiple threads. The multi-threaded processing in this library only
|
||||
* requires to run the same function over each number of a range, possibly
|
||||
* running each call in a different thread. The JPEG XL caller is responsible
|
||||
* for implementing this logic using the thread APIs available in their system.
|
||||
* For convenience, a C++ implementation based on std::thread is provided in
|
||||
* jpegxl/parallel_runner_thread.h (part of the jpegxl_threads library).
|
||||
*
|
||||
* Thread pools usually store small numbers of heterogeneous tasks in a queue.
|
||||
* When tasks are identical or differ only by an integer input parameter, it is
|
||||
* much faster to store just one function of an integer parameter and call it
|
||||
* for each value. Conventional vector-of-tasks can be run in parallel using a
|
||||
* lambda function adapter that simply calls task_funcs[task].
|
||||
*
|
||||
* If no multi-threading is desired, a @c NULL value of JxlParallelRunner
|
||||
* will use an internal implementation without multi-threading.
|
||||
*/
|
||||
|
||||
#ifndef JXL_PARALLEL_RUNNER_H_
|
||||
#define JXL_PARALLEL_RUNNER_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Return code used in the JxlParallel* functions as return value. A value
|
||||
* of ::JXL_PARALLEL_RET_SUCCESS means success and any other value means error.
|
||||
* The special value ::JXL_PARALLEL_RET_RUNNER_ERROR can be used by the runner
|
||||
* to indicate any other error.
|
||||
*/
|
||||
typedef int JxlParallelRetCode;
|
||||
|
||||
/**
|
||||
* Code returned by the @ref JxlParallelRunInit function to indicate success.
|
||||
*/
|
||||
#define JXL_PARALLEL_RET_SUCCESS (0)
|
||||
|
||||
/**
|
||||
* Code returned by the @ref JxlParallelRunInit function to indicate a general
|
||||
* error.
|
||||
*/
|
||||
#define JXL_PARALLEL_RET_RUNNER_ERROR (-1)
|
||||
|
||||
/**
|
||||
* Parallel run initialization callback. See @ref JxlParallelRunner for details.
|
||||
*
|
||||
* This function MUST be called by the JxlParallelRunner only once, on the
|
||||
* same thread that called @ref JxlParallelRunner, before any parallel
|
||||
* execution. The purpose of this call is to provide the maximum number of
|
||||
* threads that the
|
||||
* @ref JxlParallelRunner will use, which can be used by JPEG XL to allocate
|
||||
* per-thread storage if needed.
|
||||
*
|
||||
* @param jpegxl_opaque the @p jpegxl_opaque handle provided to
|
||||
* @ref JxlParallelRunner() must be passed here.
|
||||
* @param num_threads the maximum number of threads. This value must be
|
||||
* positive.
|
||||
* @return 0 if the initialization process was successful.
|
||||
* @return an error code if there was an error, which should be returned by
|
||||
* @ref JxlParallelRunner().
|
||||
*/
|
||||
typedef JxlParallelRetCode (*JxlParallelRunInit)(void* jpegxl_opaque,
|
||||
size_t num_threads);
|
||||
|
||||
/**
|
||||
* Parallel run data processing callback. See @ref JxlParallelRunner for
|
||||
* details.
|
||||
*
|
||||
* This function MUST be called once for every number in the range [start_range,
|
||||
* end_range) (including start_range but not including end_range) passing this
|
||||
* number as the @p value. Calls for different value may be executed from
|
||||
* different threads in parallel.
|
||||
*
|
||||
* @param jpegxl_opaque the @p jpegxl_opaque handle provided to
|
||||
* @ref JxlParallelRunner() must be passed here.
|
||||
* @param value the number in the range [start_range, end_range) of the call.
|
||||
* @param thread_id the thread number where this function is being called from.
|
||||
* This must be lower than the @p num_threads value passed to
|
||||
* @ref JxlParallelRunInit.
|
||||
*/
|
||||
typedef void (*JxlParallelRunFunction)(void* jpegxl_opaque, uint32_t value,
|
||||
size_t thread_id);
|
||||
|
||||
/**
|
||||
* JxlParallelRunner function type. A parallel runner implementation can be
|
||||
* provided by a JPEG XL caller to allow running computations in multiple
|
||||
* threads. This function must call the initialization function @p init in the
|
||||
* same thread that called it and then call the passed @p func once for every
|
||||
* number in the range [start_range, end_range) (including start_range but not
|
||||
* including end_range) possibly from different multiple threads in parallel.
|
||||
*
|
||||
* The @ref JxlParallelRunner function does not need to be re-entrant. This
|
||||
* means that the same @ref JxlParallelRunner function with the same
|
||||
* runner_opaque provided parameter will not be called from the library from
|
||||
* either @p init or
|
||||
* @p func in the same decoder or encoder instance. However, a single decoding
|
||||
* or encoding instance may call the provided @ref JxlParallelRunner multiple
|
||||
* times for different parts of the decoding or encoding process.
|
||||
*
|
||||
* @return 0 if the @p init call succeeded (returned 0) and no other error
|
||||
* occurred in the runner code.
|
||||
* @return JXL_PARALLEL_RET_RUNNER_ERROR if an error occurred in the runner
|
||||
* code, for example, setting up the threads.
|
||||
* @return the return value of @p init() if non-zero.
|
||||
*/
|
||||
typedef JxlParallelRetCode (*JxlParallelRunner)(
|
||||
void* runner_opaque, void* jpegxl_opaque, JxlParallelRunInit init,
|
||||
JxlParallelRunFunction func, uint32_t start_range, uint32_t end_range);
|
||||
|
||||
/* The following is an example of a @ref JxlParallelRunner that doesn't use any
|
||||
* multi-threading. Note that this implementation doesn't store any state
|
||||
* between multiple calls of the ExampleSequentialRunner function, so the
|
||||
* runner_opaque value is not used.
|
||||
|
||||
JxlParallelRetCode ExampleSequentialRunner(void* runner_opaque,
|
||||
void* jpegxl_opaque,
|
||||
JxlParallelRunInit init,
|
||||
JxlParallelRunFunction func,
|
||||
uint32_t start_range,
|
||||
uint32_t end_range) {
|
||||
// We only use one thread (the currently running thread).
|
||||
JxlParallelRetCode init_ret = (*init)(jpegxl_opaque, 1);
|
||||
if (init_ret != 0) return init_ret;
|
||||
|
||||
// In case of other initialization error (for example when initializing the
|
||||
// threads) one can return JXL_PARALLEL_RET_RUNNER_ERROR.
|
||||
|
||||
for (uint32_t i = start_range; i < end_range; i++) {
|
||||
// Every call is in the thread number 0. These don't need to be in any
|
||||
// order.
|
||||
(*func)(jpegxl_opaque, i, 0);
|
||||
}
|
||||
return JXL_PARALLEL_RET_SUCCESS;
|
||||
}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* JXL_PARALLEL_RUNNER_H_ */
|
||||
|
||||
/** @}*/
|
||||
77
util/jxl/resizable_parallel_runner.h
Normal file
77
util/jxl/resizable_parallel_runner.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/* Copyright (c) the JPEG XL Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/** @addtogroup libjxl_threads
|
||||
* @{
|
||||
* @file resizable_parallel_runner.h
|
||||
* @brief implementation using std::thread of a resizeable ::JxlParallelRunner.
|
||||
*/
|
||||
|
||||
/** Implementation of JxlParallelRunner than can be used to enable
|
||||
* multithreading when using the JPEG XL library. This uses std::thread
|
||||
* internally and related synchronization functions. The number of threads
|
||||
* created can be changed after creation of the thread pool; the threads
|
||||
* (including the main thread) are re-used for every
|
||||
* ResizableParallelRunner::Runner call. Only one concurrent
|
||||
* @ref JxlResizableParallelRunner call per instance is allowed at a time.
|
||||
*
|
||||
* This is a scalable, lower-overhead thread pool runner, especially suitable
|
||||
* for data-parallel computations in the fork-join model, where clients need to
|
||||
* know when all tasks have completed.
|
||||
*
|
||||
* Compared to the implementation in @ref thread_parallel_runner.h, this
|
||||
* implementation is tuned for execution on lower-powered systems, including
|
||||
* for example ARM CPUs with big.LITTLE computation models.
|
||||
*/
|
||||
|
||||
#ifndef JXL_RESIZABLE_PARALLEL_RUNNER_H_
|
||||
#define JXL_RESIZABLE_PARALLEL_RUNNER_H_
|
||||
|
||||
#include <jxl/jxl_threads_export.h>
|
||||
#include <jxl/memory_manager.h>
|
||||
#include <jxl/parallel_runner.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Parallel runner internally using std::thread. Use as @ref JxlParallelRunner.
|
||||
*/
|
||||
JXL_THREADS_EXPORT JxlParallelRetCode JxlResizableParallelRunner(
|
||||
void* runner_opaque, void* jpegxl_opaque, JxlParallelRunInit init,
|
||||
JxlParallelRunFunction func, uint32_t start_range, uint32_t end_range);
|
||||
|
||||
/** Creates the runner for @ref JxlResizableParallelRunner. Use as the opaque
|
||||
* runner. The runner will execute tasks on the calling thread until
|
||||
* @ref JxlResizableParallelRunnerSetThreads is called.
|
||||
*/
|
||||
JXL_THREADS_EXPORT void* JxlResizableParallelRunnerCreate(
|
||||
const JxlMemoryManager* memory_manager);
|
||||
|
||||
/** Changes the number of threads for @ref JxlResizableParallelRunner.
|
||||
*/
|
||||
JXL_THREADS_EXPORT void JxlResizableParallelRunnerSetThreads(
|
||||
void* runner_opaque, size_t num_threads);
|
||||
|
||||
/** Suggests a number of threads to use for an image of given size.
|
||||
*/
|
||||
JXL_THREADS_EXPORT uint32_t
|
||||
JxlResizableParallelRunnerSuggestThreads(uint64_t xsize, uint64_t ysize);
|
||||
|
||||
/** Destroys the runner created by @ref JxlResizableParallelRunnerCreate.
|
||||
*/
|
||||
JXL_THREADS_EXPORT void JxlResizableParallelRunnerDestroy(void* runner_opaque);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* JXL_RESIZABLE_PARALLEL_RUNNER_H_ */
|
||||
|
||||
/** @}*/
|
||||
65
util/jxl/resizable_parallel_runner_cxx.h
Normal file
65
util/jxl/resizable_parallel_runner_cxx.h
Normal file
@@ -0,0 +1,65 @@
|
||||
// Copyright (c) the JPEG XL Project Authors. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/// @addtogroup libjxl_cpp
|
||||
/// @{
|
||||
///
|
||||
/// @file resizable_parallel_runner_cxx.h
|
||||
/// @ingroup libjxl_threads
|
||||
/// @brief C++ header-only helper for @ref resizable_parallel_runner.h.
|
||||
///
|
||||
/// There's no binary library associated with the header since this is a header
|
||||
/// only library.
|
||||
|
||||
#ifndef JXL_RESIZABLE_PARALLEL_RUNNER_CXX_H_
|
||||
#define JXL_RESIZABLE_PARALLEL_RUNNER_CXX_H_
|
||||
|
||||
#include <jxl/memory_manager.h>
|
||||
#include <jxl/resizable_parallel_runner.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#ifndef __cplusplus
|
||||
#error \
|
||||
"This a C++ only header. Use jxl/jxl_resizable_parallel_runner.h from C" \
|
||||
"sources."
|
||||
#endif
|
||||
|
||||
/// Struct to call JxlResizableParallelRunnerDestroy from the
|
||||
/// JxlResizableParallelRunnerPtr unique_ptr.
|
||||
struct JxlResizableParallelRunnerDestroyStruct {
|
||||
/// Calls @ref JxlResizableParallelRunnerDestroy() on the passed runner.
|
||||
void operator()(void* runner) { JxlResizableParallelRunnerDestroy(runner); }
|
||||
};
|
||||
|
||||
/// std::unique_ptr<> type that calls JxlResizableParallelRunnerDestroy() when
|
||||
/// releasing the runner.
|
||||
///
|
||||
/// Use this helper type from C++ sources to ensure the runner is destroyed and
|
||||
/// their internal resources released.
|
||||
typedef std::unique_ptr<void, JxlResizableParallelRunnerDestroyStruct>
|
||||
JxlResizableParallelRunnerPtr;
|
||||
|
||||
/// Creates an instance of JxlResizableParallelRunner into a
|
||||
/// JxlResizableParallelRunnerPtr and initializes it.
|
||||
///
|
||||
/// This function returns a unique_ptr that will call
|
||||
/// JxlResizableParallelRunnerDestroy() when releasing the pointer. See @ref
|
||||
/// JxlResizableParallelRunnerCreate for details on the instance creation.
|
||||
///
|
||||
/// @param memory_manager custom allocator function. It may be NULL. The memory
|
||||
/// manager will be copied internally.
|
||||
/// @return a @c NULL JxlResizableParallelRunnerPtr if the instance can not be
|
||||
/// allocated or initialized
|
||||
/// @return initialized JxlResizableParallelRunnerPtr instance otherwise.
|
||||
static inline JxlResizableParallelRunnerPtr JxlResizableParallelRunnerMake(
|
||||
const JxlMemoryManager* memory_manager) {
|
||||
return JxlResizableParallelRunnerPtr(
|
||||
JxlResizableParallelRunnerCreate(memory_manager));
|
||||
}
|
||||
|
||||
#endif // JXL_RESIZABLE_PARALLEL_RUNNER_CXX_H_
|
||||
|
||||
/// @}
|
||||
103
util/jxl/stats.h
Normal file
103
util/jxl/stats.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/* Copyright (c) the JPEG XL Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/** @addtogroup libjxl_encoder
|
||||
* @{
|
||||
* @file stats.h
|
||||
* @brief API to collect various statistics from JXL encoder.
|
||||
*/
|
||||
|
||||
#ifndef JXL_STATS_H_
|
||||
#define JXL_STATS_H_
|
||||
|
||||
#include <jxl/jxl_export.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Opaque structure that holds the encoder statistics.
|
||||
*
|
||||
* Allocated and initialized with @ref JxlEncoderStatsCreate().
|
||||
* Cleaned up and deallocated with @ref JxlEncoderStatsDestroy().
|
||||
*/
|
||||
typedef struct JxlEncoderStatsStruct JxlEncoderStats;
|
||||
|
||||
/**
|
||||
* Creates an instance of JxlEncoderStats and initializes it.
|
||||
*
|
||||
* @return pointer to initialized @ref JxlEncoderStats instance
|
||||
*/
|
||||
JXL_EXPORT JxlEncoderStats* JxlEncoderStatsCreate(void);
|
||||
|
||||
/**
|
||||
* Deinitializes and frees JxlEncoderStats instance.
|
||||
*
|
||||
* @param stats instance to be cleaned up and deallocated. No-op if stats is
|
||||
* null pointer.
|
||||
*/
|
||||
JXL_EXPORT void JxlEncoderStatsDestroy(JxlEncoderStats* stats);
|
||||
|
||||
/** Data type for querying @ref JxlEncoderStats object
|
||||
*/
|
||||
typedef enum {
|
||||
JXL_ENC_STAT_HEADER_BITS,
|
||||
JXL_ENC_STAT_TOC_BITS,
|
||||
JXL_ENC_STAT_DICTIONARY_BITS,
|
||||
JXL_ENC_STAT_SPLINES_BITS,
|
||||
JXL_ENC_STAT_NOISE_BITS,
|
||||
JXL_ENC_STAT_QUANT_BITS,
|
||||
JXL_ENC_STAT_MODULAR_TREE_BITS,
|
||||
JXL_ENC_STAT_MODULAR_GLOBAL_BITS,
|
||||
JXL_ENC_STAT_DC_BITS,
|
||||
JXL_ENC_STAT_MODULAR_DC_GROUP_BITS,
|
||||
JXL_ENC_STAT_CONTROL_FIELDS_BITS,
|
||||
JXL_ENC_STAT_COEF_ORDER_BITS,
|
||||
JXL_ENC_STAT_AC_HISTOGRAM_BITS,
|
||||
JXL_ENC_STAT_AC_BITS,
|
||||
JXL_ENC_STAT_MODULAR_AC_GROUP_BITS,
|
||||
JXL_ENC_STAT_NUM_SMALL_BLOCKS,
|
||||
JXL_ENC_STAT_NUM_DCT4X8_BLOCKS,
|
||||
JXL_ENC_STAT_NUM_AFV_BLOCKS,
|
||||
JXL_ENC_STAT_NUM_DCT8_BLOCKS,
|
||||
JXL_ENC_STAT_NUM_DCT8X32_BLOCKS,
|
||||
JXL_ENC_STAT_NUM_DCT16_BLOCKS,
|
||||
JXL_ENC_STAT_NUM_DCT16X32_BLOCKS,
|
||||
JXL_ENC_STAT_NUM_DCT32_BLOCKS,
|
||||
JXL_ENC_STAT_NUM_DCT32X64_BLOCKS,
|
||||
JXL_ENC_STAT_NUM_DCT64_BLOCKS,
|
||||
JXL_ENC_STAT_NUM_BUTTERAUGLI_ITERS,
|
||||
JXL_ENC_NUM_STATS,
|
||||
} JxlEncoderStatsKey;
|
||||
|
||||
/** Returns the value of the statistics corresponding the given key.
|
||||
*
|
||||
* @param stats object that was passed to the encoder with a
|
||||
* @ref JxlEncoderCollectStats function
|
||||
* @param key the particular statistics to query
|
||||
*
|
||||
* @return the value of the statistics
|
||||
*/
|
||||
JXL_EXPORT size_t JxlEncoderStatsGet(const JxlEncoderStats* stats,
|
||||
JxlEncoderStatsKey key);
|
||||
|
||||
/** Updates the values of the given stats object with that of an other.
|
||||
*
|
||||
* @param stats object whose values will be updated (usually added together)
|
||||
* @param other stats object whose values will be merged with stats
|
||||
*/
|
||||
JXL_EXPORT void JxlEncoderStatsMerge(JxlEncoderStats* stats,
|
||||
const JxlEncoderStats* other);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* JXL_STATS_H_ */
|
||||
|
||||
/** @}*/
|
||||
71
util/jxl/thread_parallel_runner.h
Normal file
71
util/jxl/thread_parallel_runner.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/* Copyright (c) the JPEG XL Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/** @addtogroup libjxl_threads
|
||||
* @{
|
||||
* @file thread_parallel_runner.h
|
||||
* @brief implementation using std::thread of a ::JxlParallelRunner.
|
||||
*/
|
||||
|
||||
/** Implementation of JxlParallelRunner than can be used to enable
|
||||
* multithreading when using the JPEG XL library. This uses std::thread
|
||||
* internally and related synchronization functions. The number of threads
|
||||
* created is fixed at construction time and the threads are re-used for every
|
||||
* ThreadParallelRunner::Runner call. Only one concurrent
|
||||
* JxlThreadParallelRunner call per instance is allowed at a time.
|
||||
*
|
||||
* This is a scalable, lower-overhead thread pool runner, especially suitable
|
||||
* for data-parallel computations in the fork-join model, where clients need to
|
||||
* know when all tasks have completed.
|
||||
*
|
||||
* This thread pool can efficiently load-balance millions of tasks using an
|
||||
* atomic counter, thus avoiding per-task virtual or system calls. With 48
|
||||
* hyperthreads and 1M tasks that add to an atomic counter, overall runtime is
|
||||
* 10-20x higher when using std::async, and ~200x for a queue-based thread
|
||||
*/
|
||||
|
||||
#ifndef JXL_THREAD_PARALLEL_RUNNER_H_
|
||||
#define JXL_THREAD_PARALLEL_RUNNER_H_
|
||||
|
||||
#include <jxl/jxl_threads_export.h>
|
||||
#include <jxl/memory_manager.h>
|
||||
#include <jxl/parallel_runner.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Parallel runner internally using std::thread. Use as @ref JxlParallelRunner.
|
||||
*/
|
||||
JXL_THREADS_EXPORT JxlParallelRetCode JxlThreadParallelRunner(
|
||||
void* runner_opaque, void* jpegxl_opaque, JxlParallelRunInit init,
|
||||
JxlParallelRunFunction func, uint32_t start_range, uint32_t end_range);
|
||||
|
||||
/** Creates the runner for @ref JxlThreadParallelRunner. Use as the opaque
|
||||
* runner.
|
||||
*/
|
||||
JXL_THREADS_EXPORT void* JxlThreadParallelRunnerCreate(
|
||||
const JxlMemoryManager* memory_manager, size_t num_worker_threads);
|
||||
|
||||
/** Destroys the runner created by @ref JxlThreadParallelRunnerCreate.
|
||||
*/
|
||||
JXL_THREADS_EXPORT void JxlThreadParallelRunnerDestroy(void* runner_opaque);
|
||||
|
||||
/** Returns a default num_worker_threads value for
|
||||
* @ref JxlThreadParallelRunnerCreate.
|
||||
*/
|
||||
JXL_THREADS_EXPORT size_t JxlThreadParallelRunnerDefaultNumWorkerThreads(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* JXL_THREAD_PARALLEL_RUNNER_H_ */
|
||||
|
||||
/** @}*/
|
||||
66
util/jxl/thread_parallel_runner_cxx.h
Normal file
66
util/jxl/thread_parallel_runner_cxx.h
Normal file
@@ -0,0 +1,66 @@
|
||||
// Copyright (c) the JPEG XL Project Authors. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/// @addtogroup libjxl_cpp
|
||||
/// @{
|
||||
///
|
||||
/// @file thread_parallel_runner_cxx.h
|
||||
/// @brief C++ header-only helper for @ref thread_parallel_runner.h.
|
||||
///
|
||||
/// There's no binary library associated with the header since this is a header
|
||||
/// only library.
|
||||
|
||||
#ifndef JXL_THREAD_PARALLEL_RUNNER_CXX_H_
|
||||
#define JXL_THREAD_PARALLEL_RUNNER_CXX_H_
|
||||
|
||||
#include <jxl/memory_manager.h>
|
||||
#include <jxl/thread_parallel_runner.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
|
||||
#ifndef __cplusplus
|
||||
#error \
|
||||
"This a C++ only header. Use jxl/jxl_thread_parallel_runner.h from C" \
|
||||
"sources."
|
||||
#endif
|
||||
|
||||
/// Struct to call JxlThreadParallelRunnerDestroy from the
|
||||
/// JxlThreadParallelRunnerPtr unique_ptr.
|
||||
struct JxlThreadParallelRunnerDestroyStruct {
|
||||
/// Calls @ref JxlThreadParallelRunnerDestroy() on the passed runner.
|
||||
void operator()(void* runner) { JxlThreadParallelRunnerDestroy(runner); }
|
||||
};
|
||||
|
||||
/// std::unique_ptr<> type that calls JxlThreadParallelRunnerDestroy() when
|
||||
/// releasing the runner.
|
||||
///
|
||||
/// Use this helper type from C++ sources to ensure the runner is destroyed and
|
||||
/// their internal resources released.
|
||||
typedef std::unique_ptr<void, JxlThreadParallelRunnerDestroyStruct>
|
||||
JxlThreadParallelRunnerPtr;
|
||||
|
||||
/// Creates an instance of JxlThreadParallelRunner into a
|
||||
/// JxlThreadParallelRunnerPtr and initializes it.
|
||||
///
|
||||
/// This function returns a unique_ptr that will call
|
||||
/// JxlThreadParallelRunnerDestroy() when releasing the pointer. See @ref
|
||||
/// JxlThreadParallelRunnerCreate for details on the instance creation.
|
||||
///
|
||||
/// @param memory_manager custom allocator function. It may be NULL. The memory
|
||||
/// manager will be copied internally.
|
||||
/// @param num_worker_threads the number of worker threads to create.
|
||||
/// @return a @c NULL JxlThreadParallelRunnerPtr if the instance can not be
|
||||
/// allocated or initialized
|
||||
/// @return initialized JxlThreadParallelRunnerPtr instance otherwise.
|
||||
static inline JxlThreadParallelRunnerPtr JxlThreadParallelRunnerMake(
|
||||
const JxlMemoryManager* memory_manager, size_t num_worker_threads) {
|
||||
return JxlThreadParallelRunnerPtr(
|
||||
JxlThreadParallelRunnerCreate(memory_manager, num_worker_threads));
|
||||
}
|
||||
|
||||
#endif // JXL_THREAD_PARALLEL_RUNNER_CXX_H_
|
||||
|
||||
/// @}
|
||||
154
util/jxl/types.h
Normal file
154
util/jxl/types.h
Normal file
@@ -0,0 +1,154 @@
|
||||
/* Copyright (c) the JPEG XL Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/** @addtogroup libjxl_common
|
||||
* @{
|
||||
* @file types.h
|
||||
* @brief Data types for the JPEG XL API, for both encoding and decoding.
|
||||
*/
|
||||
|
||||
#ifndef JXL_TYPES_H_
|
||||
#define JXL_TYPES_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A portable @c bool replacement.
|
||||
*
|
||||
* ::JXL_BOOL is a "documentation" type: actually it is @c int, but in API it
|
||||
* denotes a type, whose only values are ::JXL_TRUE and ::JXL_FALSE.
|
||||
*/
|
||||
#define JXL_BOOL int
|
||||
/** Portable @c true replacement. */
|
||||
#define JXL_TRUE 1
|
||||
/** Portable @c false replacement. */
|
||||
#define JXL_FALSE 0
|
||||
/** Converts of bool-like value to either ::JXL_TRUE or ::JXL_FALSE. */
|
||||
#define TO_JXL_BOOL(C) (!!(C) ? JXL_TRUE : JXL_FALSE)
|
||||
/** Converts JXL_BOOL to C++ bool. */
|
||||
#define FROM_JXL_BOOL(C) (static_cast<bool>(C))
|
||||
|
||||
/** Data type for the sample values per channel per pixel.
|
||||
*/
|
||||
typedef enum {
|
||||
/** Use 32-bit single-precision floating point values, with range 0.0-1.0
|
||||
* (within gamut, may go outside this range for wide color gamut). Floating
|
||||
* point output, either ::JXL_TYPE_FLOAT or ::JXL_TYPE_FLOAT16, is recommended
|
||||
* for HDR and wide gamut images when color profile conversion is required. */
|
||||
JXL_TYPE_FLOAT = 0,
|
||||
|
||||
/** Use type uint8_t. May clip wide color gamut data.
|
||||
*/
|
||||
JXL_TYPE_UINT8 = 2,
|
||||
|
||||
/** Use type uint16_t. May clip wide color gamut data.
|
||||
*/
|
||||
JXL_TYPE_UINT16 = 3,
|
||||
|
||||
/** Use 16-bit IEEE 754 half-precision floating point values */
|
||||
JXL_TYPE_FLOAT16 = 5,
|
||||
} JxlDataType;
|
||||
|
||||
/** Ordering of multi-byte data.
|
||||
*/
|
||||
typedef enum {
|
||||
/** Use the endianness of the system, either little endian or big endian,
|
||||
* without forcing either specific endianness. Do not use if pixel data
|
||||
* should be exported to a well defined format.
|
||||
*/
|
||||
JXL_NATIVE_ENDIAN = 0,
|
||||
/** Force little endian */
|
||||
JXL_LITTLE_ENDIAN = 1,
|
||||
/** Force big endian */
|
||||
JXL_BIG_ENDIAN = 2,
|
||||
} JxlEndianness;
|
||||
|
||||
/** Data type for the sample values per channel per pixel for the output buffer
|
||||
* for pixels. This is not necessarily the same as the data type encoded in the
|
||||
* codestream. The channels are interleaved per pixel. The pixels are
|
||||
* organized row by row, left to right, top to bottom.
|
||||
* TODO(lode): support different channel orders if needed (RGB, BGR, ...)
|
||||
*/
|
||||
typedef struct {
|
||||
/** Amount of channels available in a pixel buffer.
|
||||
* 1: single-channel data, e.g. grayscale or a single extra channel
|
||||
* 2: single-channel + alpha
|
||||
* 3: trichromatic, e.g. RGB
|
||||
* 4: trichromatic + alpha
|
||||
* TODO(lode): this needs finetuning. It is not yet defined how the user
|
||||
* chooses output color space. CMYK+alpha needs 5 channels.
|
||||
*/
|
||||
uint32_t num_channels;
|
||||
|
||||
/** Data type of each channel.
|
||||
*/
|
||||
JxlDataType data_type;
|
||||
|
||||
/** Whether multi-byte data types are represented in big endian or little
|
||||
* endian format. This applies to ::JXL_TYPE_UINT16 and ::JXL_TYPE_FLOAT.
|
||||
*/
|
||||
JxlEndianness endianness;
|
||||
|
||||
/** Align scanlines to a multiple of align bytes, or 0 to require no
|
||||
* alignment at all (which has the same effect as value 1)
|
||||
*/
|
||||
size_t align;
|
||||
} JxlPixelFormat;
|
||||
|
||||
/** Settings for the interpretation of UINT input and output buffers.
|
||||
* (buffers using a FLOAT data type are not affected by this)
|
||||
*/
|
||||
typedef enum {
|
||||
/** This is the default setting, where the encoder expects the input pixels
|
||||
* to use the full range of the pixel format data type (e.g. for UINT16, the
|
||||
* input range is 0 .. 65535 and the value 65535 is mapped to 1.0 when
|
||||
* converting to float), and the decoder uses the full range to output
|
||||
* pixels. If the bit depth in the basic info is different from this, the
|
||||
* encoder expects the values to be rescaled accordingly (e.g. multiplied by
|
||||
* 65535/4095 for a 12-bit image using UINT16 input data type). */
|
||||
JXL_BIT_DEPTH_FROM_PIXEL_FORMAT = 0,
|
||||
|
||||
/** If this setting is selected, the encoder expects the input pixels to be
|
||||
* in the range defined by the bits_per_sample value of the basic info (e.g.
|
||||
* for 12-bit images using UINT16 input data types, the allowed range is
|
||||
* 0 .. 4095 and the value 4095 is mapped to 1.0 when converting to float),
|
||||
* and the decoder outputs pixels in this range. */
|
||||
JXL_BIT_DEPTH_FROM_CODESTREAM = 1,
|
||||
|
||||
/** This setting can only be used in the decoder to select a custom range for
|
||||
* pixel output */
|
||||
JXL_BIT_DEPTH_CUSTOM = 2,
|
||||
} JxlBitDepthType;
|
||||
|
||||
/** Data type for describing the interpretation of the input and output buffers
|
||||
* in terms of the range of allowed input and output pixel values. */
|
||||
typedef struct {
|
||||
/** Bit depth setting, see comment on @ref JxlBitDepthType */
|
||||
JxlBitDepthType type;
|
||||
|
||||
/** Custom bits per sample */
|
||||
uint32_t bits_per_sample;
|
||||
|
||||
/** Custom exponent bits per sample */
|
||||
uint32_t exponent_bits_per_sample;
|
||||
} JxlBitDepth;
|
||||
|
||||
/** Data type holding the 4-character type name of an ISOBMFF box.
|
||||
*/
|
||||
typedef char JxlBoxType[4];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* JXL_TYPES_H_ */
|
||||
|
||||
/** @}*/
|
||||
3
util/jxl/version.h
Normal file
3
util/jxl/version.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#ifndef JXL_Version
|
||||
#define JXL_Version = "1.10"
|
||||
#endif
|
||||
242
util/jxlwriter.hpp
Normal file
242
util/jxlwriter.hpp
Normal file
@@ -0,0 +1,242 @@
|
||||
#ifndef JXL_WRITER_HPP
|
||||
#define JXL_WRITER_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include "vec3.hpp"
|
||||
#include <jxl/encode.h>
|
||||
#include <jxl/thread_parallel_runner.h>
|
||||
|
||||
class JXLWriter {
|
||||
private:
|
||||
// Helper function to create directory if it doesn't exist
|
||||
static bool createDirectoryIfNeeded(const std::string& filename) {
|
||||
std::filesystem::path filePath(filename);
|
||||
std::filesystem::path directory = filePath.parent_path();
|
||||
|
||||
// If there's a directory component and it doesn't exist, create it
|
||||
if (!directory.empty() && !std::filesystem::exists(directory)) {
|
||||
return std::filesystem::create_directories(directory);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Helper function to convert Vec3 pixels to interleaved RGB data
|
||||
static std::vector<uint8_t> convertToRGB(const std::vector<std::vector<Vec3>>& pixels, int width, int height) {
|
||||
std::vector<uint8_t> rgbData(width * height * 3);
|
||||
|
||||
for (int y = 0; y < height; ++y) {
|
||||
for (int x = 0; x < width; ++x) {
|
||||
const Vec3& color = pixels[y][x];
|
||||
int offset = (y * width + x) * 3;
|
||||
|
||||
rgbData[offset] = static_cast<uint8_t>(std::clamp(color.x * 255.0f, 0.0f, 255.0f)); // R
|
||||
rgbData[offset + 1] = static_cast<uint8_t>(std::clamp(color.y * 255.0f, 0.0f, 255.0f)); // G
|
||||
rgbData[offset + 2] = static_cast<uint8_t>(std::clamp(color.z * 255.0f, 0.0f, 255.0f)); // B
|
||||
}
|
||||
}
|
||||
|
||||
return rgbData;
|
||||
}
|
||||
|
||||
// Helper function to convert flat Vec3 vector to interleaved RGB data
|
||||
static std::vector<uint8_t> convertToRGB(const std::vector<Vec3>& pixels, int width, int height) {
|
||||
std::vector<uint8_t> rgbData(width * height * 3);
|
||||
|
||||
for (int i = 0; i < width * height; ++i) {
|
||||
const Vec3& color = pixels[i];
|
||||
int offset = i * 3;
|
||||
|
||||
rgbData[offset] = static_cast<uint8_t>(std::clamp(color.x * 255.0f, 0.0f, 255.0f)); // R
|
||||
rgbData[offset + 1] = static_cast<uint8_t>(std::clamp(color.y * 255.0f, 0.0f, 255.0f)); // G
|
||||
rgbData[offset + 2] = static_cast<uint8_t>(std::clamp(color.z * 255.0f, 0.0f, 255.0f)); // B
|
||||
}
|
||||
|
||||
return rgbData;
|
||||
}
|
||||
|
||||
public:
|
||||
// Save a 2D vector of Vec3 (RGB) colors as JXL
|
||||
// Vec3 components: x = red, y = green, z = blue (values in range [0,1])
|
||||
static bool saveJXL(const std::string& filename,
|
||||
const std::vector<std::vector<Vec3>>& pixels,
|
||||
float quality = 90.0f, // Quality setting (0-100)
|
||||
int effort = 7) { // Encoding effort (3-9, higher = slower but better compression)
|
||||
if (pixels.empty() || pixels[0].empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int height = static_cast<int>(pixels.size());
|
||||
int width = static_cast<int>(pixels[0].size());
|
||||
|
||||
// Validate that all rows have the same width
|
||||
for (const auto& row : pixels) {
|
||||
if (row.size() != width) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return saveJXL(filename, pixels, width, height, quality, effort);
|
||||
}
|
||||
|
||||
// Alternative interface with width/height and flat vector (row-major order)
|
||||
static bool saveJXL(const std::string& filename,
|
||||
const std::vector<Vec3>& pixels,
|
||||
int width, int height,
|
||||
float quality = 90.0f,
|
||||
int effort = 7) {
|
||||
if (pixels.size() != width * height) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Convert to 2D vector format
|
||||
std::vector<std::vector<Vec3>> pixels2D(height, std::vector<Vec3>(width));
|
||||
for (int y = 0; y < height; ++y) {
|
||||
for (int x = 0; x < width; ++x) {
|
||||
pixels2D[y][x] = pixels[y * width + x];
|
||||
}
|
||||
}
|
||||
|
||||
return saveJXL(filename, pixels2D, width, height, quality, effort);
|
||||
}
|
||||
|
||||
// Save from 1D vector of uint8_t pixels (RGB order: pixels[i]=r, pixels[i+1]=g, pixels[i+2]=b)
|
||||
static bool saveJXL(const std::string& filename,
|
||||
const std::vector<uint8_t>& pixels,
|
||||
int width, int height,
|
||||
float quality = 90.0f,
|
||||
int effort = 7) {
|
||||
if (pixels.size() != width * height * 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create directory if needed
|
||||
if (!createDirectoryIfNeeded(filename)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create encoder
|
||||
JxlEncoder* enc = JxlEncoderCreate(nullptr);
|
||||
if (!enc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create thread pool (use nullptr for single-threaded)
|
||||
void* runner = JxlThreadParallelRunnerCreate(nullptr, JxlThreadParallelRunnerDefaultNumWorkerThreads());
|
||||
if (JxlEncoderSetParallelRunner(enc, JxlThreadParallelRunner, runner) != JXL_ENC_SUCCESS) {
|
||||
JxlThreadParallelRunnerDestroy(runner);
|
||||
JxlEncoderDestroy(enc);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Configure basic encoder settings
|
||||
JxlEncoderOptions* options = JxlEncoderOptionsCreate(enc, nullptr);
|
||||
|
||||
// Set quality/distance (distance = 0 is lossless, higher = more lossy)
|
||||
float distance = (100.0f - quality) / 10.0f; // Convert quality to distance
|
||||
if (quality >= 100.0f) {
|
||||
JxlEncoderOptionsSetLossless(options, JXL_TRUE);
|
||||
} else {
|
||||
JxlEncoderOptionsSetDistance(options, distance);
|
||||
}
|
||||
|
||||
JxlEncoderOptionsSetEffort(options, effort);
|
||||
|
||||
// Set up basic image info
|
||||
JxlBasicInfo basic_info;
|
||||
JxlEncoderInitBasicInfo(&basic_info);
|
||||
basic_info.xsize = width;
|
||||
basic_info.ysize = height;
|
||||
basic_info.bits_per_sample = 8;
|
||||
basic_info.exponent_bits_per_sample = 0;
|
||||
basic_info.uses_original_profile = JXL_FALSE;
|
||||
|
||||
if (JxlEncoderSetBasicInfo(enc, &basic_info) != JXL_ENC_SUCCESS) {
|
||||
JxlThreadParallelRunnerDestroy(runner);
|
||||
JxlEncoderDestroy(enc);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set color encoding to sRGB
|
||||
JxlColorEncoding color_encoding = {};
|
||||
JxlColorEncodingSetToSRGB(&color_encoding, JXL_FALSE); // is_gray = false
|
||||
if (JxlEncoderSetColorEncoding(enc, &color_encoding) != JXL_ENC_SUCCESS) {
|
||||
JxlThreadParallelRunnerDestroy(runner);
|
||||
JxlEncoderDestroy(enc);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set up pixel format
|
||||
JxlPixelFormat pixel_format = {3, JXL_TYPE_UINT8, JXL_LITTLE_ENDIAN, 0};
|
||||
|
||||
// Add image frame
|
||||
if (JxlEncoderAddImageFrame(options, &pixel_format,
|
||||
(void*)pixels.data(),
|
||||
pixels.size()) != JXL_ENC_SUCCESS) {
|
||||
JxlThreadParallelRunnerDestroy(runner);
|
||||
JxlEncoderDestroy(enc);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Mark the end of input
|
||||
JxlEncoderCloseInput(enc);
|
||||
|
||||
// Compress to buffer
|
||||
std::vector<uint8_t> compressed;
|
||||
compressed.resize(4096); // Start with 4KB
|
||||
uint8_t* next_out = compressed.data();
|
||||
size_t avail_out = compressed.size();
|
||||
JxlEncoderStatus process_result = JXL_ENC_NEED_MORE_OUTPUT;
|
||||
|
||||
while (process_result == JXL_ENC_NEED_MORE_OUTPUT) {
|
||||
process_result = JxlEncoderProcessOutput(enc, &next_out, &avail_out);
|
||||
if (process_result == JXL_ENC_NEED_MORE_OUTPUT) {
|
||||
size_t offset = next_out - compressed.data();
|
||||
compressed.resize(compressed.size() * 2);
|
||||
next_out = compressed.data() + offset;
|
||||
avail_out = compressed.size() - offset;
|
||||
}
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
if (process_result == JXL_ENC_SUCCESS) {
|
||||
// Write to file
|
||||
size_t compressed_size = next_out - compressed.data();
|
||||
std::ofstream file(filename, std::ios::binary);
|
||||
if (file) {
|
||||
file.write(reinterpret_cast<const char*>(compressed.data()), compressed_size);
|
||||
success = file.good();
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
JxlThreadParallelRunnerDestroy(runner);
|
||||
JxlEncoderDestroy(enc);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
private:
|
||||
static bool saveJXL(const std::string& filename,
|
||||
const std::vector<std::vector<Vec3>>& pixels,
|
||||
int width, int height,
|
||||
float quality,
|
||||
int effort) {
|
||||
// Create directory if needed
|
||||
if (!createDirectoryIfNeeded(filename)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Convert Vec3 pixels to interleaved RGB
|
||||
std::vector<uint8_t> rgbData = convertToRGB(pixels, width, height);
|
||||
|
||||
// Use the existing uint8_t version
|
||||
return saveJXL(filename, rgbData, width, height, quality, effort);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
375
util/simple_httpserver.hpp
Normal file
375
util/simple_httpserver.hpp
Normal file
@@ -0,0 +1,375 @@
|
||||
#ifndef SIMPLE_HTTPSERVER_HPP
|
||||
#define SIMPLE_HTTPSERVER_HPP
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "grid2.hpp"
|
||||
#include "bmpwriter.hpp"
|
||||
|
||||
class SimpleHTTPServer {
|
||||
private:
|
||||
int serverSocket;
|
||||
int port;
|
||||
bool running;
|
||||
|
||||
// Function to convert hex color string to Vec4
|
||||
Vec4 hexToVec4(const std::string& hex) {
|
||||
if (hex.length() != 6) {
|
||||
return Vec4(0, 0, 0, 1); // Default to black if invalid
|
||||
}
|
||||
|
||||
int r, g, b;
|
||||
sscanf(hex.c_str(), "%02x%02x%02x", &r, &g, &b);
|
||||
|
||||
return Vec4(r / 255.0f, g / 255.0f, b / 255.0f, 1.0f);
|
||||
}
|
||||
|
||||
// Generate gradient image
|
||||
bool generateGradientImage(const std::string& filename, int width = 512, int height = 512) {
|
||||
const int POINTS_PER_DIM = 256;
|
||||
|
||||
Grid2 grid;
|
||||
|
||||
// Define our target colors at specific positions
|
||||
Vec4 white = hexToVec4("ffffff"); // Top-left corner (1,1)
|
||||
Vec4 red = hexToVec4("ff0000"); // Top-right corner (1,-1)
|
||||
Vec4 green = hexToVec4("00ff00"); // Center (0,0)
|
||||
Vec4 blue = hexToVec4("0000ff"); // Bottom-left corner (-1,-1)
|
||||
Vec4 black = hexToVec4("000000"); // Bottom-right corner (-1,1)
|
||||
|
||||
// Create gradient points
|
||||
for (int y = 0; y < POINTS_PER_DIM; ++y) {
|
||||
for (int x = 0; x < POINTS_PER_DIM; ++x) {
|
||||
// Normalize coordinates to [-1, 1]
|
||||
float nx = (static_cast<float>(x) / (POINTS_PER_DIM - 1)) * 2.0f - 1.0f;
|
||||
float ny = (static_cast<float>(y) / (POINTS_PER_DIM - 1)) * 2.0f - 1.0f;
|
||||
|
||||
// Create position
|
||||
Vec2 pos(nx, ny);
|
||||
|
||||
// Convert to [0,1] range for interpolation
|
||||
float u = (nx + 1.0f) / 2.0f;
|
||||
float v = (ny + 1.0f) / 2.0f;
|
||||
|
||||
// Bilinear interpolation between corners
|
||||
Vec4 top = white * (1.0f - u) + red * u;
|
||||
Vec4 bottom = blue * (1.0f - u) + black * u;
|
||||
Vec4 cornerColor = top * (1.0f - v) + bottom * v;
|
||||
|
||||
// Calculate distance from center (0,0)
|
||||
float distFromCenter = std::sqrt(nx * nx + ny * ny) / std::sqrt(2.0f);
|
||||
|
||||
Vec4 color = green * (1.0f - distFromCenter) + cornerColor * distFromCenter;
|
||||
|
||||
grid.addPoint(pos, color);
|
||||
}
|
||||
}
|
||||
|
||||
// Render to RGB image
|
||||
std::vector<uint8_t> imageData = grid.renderToRGB(width, height);
|
||||
|
||||
// Save as BMP
|
||||
return BMPWriter::saveBMP(filename, imageData, width, height);
|
||||
}
|
||||
|
||||
// Read file content
|
||||
std::string readFile(const std::string& filename) {
|
||||
std::ifstream file(filename, std::ios::binary);
|
||||
if (!file) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::ostringstream ss;
|
||||
ss << file.rdbuf();
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// Send HTTP response
|
||||
void sendResponse(int clientSocket, const std::string& content, const std::string& contentType = "text/html", int statusCode = 200) {
|
||||
std::string statusText = "OK";
|
||||
if (statusCode == 404) statusText = "Not Found";
|
||||
if (statusCode == 500) statusText = "Internal Server Error";
|
||||
|
||||
std::ostringstream response;
|
||||
response << "HTTP/1.1 " << statusCode << " " << statusText << "\r\n";
|
||||
response << "Content-Type: " << contentType << "\r\n";
|
||||
response << "Content-Length: " << content.length() << "\r\n";
|
||||
response << "Connection: close\r\n";
|
||||
response << "\r\n";
|
||||
response << content;
|
||||
|
||||
std::string responseStr = response.str();
|
||||
send(clientSocket, responseStr.c_str(), responseStr.length(), 0);
|
||||
}
|
||||
|
||||
public:
|
||||
SimpleHTTPServer(int port = 8080) : port(port), serverSocket(-1), running(false) {}
|
||||
|
||||
~SimpleHTTPServer() {
|
||||
stop();
|
||||
}
|
||||
|
||||
bool start() {
|
||||
#ifdef _WIN32
|
||||
WSADATA wsaData;
|
||||
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
|
||||
std::cerr << "WSAStartup failed" << std::endl;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
serverSocket = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (serverSocket < 0) {
|
||||
std::cerr << "Socket creation failed" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
int opt = 1;
|
||||
#ifdef _WIN32
|
||||
if (setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt)) < 0) {
|
||||
#else
|
||||
if (setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
|
||||
#endif
|
||||
std::cerr << "Setsockopt failed" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
sockaddr_in serverAddr;
|
||||
serverAddr.sin_family = AF_INET;
|
||||
serverAddr.sin_addr.s_addr = INADDR_ANY;
|
||||
serverAddr.sin_port = htons(port);
|
||||
|
||||
if (bind(serverSocket, (sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) {
|
||||
std::cerr << "Bind failed on port " << port << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (listen(serverSocket, 10) < 0) {
|
||||
std::cerr << "Listen failed" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
running = true;
|
||||
std::cout << "Server started on port " << port << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
void stop() {
|
||||
running = false;
|
||||
if (serverSocket >= 0) {
|
||||
#ifdef _WIN32
|
||||
closesocket(serverSocket);
|
||||
WSACleanup();
|
||||
#else
|
||||
close(serverSocket);
|
||||
#endif
|
||||
serverSocket = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void handleRequests() {
|
||||
while (running) {
|
||||
sockaddr_in clientAddr;
|
||||
#ifdef _WIN32
|
||||
int clientAddrLen = sizeof(clientAddr);
|
||||
#else
|
||||
socklen_t clientAddrLen = sizeof(clientAddr);
|
||||
#endif
|
||||
int clientSocket = accept(serverSocket, (sockaddr*)&clientAddr, &clientAddrLen);
|
||||
|
||||
if (clientSocket < 0) {
|
||||
if (running) {
|
||||
std::cerr << "Accept failed" << std::endl;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
char buffer[4096] = {0};
|
||||
int bytesReceived = recv(clientSocket, buffer, sizeof(buffer), 0);
|
||||
|
||||
if (bytesReceived > 0) {
|
||||
std::string request(buffer);
|
||||
std::cout << "Received request: " << request.substr(0, request.find('\n')) << std::endl;
|
||||
|
||||
// Handle different routes
|
||||
if (request.find("GET / ") != std::string::npos || request.find("GET /index.html") != std::string::npos) {
|
||||
sendResponse(clientSocket, getHTML());
|
||||
} else if (request.find("GET /gradient.bmp") != std::string::npos) {
|
||||
// Generate and serve the gradient image
|
||||
if (generateGradientImage("output/gradient.bmp")) {
|
||||
std::string imageContent = readFile("output/gradient.bmp");
|
||||
if (!imageContent.empty()) {
|
||||
sendResponse(clientSocket, imageContent, "image/bmp");
|
||||
} else {
|
||||
sendResponse(clientSocket, "Error generating image", "text/plain", 500);
|
||||
}
|
||||
} else {
|
||||
sendResponse(clientSocket, "Error generating image", "text/plain", 500);
|
||||
}
|
||||
} else if (request.find("GET /generate") != std::string::npos) {
|
||||
// API endpoint to generate new gradient
|
||||
std::string filename = "output/dynamic_gradient.bmp";
|
||||
if (generateGradientImage(filename)) {
|
||||
sendResponse(clientSocket, "{\"status\":\"success\",\"file\":\"" + filename + "\"}", "application/json");
|
||||
} else {
|
||||
sendResponse(clientSocket, "{\"status\":\"error\"}", "application/json", 500);
|
||||
}
|
||||
} else {
|
||||
sendResponse(clientSocket, "404 Not Found", "text/plain", 404);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
closesocket(clientSocket);
|
||||
#else
|
||||
close(clientSocket);
|
||||
#endif
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
}
|
||||
|
||||
std::string getHTML() {
|
||||
return R"(
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Dynamic Gradient Generator</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Arial', sans-serif;
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
text-align: center;
|
||||
min-height: 100vh;
|
||||
}
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
padding: 30px;
|
||||
border-radius: 15px;
|
||||
backdrop-filter: blur(10px);
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
h1 {
|
||||
margin-bottom: 20px;
|
||||
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
.image-container {
|
||||
margin: 20px 0;
|
||||
padding: 20px;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 10px;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
.controls {
|
||||
margin: 20px 0;
|
||||
}
|
||||
button {
|
||||
background: #4CAF50;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 12px 24px;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
margin: 5px;
|
||||
transition: background 0.3s;
|
||||
}
|
||||
button:hover {
|
||||
background: #45a049;
|
||||
}
|
||||
.info {
|
||||
margin-top: 20px;
|
||||
padding: 15px;
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
border-radius: 8px;
|
||||
text-align: left;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Dynamic Gradient Generator</h1>
|
||||
<p>Real-time gradient generation using C++ HTTP Server</p>
|
||||
|
||||
<div class="controls">
|
||||
<button onclick="refreshImage()\">Refresh Gradient</button>
|
||||
<button onclick="generateNew()\">Generate New</button>
|
||||
</div>
|
||||
|
||||
<div class="image-container">
|
||||
<img id="gradientImage" src="gradient.bmp" alt="Dynamic Gradient">
|
||||
</div>
|
||||
|
||||
<div class="info">
|
||||
<h3>Color Positions:</h3>
|
||||
<ul>
|
||||
<li>Top-left: FFFFFF (White)</li>
|
||||
<li>Top-right: FF0000 (Red)</li>
|
||||
<li>Center: 00FF00 (Green)</li>
|
||||
<li>Bottom-left: 0000FF (Blue)</li>
|
||||
<li>Bottom-right: 000000 (Black)</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function refreshImage() {
|
||||
const img = document.getElementById('gradientImage');
|
||||
const timestamp = new Date().getTime();
|
||||
img.src = 'gradient.bmp?' + timestamp;
|
||||
}
|
||||
|
||||
function generateNew() {
|
||||
fetch('/generate')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.status === 'success') {
|
||||
refreshImage();
|
||||
} else {
|
||||
alert('Error generating new gradient');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
alert('Error generating new gradient');
|
||||
});
|
||||
}
|
||||
|
||||
// Auto-refresh every 30 seconds
|
||||
setInterval(refreshImage, 30000);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
)";
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user