Path: blob/master/3rdparty/libwebp/src/webp/encode.h
16348 views
// Copyright 2011 Google Inc. All Rights Reserved.1//2// Use of this source code is governed by a BSD-style license3// that can be found in the COPYING file in the root of the source4// tree. An additional intellectual property rights grant can be found5// in the file PATENTS. All contributing project authors may6// be found in the AUTHORS file in the root of the source tree.7// -----------------------------------------------------------------------------8//9// WebP encoder: main interface10//11// Author: Skal ([email protected])1213#ifndef WEBP_WEBP_ENCODE_H_14#define WEBP_WEBP_ENCODE_H_1516#include "./types.h"1718#ifdef __cplusplus19extern "C" {20#endif2122#define WEBP_ENCODER_ABI_VERSION 0x020e // MAJOR(8b) + MINOR(8b)2324// Note: forward declaring enumerations is not allowed in (strict) C and C++,25// the types are left here for reference.26// typedef enum WebPImageHint WebPImageHint;27// typedef enum WebPEncCSP WebPEncCSP;28// typedef enum WebPPreset WebPPreset;29// typedef enum WebPEncodingError WebPEncodingError;30typedef struct WebPConfig WebPConfig;31typedef struct WebPPicture WebPPicture; // main structure for I/O32typedef struct WebPAuxStats WebPAuxStats;33typedef struct WebPMemoryWriter WebPMemoryWriter;3435// Return the encoder's version number, packed in hexadecimal using 8bits for36// each of major/minor/revision. E.g: v2.5.7 is 0x020507.37WEBP_EXTERN int WebPGetEncoderVersion(void);3839//------------------------------------------------------------------------------40// One-stop-shop call! No questions asked:4142// Returns the size of the compressed data (pointed to by *output), or 0 if43// an error occurred. The compressed data must be released by the caller44// using the call 'WebPFree(*output)'.45// These functions compress using the lossy format, and the quality_factor46// can go from 0 (smaller output, lower quality) to 100 (best quality,47// larger output).48WEBP_EXTERN size_t WebPEncodeRGB(const uint8_t* rgb,49int width, int height, int stride,50float quality_factor, uint8_t** output);51WEBP_EXTERN size_t WebPEncodeBGR(const uint8_t* bgr,52int width, int height, int stride,53float quality_factor, uint8_t** output);54WEBP_EXTERN size_t WebPEncodeRGBA(const uint8_t* rgba,55int width, int height, int stride,56float quality_factor, uint8_t** output);57WEBP_EXTERN size_t WebPEncodeBGRA(const uint8_t* bgra,58int width, int height, int stride,59float quality_factor, uint8_t** output);6061// These functions are the equivalent of the above, but compressing in a62// lossless manner. Files are usually larger than lossy format, but will63// not suffer any compression loss.64WEBP_EXTERN size_t WebPEncodeLosslessRGB(const uint8_t* rgb,65int width, int height, int stride,66uint8_t** output);67WEBP_EXTERN size_t WebPEncodeLosslessBGR(const uint8_t* bgr,68int width, int height, int stride,69uint8_t** output);70WEBP_EXTERN size_t WebPEncodeLosslessRGBA(const uint8_t* rgba,71int width, int height, int stride,72uint8_t** output);73WEBP_EXTERN size_t WebPEncodeLosslessBGRA(const uint8_t* bgra,74int width, int height, int stride,75uint8_t** output);7677// Releases memory returned by the WebPEncode*() functions above.78WEBP_EXTERN void WebPFree(void* ptr);7980//------------------------------------------------------------------------------81// Coding parameters8283// Image characteristics hint for the underlying encoder.84typedef enum WebPImageHint {85WEBP_HINT_DEFAULT = 0, // default preset.86WEBP_HINT_PICTURE, // digital picture, like portrait, inner shot87WEBP_HINT_PHOTO, // outdoor photograph, with natural lighting88WEBP_HINT_GRAPH, // Discrete tone image (graph, map-tile etc).89WEBP_HINT_LAST90} WebPImageHint;9192// Compression parameters.93struct WebPConfig {94int lossless; // Lossless encoding (0=lossy(default), 1=lossless).95float quality; // between 0 and 100. For lossy, 0 gives the smallest96// size and 100 the largest. For lossless, this97// parameter is the amount of effort put into the98// compression: 0 is the fastest but gives larger99// files compared to the slowest, but best, 100.100int method; // quality/speed trade-off (0=fast, 6=slower-better)101102WebPImageHint image_hint; // Hint for image type (lossless only for now).103104int target_size; // if non-zero, set the desired target size in bytes.105// Takes precedence over the 'compression' parameter.106float target_PSNR; // if non-zero, specifies the minimal distortion to107// try to achieve. Takes precedence over target_size.108int segments; // maximum number of segments to use, in [1..4]109int sns_strength; // Spatial Noise Shaping. 0=off, 100=maximum.110int filter_strength; // range: [0 = off .. 100 = strongest]111int filter_sharpness; // range: [0 = off .. 7 = least sharp]112int filter_type; // filtering type: 0 = simple, 1 = strong (only used113// if filter_strength > 0 or autofilter > 0)114int autofilter; // Auto adjust filter's strength [0 = off, 1 = on]115int alpha_compression; // Algorithm for encoding the alpha plane (0 = none,116// 1 = compressed with WebP lossless). Default is 1.117int alpha_filtering; // Predictive filtering method for alpha plane.118// 0: none, 1: fast, 2: best. Default if 1.119int alpha_quality; // Between 0 (smallest size) and 100 (lossless).120// Default is 100.121int pass; // number of entropy-analysis passes (in [1..10]).122123int show_compressed; // if true, export the compressed picture back.124// In-loop filtering is not applied.125int preprocessing; // preprocessing filter:126// 0=none, 1=segment-smooth, 2=pseudo-random dithering127int partitions; // log2(number of token partitions) in [0..3]. Default128// is set to 0 for easier progressive decoding.129int partition_limit; // quality degradation allowed to fit the 512k limit130// on prediction modes coding (0: no degradation,131// 100: maximum possible degradation).132int emulate_jpeg_size; // If true, compression parameters will be remapped133// to better match the expected output size from134// JPEG compression. Generally, the output size will135// be similar but the degradation will be lower.136int thread_level; // If non-zero, try and use multi-threaded encoding.137int low_memory; // If set, reduce memory usage (but increase CPU use).138139int near_lossless; // Near lossless encoding [0 = max loss .. 100 = off140// (default)].141int exact; // if non-zero, preserve the exact RGB values under142// transparent area. Otherwise, discard this invisible143// RGB information for better compression. The default144// value is 0.145146int use_delta_palette; // reserved for future lossless feature147int use_sharp_yuv; // if needed, use sharp (and slow) RGB->YUV conversion148149uint32_t pad[2]; // padding for later use150};151152// Enumerate some predefined settings for WebPConfig, depending on the type153// of source picture. These presets are used when calling WebPConfigPreset().154typedef enum WebPPreset {155WEBP_PRESET_DEFAULT = 0, // default preset.156WEBP_PRESET_PICTURE, // digital picture, like portrait, inner shot157WEBP_PRESET_PHOTO, // outdoor photograph, with natural lighting158WEBP_PRESET_DRAWING, // hand or line drawing, with high-contrast details159WEBP_PRESET_ICON, // small-sized colorful images160WEBP_PRESET_TEXT // text-like161} WebPPreset;162163// Internal, version-checked, entry point164WEBP_EXTERN int WebPConfigInitInternal(WebPConfig*, WebPPreset, float, int);165166// Should always be called, to initialize a fresh WebPConfig structure before167// modification. Returns false in case of version mismatch. WebPConfigInit()168// must have succeeded before using the 'config' object.169// Note that the default values are lossless=0 and quality=75.170static WEBP_INLINE int WebPConfigInit(WebPConfig* config) {171return WebPConfigInitInternal(config, WEBP_PRESET_DEFAULT, 75.f,172WEBP_ENCODER_ABI_VERSION);173}174175// This function will initialize the configuration according to a predefined176// set of parameters (referred to by 'preset') and a given quality factor.177// This function can be called as a replacement to WebPConfigInit(). Will178// return false in case of error.179static WEBP_INLINE int WebPConfigPreset(WebPConfig* config,180WebPPreset preset, float quality) {181return WebPConfigInitInternal(config, preset, quality,182WEBP_ENCODER_ABI_VERSION);183}184185// Activate the lossless compression mode with the desired efficiency level186// between 0 (fastest, lowest compression) and 9 (slower, best compression).187// A good default level is '6', providing a fair tradeoff between compression188// speed and final compressed size.189// This function will overwrite several fields from config: 'method', 'quality'190// and 'lossless'. Returns false in case of parameter error.191WEBP_EXTERN int WebPConfigLosslessPreset(WebPConfig* config, int level);192193// Returns true if 'config' is non-NULL and all configuration parameters are194// within their valid ranges.195WEBP_EXTERN int WebPValidateConfig(const WebPConfig* config);196197//------------------------------------------------------------------------------198// Input / Output199// Structure for storing auxiliary statistics.200201struct WebPAuxStats {202int coded_size; // final size203204float PSNR[5]; // peak-signal-to-noise ratio for Y/U/V/All/Alpha205int block_count[3]; // number of intra4/intra16/skipped macroblocks206int header_bytes[2]; // approximate number of bytes spent for header207// and mode-partition #0208int residual_bytes[3][4]; // approximate number of bytes spent for209// DC/AC/uv coefficients for each (0..3) segments.210int segment_size[4]; // number of macroblocks in each segments211int segment_quant[4]; // quantizer values for each segments212int segment_level[4]; // filtering strength for each segments [0..63]213214int alpha_data_size; // size of the transparency data215int layer_data_size; // size of the enhancement layer data216217// lossless encoder statistics218uint32_t lossless_features; // bit0:predictor bit1:cross-color transform219// bit2:subtract-green bit3:color indexing220int histogram_bits; // number of precision bits of histogram221int transform_bits; // precision bits for transform222int cache_bits; // number of bits for color cache lookup223int palette_size; // number of color in palette, if used224int lossless_size; // final lossless size225int lossless_hdr_size; // lossless header (transform, huffman etc) size226int lossless_data_size; // lossless image data size227228uint32_t pad[2]; // padding for later use229};230231// Signature for output function. Should return true if writing was successful.232// data/data_size is the segment of data to write, and 'picture' is for233// reference (and so one can make use of picture->custom_ptr).234typedef int (*WebPWriterFunction)(const uint8_t* data, size_t data_size,235const WebPPicture* picture);236237// WebPMemoryWrite: a special WebPWriterFunction that writes to memory using238// the following WebPMemoryWriter object (to be set as a custom_ptr).239struct WebPMemoryWriter {240uint8_t* mem; // final buffer (of size 'max_size', larger than 'size').241size_t size; // final size242size_t max_size; // total capacity243uint32_t pad[1]; // padding for later use244};245246// The following must be called first before any use.247WEBP_EXTERN void WebPMemoryWriterInit(WebPMemoryWriter* writer);248249// The following must be called to deallocate writer->mem memory. The 'writer'250// object itself is not deallocated.251WEBP_EXTERN void WebPMemoryWriterClear(WebPMemoryWriter* writer);252// The custom writer to be used with WebPMemoryWriter as custom_ptr. Upon253// completion, writer.mem and writer.size will hold the coded data.254// writer.mem must be freed by calling WebPMemoryWriterClear.255WEBP_EXTERN int WebPMemoryWrite(const uint8_t* data, size_t data_size,256const WebPPicture* picture);257258// Progress hook, called from time to time to report progress. It can return259// false to request an abort of the encoding process, or true otherwise if260// everything is OK.261typedef int (*WebPProgressHook)(int percent, const WebPPicture* picture);262263// Color spaces.264typedef enum WebPEncCSP {265// chroma sampling266WEBP_YUV420 = 0, // 4:2:0267WEBP_YUV420A = 4, // alpha channel variant268WEBP_CSP_UV_MASK = 3, // bit-mask to get the UV sampling factors269WEBP_CSP_ALPHA_BIT = 4 // bit that is set if alpha is present270} WebPEncCSP;271272// Encoding error conditions.273typedef enum WebPEncodingError {274VP8_ENC_OK = 0,275VP8_ENC_ERROR_OUT_OF_MEMORY, // memory error allocating objects276VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY, // memory error while flushing bits277VP8_ENC_ERROR_NULL_PARAMETER, // a pointer parameter is NULL278VP8_ENC_ERROR_INVALID_CONFIGURATION, // configuration is invalid279VP8_ENC_ERROR_BAD_DIMENSION, // picture has invalid width/height280VP8_ENC_ERROR_PARTITION0_OVERFLOW, // partition is bigger than 512k281VP8_ENC_ERROR_PARTITION_OVERFLOW, // partition is bigger than 16M282VP8_ENC_ERROR_BAD_WRITE, // error while flushing bytes283VP8_ENC_ERROR_FILE_TOO_BIG, // file is bigger than 4G284VP8_ENC_ERROR_USER_ABORT, // abort request by user285VP8_ENC_ERROR_LAST // list terminator. always last.286} WebPEncodingError;287288// maximum width/height allowed (inclusive), in pixels289#define WEBP_MAX_DIMENSION 16383290291// Main exchange structure (input samples, output bytes, statistics)292struct WebPPicture {293// INPUT294//////////////295// Main flag for encoder selecting between ARGB or YUV input.296// It is recommended to use ARGB input (*argb, argb_stride) for lossless297// compression, and YUV input (*y, *u, *v, etc.) for lossy compression298// since these are the respective native colorspace for these formats.299int use_argb;300301// YUV input (mostly used for input to lossy compression)302WebPEncCSP colorspace; // colorspace: should be YUV420 for now (=Y'CbCr).303int width, height; // dimensions (less or equal to WEBP_MAX_DIMENSION)304uint8_t *y, *u, *v; // pointers to luma/chroma planes.305int y_stride, uv_stride; // luma/chroma strides.306uint8_t* a; // pointer to the alpha plane307int a_stride; // stride of the alpha plane308uint32_t pad1[2]; // padding for later use309310// ARGB input (mostly used for input to lossless compression)311uint32_t* argb; // Pointer to argb (32 bit) plane.312int argb_stride; // This is stride in pixels units, not bytes.313uint32_t pad2[3]; // padding for later use314315// OUTPUT316///////////////317// Byte-emission hook, to store compressed bytes as they are ready.318WebPWriterFunction writer; // can be NULL319void* custom_ptr; // can be used by the writer.320321// map for extra information (only for lossy compression mode)322int extra_info_type; // 1: intra type, 2: segment, 3: quant323// 4: intra-16 prediction mode,324// 5: chroma prediction mode,325// 6: bit cost, 7: distortion326uint8_t* extra_info; // if not NULL, points to an array of size327// ((width + 15) / 16) * ((height + 15) / 16) that328// will be filled with a macroblock map, depending329// on extra_info_type.330331// STATS AND REPORTS332///////////////////////////333// Pointer to side statistics (updated only if not NULL)334WebPAuxStats* stats;335336// Error code for the latest error encountered during encoding337WebPEncodingError error_code;338339// If not NULL, report progress during encoding.340WebPProgressHook progress_hook;341342void* user_data; // this field is free to be set to any value and343// used during callbacks (like progress-report e.g.).344345uint32_t pad3[3]; // padding for later use346347// Unused for now348uint8_t *pad4, *pad5;349uint32_t pad6[8]; // padding for later use350351// PRIVATE FIELDS352////////////////////353void* memory_; // row chunk of memory for yuva planes354void* memory_argb_; // and for argb too.355void* pad7[2]; // padding for later use356};357358// Internal, version-checked, entry point359WEBP_EXTERN int WebPPictureInitInternal(WebPPicture*, int);360361// Should always be called, to initialize the structure. Returns false in case362// of version mismatch. WebPPictureInit() must have succeeded before using the363// 'picture' object.364// Note that, by default, use_argb is false and colorspace is WEBP_YUV420.365static WEBP_INLINE int WebPPictureInit(WebPPicture* picture) {366return WebPPictureInitInternal(picture, WEBP_ENCODER_ABI_VERSION);367}368369//------------------------------------------------------------------------------370// WebPPicture utils371372// Convenience allocation / deallocation based on picture->width/height:373// Allocate y/u/v buffers as per colorspace/width/height specification.374// Note! This function will free the previous buffer if needed.375// Returns false in case of memory error.376WEBP_EXTERN int WebPPictureAlloc(WebPPicture* picture);377378// Release the memory allocated by WebPPictureAlloc() or WebPPictureImport*().379// Note that this function does _not_ free the memory used by the 'picture'380// object itself.381// Besides memory (which is reclaimed) all other fields of 'picture' are382// preserved.383WEBP_EXTERN void WebPPictureFree(WebPPicture* picture);384385// Copy the pixels of *src into *dst, using WebPPictureAlloc. Upon return, *dst386// will fully own the copied pixels (this is not a view). The 'dst' picture need387// not be initialized as its content is overwritten.388// Returns false in case of memory allocation error.389WEBP_EXTERN int WebPPictureCopy(const WebPPicture* src, WebPPicture* dst);390391// Compute the single distortion for packed planes of samples.392// 'src' will be compared to 'ref', and the raw distortion stored into393// '*distortion'. The refined metric (log(MSE), log(1 - ssim),...' will be394// stored in '*result'.395// 'x_step' is the horizontal stride (in bytes) between samples.396// 'src/ref_stride' is the byte distance between rows.397// Returns false in case of error (bad parameter, memory allocation error, ...).398WEBP_EXTERN int WebPPlaneDistortion(const uint8_t* src, size_t src_stride,399const uint8_t* ref, size_t ref_stride,400int width, int height,401size_t x_step,402int type, // 0 = PSNR, 1 = SSIM, 2 = LSIM403float* distortion, float* result);404405// Compute PSNR, SSIM or LSIM distortion metric between two pictures. Results406// are in dB, stored in result[] in the B/G/R/A/All order. The distortion is407// always performed using ARGB samples. Hence if the input is YUV(A), the408// picture will be internally converted to ARGB (just for the measurement).409// Warning: this function is rather CPU-intensive.410WEBP_EXTERN int WebPPictureDistortion(411const WebPPicture* src, const WebPPicture* ref,412int metric_type, // 0 = PSNR, 1 = SSIM, 2 = LSIM413float result[5]);414415// self-crops a picture to the rectangle defined by top/left/width/height.416// Returns false in case of memory allocation error, or if the rectangle is417// outside of the source picture.418// The rectangle for the view is defined by the top-left corner pixel419// coordinates (left, top) as well as its width and height. This rectangle420// must be fully be comprised inside the 'src' source picture. If the source421// picture uses the YUV420 colorspace, the top and left coordinates will be422// snapped to even values.423WEBP_EXTERN int WebPPictureCrop(WebPPicture* picture,424int left, int top, int width, int height);425426// Extracts a view from 'src' picture into 'dst'. The rectangle for the view427// is defined by the top-left corner pixel coordinates (left, top) as well428// as its width and height. This rectangle must be fully be comprised inside429// the 'src' source picture. If the source picture uses the YUV420 colorspace,430// the top and left coordinates will be snapped to even values.431// Picture 'src' must out-live 'dst' picture. Self-extraction of view is allowed432// ('src' equal to 'dst') as a mean of fast-cropping (but note that doing so,433// the original dimension will be lost). Picture 'dst' need not be initialized434// with WebPPictureInit() if it is different from 'src', since its content will435// be overwritten.436// Returns false in case of memory allocation error or invalid parameters.437WEBP_EXTERN int WebPPictureView(const WebPPicture* src,438int left, int top, int width, int height,439WebPPicture* dst);440441// Returns true if the 'picture' is actually a view and therefore does442// not own the memory for pixels.443WEBP_EXTERN int WebPPictureIsView(const WebPPicture* picture);444445// Rescale a picture to new dimension width x height.446// If either 'width' or 'height' (but not both) is 0 the corresponding447// dimension will be calculated preserving the aspect ratio.448// No gamma correction is applied.449// Returns false in case of error (invalid parameter or insufficient memory).450WEBP_EXTERN int WebPPictureRescale(WebPPicture* pic, int width, int height);451452// Colorspace conversion function to import RGB samples.453// Previous buffer will be free'd, if any.454// *rgb buffer should have a size of at least height * rgb_stride.455// Returns false in case of memory error.456WEBP_EXTERN int WebPPictureImportRGB(457WebPPicture* picture, const uint8_t* rgb, int rgb_stride);458// Same, but for RGBA buffer.459WEBP_EXTERN int WebPPictureImportRGBA(460WebPPicture* picture, const uint8_t* rgba, int rgba_stride);461// Same, but for RGBA buffer. Imports the RGB direct from the 32-bit format462// input buffer ignoring the alpha channel. Avoids needing to copy the data463// to a temporary 24-bit RGB buffer to import the RGB only.464WEBP_EXTERN int WebPPictureImportRGBX(465WebPPicture* picture, const uint8_t* rgbx, int rgbx_stride);466467// Variants of the above, but taking BGR(A|X) input.468WEBP_EXTERN int WebPPictureImportBGR(469WebPPicture* picture, const uint8_t* bgr, int bgr_stride);470WEBP_EXTERN int WebPPictureImportBGRA(471WebPPicture* picture, const uint8_t* bgra, int bgra_stride);472WEBP_EXTERN int WebPPictureImportBGRX(473WebPPicture* picture, const uint8_t* bgrx, int bgrx_stride);474475// Converts picture->argb data to the YUV420A format. The 'colorspace'476// parameter is deprecated and should be equal to WEBP_YUV420.477// Upon return, picture->use_argb is set to false. The presence of real478// non-opaque transparent values is detected, and 'colorspace' will be479// adjusted accordingly. Note that this method is lossy.480// Returns false in case of error.481WEBP_EXTERN int WebPPictureARGBToYUVA(WebPPicture* picture,482WebPEncCSP /*colorspace = WEBP_YUV420*/);483484// Same as WebPPictureARGBToYUVA(), but the conversion is done using485// pseudo-random dithering with a strength 'dithering' between486// 0.0 (no dithering) and 1.0 (maximum dithering). This is useful487// for photographic picture.488WEBP_EXTERN int WebPPictureARGBToYUVADithered(489WebPPicture* picture, WebPEncCSP colorspace, float dithering);490491// Performs 'sharp' RGBA->YUVA420 downsampling and colorspace conversion.492// Downsampling is handled with extra care in case of color clipping. This493// method is roughly 2x slower than WebPPictureARGBToYUVA() but produces better494// and sharper YUV representation.495// Returns false in case of error.496WEBP_EXTERN int WebPPictureSharpARGBToYUVA(WebPPicture* picture);497// kept for backward compatibility:498WEBP_EXTERN int WebPPictureSmartARGBToYUVA(WebPPicture* picture);499500// Converts picture->yuv to picture->argb and sets picture->use_argb to true.501// The input format must be YUV_420 or YUV_420A. The conversion from YUV420 to502// ARGB incurs a small loss too.503// Note that the use of this colorspace is discouraged if one has access to the504// raw ARGB samples, since using YUV420 is comparatively lossy.505// Returns false in case of error.506WEBP_EXTERN int WebPPictureYUVAToARGB(WebPPicture* picture);507508// Helper function: given a width x height plane of RGBA or YUV(A) samples509// clean-up or smoothen the YUV or RGB samples under fully transparent area,510// to help compressibility (no guarantee, though).511WEBP_EXTERN void WebPCleanupTransparentArea(WebPPicture* picture);512513// Scan the picture 'picture' for the presence of non fully opaque alpha values.514// Returns true in such case. Otherwise returns false (indicating that the515// alpha plane can be ignored altogether e.g.).516WEBP_EXTERN int WebPPictureHasTransparency(const WebPPicture* picture);517518// Remove the transparency information (if present) by blending the color with519// the background color 'background_rgb' (specified as 24bit RGB triplet).520// After this call, all alpha values are reset to 0xff.521WEBP_EXTERN void WebPBlendAlpha(WebPPicture* pic, uint32_t background_rgb);522523//------------------------------------------------------------------------------524// Main call525526// Main encoding call, after config and picture have been initialized.527// 'picture' must be less than 16384x16384 in dimension (cf WEBP_MAX_DIMENSION),528// and the 'config' object must be a valid one.529// Returns false in case of error, true otherwise.530// In case of error, picture->error_code is updated accordingly.531// 'picture' can hold the source samples in both YUV(A) or ARGB input, depending532// on the value of 'picture->use_argb'. It is highly recommended to use533// the former for lossy encoding, and the latter for lossless encoding534// (when config.lossless is true). Automatic conversion from one format to535// another is provided but they both incur some loss.536WEBP_EXTERN int WebPEncode(const WebPConfig* config, WebPPicture* picture);537538//------------------------------------------------------------------------------539540#ifdef __cplusplus541} // extern "C"542#endif543544#endif /* WEBP_WEBP_ENCODE_H_ */545546547